Wednesday, August 15, 2007

Introduction to Software Design

Overview
Problems in Software Architectural Design
Function, Form, and Fabrication: The Vitruvian Triad
The Scope of Design
The Psychology and Philosophy of Design
General Methodology of Design
Summary



Overview
Higher-quality design, not just higher-quality development processes, is necessary in order to achieve a high-quality product. But what characterizes a higher-quality design, and how do we achieve it? And, more fundamentally, what characterizes an activity as design, and what is the product of design? This presents the fundamental methods of the software design process and establishes the scope of the architectural level of design. The same fundamental design principles and methods apply whether a software architect is analyzing the problem domain, specifying the function of an application to address the problem domain, or designing the structure or form of the software. They also apply when a software engineer is creating a detailed design (including coding) or testing an implementation or designing a development environment in which to create the code. A generalized method of design is presented.



The obstacles to achieving high-quality architectural design in software development are:

A lack of awareness of the importance of architectural design to software development

A lack of understanding of the role of the software architect

A widespread view that designing is an art form, not a technical activity

A lack of understanding of the design process

A lack of design experience in a development organization

Insufficient software architecture design methods and tools

A lack of understanding of how to evaluate designs

Poor communication among stakeholders

Most of these obstacles stem from ignorance around what software architecture and design are and why they are critical to the success of an application or other system development project. This ignorance results in an inability to effectively communicate what problems an application is really addressing and how a technical solution solves those problems.

The solution to the problem of inadequate design must address the obstacles to achieving adequate design. The solution involves the following:

Evangelizing the importance of software architecture

Improving software architecture education

Using architecture methods and tools






General Methodology of Design
In this section, we look at the general elements of a design method based on Pahl and Beitz (Pahl, 1996). Not all design methods include all of these elements, but these elements are present in all design methods:

Purposeful thinking

Analysis

Abstraction

Synthesis

General heuristics

Purposeful Thinking
Design requires systematic thinking, which separates design from routine tasks. Systematic, or discursive, techniques are not the opposite of creative techniques nor are they the opposite of subconscious, or intuitive, thought. Relying on intuition alone, however, is not a good design practice so we need to be more deliberate in our approach to design. A purely intuitive approach to design has several disadvantages: The right solution rarely comes at the right time, the results depend on the architect's skills and talents, and the solutions may be negatively influenced by preconceived ideas (also called fixation). Intuition can lead to good solutions but requires conscious and deliberate involvement with the problem. Discursive thought can stimulate intuitive thinking. Programmers experience this frequently. A programmer may spend hours or days struggling with some problem only to have the solution come to her while she is away from the computer, not even consciously thinking about the problem.

Design should be primarily discursive; that is, it should proceed deliberately in a stepwise fashion. Unconscious procedures can be transformed into deliberate and systematic methods through systematic rules, clear task formulation, and structured design procedures.

