Requirements that express robustness against functional changes and extensions are called non-functional, while the need for the functionality itself is expressed in functional requirements. Functionality in software works compositionally; that is, it is created by combining components that realize functionality partially. This partial functionality offered by a component is not affected by making such compositions. So one can separate functional concerns. However such compositionality does not work for non-functional aspects like performance and the ‘-ilities’ (scalability, reusability, extensibility etc.). For example, if we have two independent components that meet a deadline when individually deployed, it is far from certain that they meet the same deadline when deployed together. Meeting a deadline cannot be localized (e.g. in a single class) and requires the application of very different techniques than the realization of functional properties. A simple divide-and-conquer approach is ineffective. Many authors define system properties that are non-localizable as architectural.
This course will introduce and explore these main ideas behind object-oriented development and will discussed how this technique can be used to fulfill the architectural or non-functional requirements. The UML modeling language is used as the main tool.
This course is naturally divided into two interlocking parts: object-oriented analysis, and object-oriented design. During analysis an object-oriented behavior specification of the system is created. During the design process this specification is augmented with the desired non-functional system properties. Thus, analysis captures the functional requirements and produces a (possibly executable) functional specification, while the design step captures and realizes the non-functional requirements.
Object-oriented programming is a form of modular programming with the class as basic building block. Classes can be obtained from the object types that we find in the problem domain: the objects in the machine to be controlled or in the business process to be supported. Object orientation contrasts with (older) procedural approaches. In general it is easier for people to think in terms of objects than it is to think procedurally.
A class is a software module that offers access to its data, also called attributes, via operations. This promotes the idea of "keeping data in one place" and information hiding which can help to make software less sensitive to changes in data representation and extensions. When properly applied, an object-oriented approach leads to better localization of software changes compared to the traditional procedural way of working.
The analysis process starts with the definition of so called use cases, scenario-like descriptions of user-system-interactions. In addition, the system structure is captured as a simple class hierarchy. Subsequently, the use cases are analyzed and realized using UML sequence diagrams. This helps to allocate behavior to the system objects in such a way that the interactions as specified in the use cases emerge. This behavior allocation results in discovery of operations on classes. The final step is to refine the behavior of individual classes in UML state machine descriptions, (at most) one state machine per class.
During analysis, the system under development is modeled rather than the software under development. This is important, as it leads to the localization of system parameters and associated behavior and helps to promote encapsulation. In this manner, information hiding and encapsulation are naturally built in to the object-oriented model.
A functionally correct (partial) analysis model is a good starting point for design. The design part of the course is based on the 4+1 Views of architecture from P. Krugten: the Logical, Process, Component and Deployment Views. These views were introduced to separate the addressed non-functional aspects and the employed techniques for their realization.
A major architectural technique used in the logical view is modularity. Many trainees in this course believe that modularity itself is a requirement. The course advocates to look at this differently. Modularity is always there for the purpose of some other, higher goal (e.g. reuse, extensibility, maintainability). Thus changing the software structure is viewed as a means to achieve the desired non-functional properties. There are two major ways of changing software structure: (1) code refactoring and (2) the application of design patterns. Both these techniques can be applied in a way that functionality is preserved.
During the process view one addresses issues like performance scalability, correctness (absence of deadlock and race conditions). It is shown how the behavior descriptions in the form of UML state machines yield concurrency (multi-threading) that is natural to the problem, the system behavior. Threading can be refactored in the process view very much like transformation can help refactor classes and their structure in the logical view. Some simple transformations based on thread cohesion arguments are discussed and illustrated.
Finally, the components and deployment views are very briefly discussed. These views address the way executable software building blocks are offered for deployment on an execution platform. Typical issues are scalability and software evolution. The focus here is mainly on notations, but also some issues with component interfaces are briefly addressed.
The course material contains a good number of case studies used as examples and exercises. These case studies have been worked out in detail, from requirements via models to executable (Java) implementations. The last step is performed as “proof of concept”. Trainees will receive these case studies on USB stick.
This course is particularly intended for software developers that recognize the issues mentioned above and feel that they would benefit from a clear and cohesive treatment. The clear learning goals and the many exercises will help to consolidate the presented theory and techniques.
A natural sequel of this training is “Design Patterns and Emergent Architecture”. It is recommended that this course is attended first.