Computer system consists of two major components. 1. Hardware 2. Software Hardware is the name given to physical machines whereas software is the set of logical instructions that direct the hardware to achieve a particular task. Both the components are dependent on each other. One is useless in the absence of other.
Vendors usually design the Hardware and conceptually it fairly matches with the Hardware of other vendors. on the other hand software designs, most of the time, are custom design and various methodology are adopted in its design. In the ongoing paragraphs the process of software design has been discussed. GENERAL SOFTWARE DESIGN PROCESS A general model of a software deign is a directed graph. Nodes in this graph represent enmities in the design, such as processes, functions or types, and links represent relation between these design entities. The target of the design process is the creation of such a graph without inconsistencies and where all of the relationships between design entities are legal.
Software designers do not arrive at a finished design graph immediately. The design process involves adding formality as design progresses, with constant backtracking to correct earlier, less formal, designs. The designer starts with a very informal picture of the design and refines it by adding information to make the design more formal. -2- The relationship between design and specification is a close one. Although the process of setting out a requirement specification as the basis of a contract is a separate activity, formalizing that specification may be part of the design process. In practice, the designer iterates between specification and design.
The design process involves describing the system at a number of different levels of abstraction. As a design is decomposed, errors and omissions in earlier stages are discovered. These fee back to allow earlier design stages to be refined. It is common to begin the next stage before a stage is finished simply to get feedback from the refinement process. These stages are fairly arbitrary but make the design process visible and thus allow it to be managed. A specification is the output of each activity.
This specification may be an abstract, formal specification, which is produced to clarify the requirements, or it may be a specification of show part of the system is to be realised. As the design process continues, more and more detail is added to the specification. The ultimate outputs are specifications of algorithms and data structures, which are used as a basis for system implementation. The design process activities go on in parallel with different design products developed to different levels of detail in the course of the design process.
However, the activities shown below are all essential in the deign of large software systems: 1) Architectural design: The sub-systems making up the overall system and their relationships are identified and documented. 2) Abstract specification: For each sub-system, and abstract specification of the services it provides and the constraints under which it must operate is produced. -3- 3) Interface design: For each sub-system, its interface with other sub systems is designed and documented. This interface specification must be unambiguous as it allows the sub-system to be used without knowledge of the subsystem operation. 4) Component design: The services provided by a sub-system are partitioned across the components in that sub-system. 5) Data Structure design: The data structure used in the system implementation are designed in detail and specified.
6) Algorithm design: The algorithms used to provide services are designed in detail and specified. This process is repeated for each sub-system until the components identified can be mapped directly into programming language components such as packages, procedures or functions. A widely recommended approach to design is a top-down approach where the problem is recursively partitioned into sub-problems until tractable sub-problems are identified. The general form of the design, which usually emerges from such a design process, is approximately hierarchical.
Cross-links in the graph emerge at lower levels of the design tree as designers identify possibilities for reuse. In fact, it is unusual for large systems to be designed in manner, which is strictly top-down. Designers always use their previous design knowledge in the design process. They do not need to decompose all abstractions as they may be aware exactly how one part of the design can be built. They might therefore return to that part. Indeed, project planning may require difficult parts of the design to be tackled first so that management can make more informed estimates of the system development time.
-4- Top-down design was proposed in conjunction with functional decomposition and it is a valid approach where design components are rightly coupled. However, when an object-oriented approach to design is adopted and many existing objects are available for reuse, top-down design so less useful. The designer uses existing objects as a design framework and builds the design out from them; there is no concept of a single 'top' or of all objects existing in a single object hierarchy. Design methods In many organisations, software design is still an ad hoc process. Given a set of requirements, usually in natural language, an informal design is prepared. Coding commences and the design is modified as the system is implemented.
When the implementation stage is complete, the design has usually changed so much from its initial specification that the original design document is a totally inadequate description of the system. A more methodical approach to software design is proposed by 'structured methods' which are sets of notations and guidelines about how to create a software design. Structured methods have been applied successfully in many large projects. They can deliver significant cost reductions because they use standard notations and ensure that designs follow a standard form. The use of structured methods normally involves producing large amounts of diagrammatic design documentation.
-5- Although there are a large number of methods, they have much in common and usually support some or all of the following views of a system: 1) A data flow view where the system is modelled using the data transformations, which take place as it, is processed. 2) An entity relation view, which is used to describe the logical data, structures being used. 3) A structural view where the system components and their interactions are documented. Particular methods supplement these with other system models such as state transition diagrams, entity life histories, which show how each entity is transformed as it is processed, and so on. Most methods suggest that a centralised repository for system information (a data dictionary) would be used but this is only really feasible with automated tool support. Because of the variety of methods and the fact that no one method is demonstrably superior to another.
A mathematical method (such as the method for long division) is a strategy which, if adopted, will always lead to the same result. The term 'structured methods's ugg ests, therefore, that designers should normally generate similar designs for the same specification. In practice, the guidance given by the methods is informal so this situation is unlikely. These 'methods' are really standard notations and embodiments of good practice.
By following these methods and applying guidelines, a reasonable design should emerge but designer creativity is still required to decide on the system -6- decomposition and to ensure that the design adequately captures the system specification. Design description A software design is a model of real-world system, which has many participating entities and relationships. Different engineers use this design in different ways. It must act as a basis for detailed implementation, it serves as communication medium between the designers of sub-systems, it provides information to system maintainers about the original intentions of the system designers, and so on. This means that it must be possible to view a design at a number of different levels of abstraction. There are three types of notation, which are widely used for design documentation: 1) Graphical notations: These are used to display the relationships between the Components making up the design and to relate the design to the real-world system it is modelling.
A graphical view of a design is an abstract view and is most useful for giving an overall picture of the system. 2) Program description languages: These languages (Pdas) use control and structuring constructs based on programming language constructs but also allow explanatory text and (sometimes) additional types of statement to be used. These allow the intention of the designer to be expressed rather than the details of how the design is to be implemented. 3) Informal Text: Much of the information that is associated with a design cannot be expressed formally. Information about design -7- rationale or non-functional considerations must be expressed using natural language text. Generally, all of these different notations would be used in describing a system design.
The architecture and the logical data design should be described graphically supplemented by design rationale and further informal or formal descriptive text. The interface design, the detailed data structure design and the algorithm design are best described as a PDL. Design strategies Until relatively recently, most software was developed according to a design strategy which involved decomposing the design into functional components with system state information held in a shared data area. It is only since the mid-1980 s that this alternative, object-oriented design, has been widely adopted. These two design strategies may be summarised as follows: 1) Functional design: The system is designed from a functional viewpoint, starting with a high level view and progressively refining this into a more detailed design. The system state is centralised and shared between the functions operating on that state.
Structured design and step-wise refinement exemplify this strategy. Methods such as Jackson structured programming and the Warner-Orr method are techniques of functional decomposition where the structure of the data is used to determine the functional structure used to process that data. 2) Object-oriented design: The system is viewed as a collection of object rather than as functions. The system is decentralised and each object manages its own state information. Objects have a set -8- of attributes defining their state and operations, which act on these attributes. Objects are usually members of an object class whose definition defines attributes and operations of class members.
These may be inherited from one or more super-classes so that a class definition need merely set out the differences between that class and its super-classes. Conceptually, objects communicate by exchanging messages; in practice, most object communication is achieved by an object calling a procedure associated with another object. Top-down functional decomposition has been widely used for both small-scale and large-scale projects in diverse application areas. Object-oriented design is a more recent development, which encourages the production of system composed in independent, interacting components. To illustrate the difference between functional and object-oriented approaches to software design, consider the structure of a compiler. It may be viewed as a set of functional transformations with information being passed from one function to another.
An alternative, object-oriented view of the structure of compiler would be the objects manipulated by the compiler are central with transformation functions associated with object communications. Enthusiasts for particular design techniques sometimes suggest that their favourite technique is generally applicable and that other techniques should not be used. In fact, large software systems are such complex entities that different approaches might be used at some stage in the design of different parts of the system. There is no best design strategy for large projects. Functional and object-oriented approaches are complementary stages in the design process. The pragmatic software engineer selects the most appropriate approach for each stage in the design process.
-9- TBC To illustrate this, consider the software systems, which might be part of a modern civil aircraft. Some of these might be: The navigation system. The radar system. The external communications system.
The engine control system. Our natural high-level view of the overall software system is as a set of objects (sub-systems) rather than as a set of functions. Thus at abstract design levels, an object-oriented approach is appropriate. When the system is examined in more detail, its natural description is as a set of interacting functions rather than objects. For example, some of these functions might be: Display Track (radar sub-system). Compensate for WindSpeed (navigation sub-system).
Reduce Power (engine control sub-system). Indicate Emergency (instrument sub-system). LockontoFrequency (communications sub-system). This functional view may be taken by the requirements definition. This can be converted to an object-oriented view but system validation may be difficult because there is not a simple correspondence between design components and requirements definitions. A single logical function in the requirements definition may be implemented as a sequence of object interactions.
As the system design is further decomposed, an object-oriented view may again become the natural way to view the system. At the detailed design stage, the objects manipulated might be -10- Theenginestatus, The aircraft position, Theantimeter, Theradiobeacon, and so on. Thus an object-oriented approach to the lower levels of the system deign is likely to be effective. In summary, an object-oriented approach to software design seems to be the most natural at the highest and lowest levels of system design. At these levels, an object-oriented approach leads to the production of independent components which are usually more maintainable than functional components. TBC END Concurrent systems design Many software systems, particularly embedded real-time systems, are structured as a set of parallel communicating processes.
Indeed, it is sometimes suggested that this structure of parallel processes is a natural and necessary approach for real-time systems construction. Both object-oriented and function-oriented designs can be realised as sequential or concurrent programs. Indeed, structuring the design as a set of co-operating processes where each process maintains its own state is a half-way house between these two approaches to design. If no shared memory is used for process communication, the processes hide information in the same way as objects. Embedded systems must often perform to strict time constraints and, where hardware is relatively slow, only a multiple process / multiple processor approach may be able to provide the necessary performance. However, with fast processors, it may not be necessary to implement embedded systems as parallel processes.
A sequential system, which uses polling to interrogate and control hardware components, may provide adequate performance. -11- The advantage of avoiding a parallel systems design is that sequential programs are easier to design, implement, verify and test that parallel systems design is that sequential programs are easier to design implement, verify and test than parallel systems. Time dependencies between processes are hard to formalism, control and verify. The deign process should therefore be considered as a two-stage activity: 1) Identify the logical design structure, namely the component of a system and their interrelationships. Either a functional or an object-oriented view may be used. 2) Realise this structure in a form which can be executed This latter stage is sometimes considered detailed design and sometimes programming.
Decisions on parallelism should be made at this stage rather than preconceived at earlier stages in the design process. Design quality There is no definitive way of establishing what is meant by a good design. Depending on the application and project requirements, a good design might be a design, which allows efficient code to be produced; it might be a minimal design where the implementation is as compact as possible; or it might be the most maintainable design. This latter criterion is the criterion of goodness used here. A maintainable design can be readily adapted to modify existing functionality and add new functionality. The design should therefore be understandable and changes should be local in effect.
The components of the design should be cohesive, which means -12- that all parts of the component should have a close logical relationship. They should be loosely coupled. Coupling is a measure of the independence of components. The looser the coupling, the easier it is to adapt the design. Some work has been carried out to establish design quality metrics to establish whether or not a design is a good design. These have mostly been developed in conjunction with structured design methods.
Quality characteristics are equally applicable to object-oriented and function-oriented design. Because of the inherent nature of object-oriented designs, it is usually easier to achieve maintainable designs because information is concealed within objects. However, inheritance in object-oriented systems can compromise design quality. Cohesion The cohesion of a component is a measure of how well it fits together. A component should implement a single logical function or should implement a single logical entity. All of the parts of the component should contribute to this implementation.
If the component includes parts which are not directly related to its logical function (for example, if it is a grouping of unrelated operations which are executed at the same time) it has a low degree of cohesion. There are seven levels of cohesion, which, in order of increasing strength of cohesion are given below: - Coincidental cohesion: The parts of a component are not -13- related but simply bundled into a single component. - Logical association: Components which perform similar functions such as input, error handling, etc. are put together in a single component. - Temporal cohesion: All of the components which are activated at a single time, such as start up or shut down, are brought together. - Procedural cohesion: The elements in a component make up a single control sequence.
- Communicational cohesion: All of the elements of a component operate on the same input data or produce the same output data. - Sequential cohesion: The output from one element in the component serves as input for some other element. - Functional cohesion: Each part of the component is necessary for the execution of a single function. These cohesion classes are not strictly defined and Constantine and Your don illustrate each by example. It is not always easy to decide under what cohesion category a unit should be classed. It is not always easy to decide under what cohesion category a unit should be classed.
It is obvious that the most cohesive from of unit is the function. However, a high degree of cohesion is also a feature of object-oriented systems. Indeed, one of the principal advantages of this approach to design is that the objects making up the system are naturally cohesive. -14- A cohesive object is one where a single entity is represented and all of the operations on that entity are included with the object.
For example, an object representing a complied symbol table is cohesive if all of the functions such as 'Add a symbol', 'Search table', and so on, are included with the symbol table object. Thus, a further class of cohesion might be defined as follows: - Object cohesion: Each operation provides functionality which allows the attributes of the object to be modified, inspected or used as a basis for service provision. Cohesion is a desirable characteristic because it means that a unit represents a single part of the problem solution. Of It becomes necessary to change the system, that part exists in a single place and everything to do with it is encapsulated in a single unit.
There is no need to modify many components if a change has to be made. If functionality is provided in an object-oriented system using inheritance from super-classes, the cohesion of the object which inherits attributes and operations is reduced. It is no longer possible to consider that object as a separate unit. All super-classes also have to be inspected if the object's functionality is to be understood completely. System browsers which display object classes and their super- classes asist with this process but understanding a component which inherits attributes from a number of super-classes can be particularly complex. -15- Coupling Coupling is related to cohesion.
It is an indication of the strength of interconnections between program units. Highly coupled systems have strong interconnections, with program units dependent on each other. Loosely coupled systems are made up of units which are independent or almost independent. As a general rule, modules are tightly coupled if they make use of shared variables or if they interchange control information. This is known as common coupling and control coupling. Loose coupling is achieved by ensuring that, wherever possible, representation information is held within a component and that its data interface with other units is via its parameter list.
Other coupling problem arise when names are bound to values at an early stage in the development of the design. For example, if a program is concerned with tax computations and a tax rate of 30% is encoded as a number in the program, that program is coupled with the tax rate. Changes to the tax rate require changes to the program. If the program reads in the tax rate at run-time, it is easy to accommodate rate changes. Perhaps the principal advantage of object-oriented design is that the nature of objects leads to the creation of loosely coupled system. It is fundamental to object-oriented design that the representation of an object is concealed within that object and is not visible to external components.
The system does not have a shared state and any object can be -16- replaced by another object with the same interface. Inheritance in object-oriented systems, however, leads to a different from of coupling. Objects which inherit attributes and operations are coupled to their super-classes. Changes to the super-class must be made carefully as these changes propagate to all of the classes which inherit their characteristics.
Understandability Changing a design component implies that the person responsible for making the change understands the operation of the component. This understandability is related to a number of component characteristics: (1) Cohesion Can the component be understood without reference to other components (2) Naming Are the names used in the component meaningful Meaningful names are names which reflect the names of the realworld entities being modelled by the component. (3) Documentation Is the component documented so that the mapping between the real-world entities and the component is clear Is the rationale for that mapping documented (4) Complexity How complex are the algorithms used to implement the component High complexity implies many relationship between different parts of the design component and a complex logical structure which may involve deeply nested if-then-else statements. Complex components are hard to understand so the designer should strive for as simple as possible a component design.
Complexity affects understandability but -17- there are a number of other factors which influence the understandability, such as the data organization and the style in which the design is described. Complexity measures can only provide an indicator to the understandability of a component. Inheritance in an obect-oriented design affects its understandability. If inheritance is used to conceal design details, the design is easier to understand. If one the other hand, the use of inheritance requires the design reader to look at many different object classes in the inheritance hierarchy, the understandability of the design is reduced.
Adaptability If a design is to be maintained, it must be readily adaptable. Of course, this implies that its components should be loosely coupled. As well as this, however, adaptability means that the design should be well-documented, the component documentation should be readily understandable and consistent with the implementation, and that the implementation should be written in a readable way. An adaptable design should have a high level of visibility. There should be a clear relationship between the different level in the design.
It should be possible for a reader of the design to find related representations such as the structure chart representing a transformation on a data flow diagram. It should be easy to incorporate changes made to the design in all design documents. If this is not the case, changes made to a design description may not be included in -18- all related descriptions. The design documentation may become inconsistent. Later changes are more difficult to make (the component is less adaptable) because the modifier cannot rely on the consistency of design documentation. For optimum adaptability, a component should be self- contained.
A component may be loosely coupled in that it only cooperates with other components via message passing. This is not the same as being self-contained as the component may rely on other components, such as systems functions or error handling functions. Adaptations to the component may involve changing parts of the component which rely on external functions so the modifier must also consider the specification of these external functions. To be completely self-contained, a component should not use other components which are externally defined. However, this is contrary to good practice which suggests that existing components should be reused. Thus, some balance must be struck between the advantages of reusing components and the loss of component adaptability that this entails.
One of the principal advantages of inheritance in object-oriented systems is that components may be readily adapted. The adaptation mechanism does not rely on modifying the component but on creating a new component which inherits the attributes and operations of the original component. Only those attributes and operations which need; be; changed are modified. Components which rely on the base component are; not affected by the changes made. This simple adaptability is one reads on why object- oriented languages are so effective for rapid prototyping. However, for long lifetime systems, the problem with inheritance is that as more and more change are made, the -19- inheritance network becomes increasingly complex.
Functionality is often replicated at different points in the network and components are harder to understand. Experience of object-oriented programming has shown that the inheritance network must be periodically reviewed and restructured to reduce its complexity and functional duplication. Clearly, this adds to the costs of system change. KEY POINTS Design is a creative process.
Although methods and guidlines are helpful, judgement and flair on the part of the software engineer are still required to design a software system. The main design activities in the software process are architectural design, system specification, interface design, component design, data structure design and algorithm de sing. Functional decomposition involves considering system as a set of interacting functional units. Object-oriented decomposition consider the system as a set of objects where an object is an entity with state and functions to inspect and modify that state. A decision on whether a system should be implemented as a single sequential process or as a number of parallel process is a detailed design decision. The design process should partition the system into logical, intercating units which may be realized as either sequential or parallel components.
-20- The most important design quality attribute is maintainability. Maximizing cohesion in a component and minimizing the coupling between components is likely to lead to a maintainable design. The use of inheritance in obect-oriented systems can improve the quality of a design but may make the design more difficult to understand. Object-Oriented Design Object-Oriented Design strategy maximize information hiding and usually leads the systems with lower coupling and higher cohesion than the functional approach. Information hiding is a design strategy where as much information as possible is hidden within design components. The basic premise underlying information hiding is the notion that the binding of logical control and data structures to their implementation should be made as late as possible in the design process.
Communication through shared state information (global variables) is minimized, thus increasing the understandability of the design. The design is relatively easy to change as changes to a component should not have unforeseen side-effects on other components. Object-oriented design is based on information hiding. It differs from the functional approach to design in that it views a software system as a set of interacting objects, with their won private state, rater than as a set of function. -21- An object-oriented design is based on entities (object) which have a hidden state and operations on that state. The design is expressed in terms of services requested and provided by interacting objects.
The characteristics of an object-oriented design are: - Shared data areas are eliminated. Object communicate by exchanging message rather than sharing variables. This reduces overall system coupling as there is no possibility of unexpected modifications to shared information. - Object are independent entities that may readily be changed; because all state and representation information is held within the object itself.
No access and hence no deliberate or accidental use of this information by other objects is possible. Changes to the representation may be made without reference to other system object. - Object may be distributed and may execute either sequentially or in parallel. Decisions on parallelism need not be taken to an early stage of the design process.