Errors are unavoidable so our processes must allow for this. Therefore the architect should analyze the design for errors or weak points in the early stages of development. Clearly defined requirements and problem statements help reduce the risk of design errors by minimizing the amount of guesswork that goes into the design process as well as minimizing the amount of rework that would otherwise be necessary. A discursive design approach helps reduce errors by enforcing systematic testing of design ideas and assumptions early in the development process. Fixed design ideas (assumptions) should be avoided and existing methods and tools should be adapted as necessary (don't let a given methodology artificially constrain you). The deliberate use of specific methods for failure or error identification should be used.

Creativity is inhibited or encouraged by different influences. Some techniques for encouraging creativity are:

Interrupt the activity to create incubation periods (but be careful; too many interruptions can be disruptive).

Apply different solution-finding methods.

Move from abstract to concrete ideas.

Find and collect information from design catalogues (such as design patterns).

Divide work among architecture team members.

Make realistic plans: Realistic planning is found to encourage motivation and creativity, while unrealistic planning is inhibiting.



Analysis



Analysis is the decomposition of complex systems into elements and their interrelationships, identifying essential distinctions, and discarding accidental distinctions. The activities of analysis include identification, definition, and structuring with the purpose of acquiring information about a subject that can be transformed into knowledge. Analytic methods are useful in all stages of software design, from requirements gathering to evaluating designs and technologies to implementation.

Formulating problems clearly and unambiguously, via analysis of an application domain, helps avoid many expensive design and implementation errors. Careful analysis and formulation of problems are two of the most important and effective tools a software architect has. All design methodologies have some analysis aspect. However, I find that many modern design methodologies tend to blur the distinction between analysis and design. Many object-oriented methodologies promote a seamless development concept where the problem or application domain is continuously transformed into a solution, for example, Object Modeling Technique (OMT). In practice, the analysis is rarely done or is not done adequately.

Structured analyses in software, such as the techniques of Gane and Sarson, Yourdon, DeMarco, Ward and Mellor, and the Structured Systems Analysis and Design Methodology (SSADM), are methods for formulating and structuring the problem. Structured analysis is a process where the problem is formulated in terms of data flows, as represented in data flow diagrams (DFDs) and in system state transitions as represented in state transition diagrams. These models emphasize a hierarchical structuring of the functions of a system.

Similarly, object-oriented analysis, such as the techniques of Jacobson, Booch, Rumbaugh (OMT), and Yourdon and Coad, are techniques for structuring the problem domain in terms of objects, their interrelationships, and their class hierarchies. Whereas structured analysis emphasizes a functional hierarchy, object orientation emphasizes a data hierarchy.




Abstraction
Through abstraction, we can infer more general and comprehensive relationships among the elements of our problem. Abstraction reduces the complexity of a problem while emphasizing the essential characteristics of it and aids in the discovery of solutions. Abstractions are not always invented; sometimes they are discovered by using existing abstraction models and attempting to fit the problem into them.

This is an example of predication: A statement is created about the problem abstraction and an existing model such as "problem A (new) is a form of problem B (existing)." An otherwise seemingly novel problem may turn out to be a variation of an existing problem to which some known solutions already exist. By formulating problem A in terms of problem B, the architect then only needs to find suitable abstractions for the remaining part of problem A. A problem can have many abstractions, and, using a discursive approach, the architect can discover several suitable abstractions and apply many existing problem models. Metamodels or reference models are examples of such reusable abstractions.

Analysis aids in the discovery and evaluation of abstractions. Not all analysis results in abstractions, but most abstractions are discovered via analysis.




Synthesis



Synthesis is the combining of individual elements or parts to produce a new effect. It is the integration of solutions to subproblems and the evaluation of the resulting system. When we decompose a problem via analysis into sub-problems and discover solutions to those subproblems, there is still the risk that synthesizing those solutions will not solve the larger problem entirely or, worse, the solutions will be incompatible. Existing abstraction models may also be synthesized to form larger, more specialized abstractions. Synthesis is not only applied to the models of software architecture, it is also applied to the design methods



General Heuristics
In this section, we look at some heuristic design methods. Heuristics are techniques that are characterized as the searching for suitable solutions. These methods apply to many design tasks:

Persistent questions

Negation

Forward steps

Backward steps

Factorization

Systematic variation

Division of labor and collaboration




The Method of Persistent Questions
This method is useful when applying any systematic procedure such as requirements engineering (systems analysis), architectural design, and architectural evaluation. Requirements are almost never complete or at the right level of abstraction and the architect must help the acquirer to discover the essential requirements of the application they are envisioning during the analysis of the requirements. Persistent questioning stimulates ideas and intuition and helps to eliminate assumptions and preconceived notions. The method of persistent questions is a tool that the architect may use when analyzing the problem to discover useful abstractions, as well as a tool for evaluating solutions. An architect or architecture team may even keep a database of standard sets of questions for various purposes. Such a database of questions helps extend the memory of the architect and transfer useful design methods and knowledge to others. Asking questions is considered one of the most important methodological tools, and the technique is found in many existing product development methodologies



The Method of Persistent Questions
This method is useful when applying any systematic procedure such as requirements engineering (systems analysis), architectural design, and architectural evaluation. Requirements are almost never complete or at the right level of abstraction and the architect must help the acquirer to discover the essential requirements of the application they are envisioning during the analysis of the requirements. Persistent questioning stimulates ideas and intuition and helps to eliminate assumptions and preconceived notions. The method of persistent questions is a tool that the architect may use when analyzing the problem to discover useful abstractions, as well as a tool for evaluating solutions. An architect or architecture team may even keep a database of standard sets of questions for various purposes. Such a database of questions helps extend the memory of the architect and transfer useful design methods and knowledge to others. Asking questions is considered one of the most important methodological tools, and the technique is found in many existing product development methodologies




The Method of Forward Steps
The method of forward steps is also known as the method of divergent thought. It starts with a first solution attempt and proceeds to follow as many solution paths as possible, yielding other solutions. The method of forward steps is not necessarily systematic and usually starts with an unsystematic divergence of ideas. For example, the first solution attempt at an application problem may be to apply a client/server architectural style. By applying forward steps, the architect follows several paths such as browser-based client, Web client with browser plug-ins, fat client with embedded browser, or fat client that speaks HTTP with the server.

This method can be applied to any model at any level of abstraction and is typically followed recursively as far down a path as possible. For example, starting with the fat client that speaks HTTP solution, additional application of the method of forward steps could yield solutions like fat client with local storage, fat client with server-side storage only, and fat client with heterogeneous local and server-side storage. The process can follow any path. This is a good way to brainstorm over an object model of the application domain as well as the choice of technologies in the solution domain. This method is similar to the method of systematic variation.

The Method of Backward Steps
The method of backward steps is also known as the method of convergent thought. In this approach, the architect starts with a goal in mind rather than the initial problem. This technique is most useful for setting up an engineering design process for a product and a product development plan after the architecture has been determined. Starting with the final objective of the development effort, all (or a reasonable subset of) possible paths that could have led up to the objective are retraced. This method is useful not only in preparing an engineering process but also for organizing an engineering department around the architecture of a product (known as Conway's law).



The Method of Factorization



This method is the basis of the refactoring technique, popular among software engineers when reworking existing source code to make it more readable, manageable, maintainable, and reusable. The method involves breaking a complex system into less complex elements or factors. Factorization is a type of analysis method. In architecting, this technique is used to find the essential problems being solved (for example, factoring the objectives into subobjectives). Just as in mathematics, the factorization may not be obvious and requires some insight, skill, and lots of practice. In algebra, you may factor an equation by introducing zero as a factor. Similarly, finding that one of the factors of a publishing system is a file-versioning repository may not be obvious (although the experienced architect may see the factorization immediately). Another example is taking what may appear to be an indivisible component and finding a way to divide it into two components and an interface.




The Method of Systematic Variation
The method of systematic variation of solutions may have originated with Leonardo DaVinci. DaVinci kept meticulous notes on his ideas and inventions and applied this technique to derive multiple variations of ideas, each varying only by a single characteristic from the former. The method starts with a generalized classification structure, such as a class hierarchy, that represents the various problem characteristics and possible solutions. By systematically varying a single characteristic, the architect may discover more optimized solutions. The approach yields a solution field. Evaluation techniques can be applied to each solution to determine its suitability.




Division of Labor and Collaboration
The study of human factors has found that implementing large and complex tasks requires a division of labor. The more specialized the task the more important the division of labor. Software development tasks are commonly based not only on functional areas of the system but also on the technology used. We typically have user interface designers, user interface engineers, middle-tier engineers, back-end or database engineers, test engineers, configuration management engineers, and so on. A complex application or system also benefits from a division of labor with respect to the architecture. For example, it seems natural to separate the tasks of requirements engineering, functional specification, interaction design, and structural design, all of which are in the scope of architecture. However, whenever there is a division of labor there is an information exchange problem. Systematic methods and the creation of models can help overcome this problem.

No comments: