Skip to content Skip to navigation

OpenStax-CNX

You are here: Home » Content » Introduction to (Software) Design

Navigation

Recently Viewed

This feature requires Javascript to be enabled.
 

Introduction to (Software) Design

Module by: Guilherme Germoglio. E-mail the author

Summary: An introduction to design and software design, in order to set up an underlying, supportive foundation to help the reader recognize both the relevance and the advantages of software design.

Before setting up to the task of studying and applying Software Architecture, it is convenient to know where – within the range of Software Engineering Body of Knowledge – Software Architecture should be placed as a discipline. Besides, the implementation of Software architectural design is the first of two activities that comprise the Software Design Knowledge Area (the other activity is that of software detailed design). As part of Software Design, Software Architecture is a mixture of method and creativity. Software Architecture lies beyond the range of this book whose purpose does not include the teaching of creativity. Creativity is something that results from experience, thus it is not the purpose of this book teach it. However, the authors seek to impart the knowledge needed for you to create software system architectures.

A sound knowledge of the fundamentals of Software Design is certainly needed for you to take up the material covered in this book. Therefore, this chapter will provide you with an overall view of these fundamentals, expounding them further by setting up an underlying, supportive foundation to help you recognize both the relevance and the advantages of software design. In other words, it will provide you with the necessary knowledge that will enable you to:

  • Recognize the basic concepts required to design software
  • Describe a design problem by way of its fundamental elements
  • Identify design enabling techniques and explain their benefits
  • Differentiate low-level design activities from high-level design activities, and know when to apply either of them.

Design and Software Design

The relevance of the practice (and, therefore, of the study) of Software Design can be explained by the ever-increasing complexity of software systems. Because of such complexity, the risk of building a system that will not meet its goals is indeed too high.

In order to avoid such a risk, the rule of thumb of any engineering process for building a complex artifact is to build it according to a pre-established plan, e.g., to design it before building it. Therefore, the purpose of design is twofold. One is to allow you to build models that can be analyzed and evaluated against their aimed objectives before they are actually built; and the other is to serve as a guide for the artifact assemblage after it has passed both the analysis and the evaluation phases.

Characteristics of Design

There are several reasons for designing an artifact before building it. The following paragraphs describe some of them.

Design enables early evaluation. The building process of an artifact can be very expensive in terms of time and money. Because it helps to ensure that the right thing is being built, those involved in this process desire the possibility of early evaluation. Since the products of design process often permit this kind evaluation and it often costs less than actually building the artifact, designing and early evaluating the artifact before building are recommended in order to save time and money.

Design demands modeling. When modeling, the designer's focus is on the problem, letting apart some complexity inherent to the final product. Since complexity is one of the greatest difficulties of artifact development 1, any practice that helps to prevent is also highly recommended.

Design involves planning. Because of this, the design process helps on estimating costs, e.g., how long it will take to build the artifact, how many men will be necessary to build it, what existing parts can be reused in current design, etc., and adds control to development.

Lastly, design facilitates communication. A design provides a common language in which knowledge about the artifact can be recorded, transmitted and discussed. So, if the artifact development involves more than one person and communication among the involved is desired, it is recommended to leverage design in order to assist communication.

In addition to these characteristics, we introduce two important points, which must be kept in mind while designing.

First, designing an artifact may be cheaper than building it, but is not cheap. Design takes time and money and must be performed with care and method. We will further see that design is made to achieve goals, but nothing ensures that the design goals will remain the same by the end of the design process. Consequently, this possible transient nature of design goals can bring risk to the design process and lead to failure, especially when performed by those not aware of this aspect of design goals.

Second, the design of an artifact is not the true artifact. This means that design evaluation against its goals cannot be perfect and its results must be analyzed carefully – always keeping in mind that there will be some intricacies out of the design that can deeply impact its success and, so, must not be completely ignored.

Please notice that these points above will be better illustrated when we restrict the subject of this chapter to design of software.

Software design

Since design is a rather vast discipline, it is wise to pin down our subject. Authors usually define design in two steps: when it is used as a subject and when it is used as a verb. When used as a subject, design “indicates the [product] that emerges from the design process, some physical document or other kind of representation that articulates the intent of the designer. This product results from the choices the designer made, choices that form an abstraction of that what is eventually desired in the real world.” Moreover, as a verb, to design “indicates the process by which a design is achieved. It is a human-centered process, involving varied stakeholders. It is also understood to be strongly goal-driven and drawing upon established knowledge of the designer and the field at large.” [9]

Turning our attention to software design, we must make just a small (and obvious) specialization on design definition: the product of software design turns out to be a software system representation. This way, a software design may typically describe many aspects of the software system. Budgen identifies some of these aspects [6]:

  • the static structure of the system, including any subprograms to be used and their hierarchy;
  • any data objects to be used;
  • the algorithms to be used;
  • the packaging of the system, in terms of how modules are grouped in compilation units (assuming that implementation will use a conventional imperative programming language); and
  • interactions between components, including the form these should take, and the nature of any causal links.

Characteristics of Software Design

Because designing all these aspects of a software system might be hard work, its benefits must be brought to light. We soon see that these benefits are analogous to the benefits of general design. Software development consumes time and money. Also, it is quite obvious that no one wants to spend his or her resources in developing software that solves the wrong problem. Considering this, just like when we were generally describing design, the possibility of early evaluation is desirable because it helps to ensure the stakeholders the development of the right program. Software design enables this early evaluation, because its product describes several aspects of the final program. Also, it is often less expensive to obtain than the whole program.

When modeling a software system, thus designing it, the designer focuses on the domain problem. This enables the designer to distinguish the problem's essential complexity from the accidental one. As stated by Brooks [5], this separation is known to impact positively on the quality of the final program.

Just like general design, software design helps on estimating costs, e.g., how long all the development process will be, how many implementers will be necessary for a specific module, should a module be implemented or bought, what group is responsible for implementing a specific module, and so on.

Finally, because it contains knowledge from the system that can be recorded, transmitted, and discussed, software design can act as a communication vehicle. For example, if a software system is to be presented to a new member of the development team, before making her dive into the code, valuable information can be passed to her via the software design. Moreover, if the audience of this presentation is a program user, information (often abridged) from the design is even more necessary, since it may not make sense showing software source code to this kind of audience.

Nevertheless, some important observations related to these characteristics must be made.

While the design process occurs, it is possible that the person who wants the software to be built for solving her problem (the client) (1) change her mind about the very problem, (2) describe her problem incorrectly, or even (3) consider that the problem itself changed, or have been solved, during the design process. All these three possibilities must be kept in mind because they may lead the designer to fail on achieving the client's objectives and eventually to waste time and money.

Since a software design is just a model, its detail level may not be adequate for certain kinds of evaluation. In fact, evaluating a software design without enough details can lead to wrong results and then to wrong programs. This is quite common when evaluating performance, especially when bad designers consider insufficient detail for this purpose. For example, a performance design evaluation stated that a specific system was able to cope with a thousand users accessing it simultaneously. However, this very design did not add enough details on the actions performed by users. The case was that the performance analysis was made considering that each action consumed less resources than they in fact did after implemented. As expected, this system failed miserably when the number of concurrent users started to grow near the expected limit of a thousand users.

Finally, although a software design is correct, it may not be followed as such during its implementation. So, we must be aware that wrong implementation of a design can lead to wrong software just like a wrong design would.

We understand that software design can lead to some drawbacks that are not to be ignored, but its advantages, as we have seen, are very relevant too. Considering all this, we believe that understanding the fundamentals of (software) design, as well good practices, guidelines, and enabling techniques are essential to an aspiring architect.

Elements of software design process

The design process can be described as the process of choosing a representation of a solution from a set of alternatives, given the constraints towards a set of goals. It can be divided in two phases [2]: diversification and convergence.

The diversification is the phase of generating alternatives. Not necessarily documents describing a possible solution, but, at least, on the designer's mind. These alternatives are the solution candidates and are generated/obtained from knowledge, catalogs, or previous experience. During the convergence phase, the designer chooses the alternative (or the combination of alternatives) that meets the intended goals. The alternative selected will be the solution, which will meet the constraints imposed by the problem domain. The solution then may be described using some representation. The representation chosen must fit its purpose: describe the solution and the process to build the artifact that reaches the intended goals.

From the paragraph above, we must emphasize the following elements: goals, constraints, alternatives, representations, and solutions[8]. These elements together define a conceptual framework that helps to understand the software design process.

Goals

Design begins with a need. If something is to be designed, though to be built, it is because the outcome of the design process will fulfill this need. In Software Engineering, the necessity starts from a customer who specifies what are her needs and therefore what are the goals to be achieved with the software system to be designed. So, the goal of the design process is to achieve a solution that will solve the customer's needs. In software design, goals are also referred to as requirements. Software design is mainly concerned on two types of requirements: functional and nonfunctional requirements.

A functional requirement specifies the functionality that a system will exhibit. In other words, what the system is to perform according to the customer. For example, a functional requirement for a sorting program is to provide the ability to sort integers. Another example could be related to a software system that manages the inventory of a movie rental store. If we were to enumerate the functional requirements of a system like this, among them would be: the ability to search for a movie by its keywords, the ability to perform a movie rental, the ability to perform a movie return, and many others.

On the other hand, a nonfunctional requirement specifies properties or characteristics that a software system must exhibit other than the observable behavior [10]. Specifically, it is concerned on how the software will function. Back to our sorting program example, a nonfunctional requirement is the customer's concern with the running time of the sorting function (e.g., it is acceptable that the sorting algorithm execution time has the growth rate of O(nlogn)O(nlogn), where nn is the size of the input). If we are talking about the movie rental store software, one nonfunctional requirement can be described as exposing some system's functions, such as the search for movie by its keywords, to be accessible via browser to its users.

As nonfunctional requirements play an important role on software architecture, we may return to them in the chapter on Nonfunctional Requirements, where they will exemplified, described, and categorized in detail, as well they will be correlated to their imposers, the system's stakeholders.

Constraints

A design product must be feasible. Considering this, a design constraint is the rule, requirement, relation, convention, or principle that define the context of design, in order to achieve a feasible design product. Smith and Browne gave a detailed description of the role of constraints on design [8]:

The notion of constraint is central to design. [...] This centrality derives from the nature of design problems: something new must be created; human imagination is able to generate various possibilities; but this capacity and the alternatives it proposes must be managed by consideration of what is feasible. Constraints serve this purpose. They express relations among properties or variables of the proposed artifact and its environment or context.

It is important to know that constraints are related to goals, and sometimes they can even be exchanged. However, in order to differentiate them, it is also important to understand that are not only the goals that rule what is to be designed. In other words, a software system may have clear goals, but its design, or some possibilities of it, may not be feasible because of its constraints.

In order to grasp the role of constraints in design, let us consider two examples. In the first example, despite the software system has a clear goal, its design is not feasible due to some of its constraints. In the second, a software system also has a clear goal, but just a clear design possibility is constrained.

First, please consider that a customer describes a simple goal to be achieved by a system: it must be able to decide whether its input, a description of another program, finishes running or not. An inexperienced software designer might even try to find a design possibility for this requirement – but this would be in vain. There is a theoretical constraint in computer science, widely known as the halting problem, which forbids a program to decide whether or not another program halts after its execution, thus not allowing achieving a solution. So, a design was not allowed due to its constraints even with a clear stated goal.

In the second example, the customer requires the following for a software system: the system must read input data from a specific card reader from a specific manufacturer. Besides the goal, the designer finds the following restriction. The specific manufacturer does not provide the card reader drivers for one of the operating systems the system must execute on. If it weren’t for this restriction, the design for the input data module would be quite straightforward: just rely on the hardware driver to fetch the input data from cards. But now the designer will have to work out an alternative design to handle this restriction. One design possibility could be emulating one of the operating systems supported by the manufacturer when the system is executing in a non-supported environment. This would mean the creation of a layer of abstraction that would represent the supported environment and eventually be implemented by a native or an emulated system. Another possibility could be just designing and implementing the missing driver.

Alternatives

A design alternative is a possibility of solution. Since design problems often have multiple solutions, since design problems often have multiple solutions, the designer is expected to generate multiple design alternatives for a single problem. We must understand that the designer, after understanding the problem's goals and constraints, has two concerns: the alternative generation and the solution election among the alternatives.

Alternative generation poses the real challenge for a designer. Unlike decision problems area where decision alternatives are known or can be discovered through search methods, design alternatives must be created. This creation process then must be controlled by design enabling techniques, and designer's experiential knowledge and creative imagination [8]. "Enabling Techniques" will present some essential techniques for a designer.

The solution election is simply the choice of one of the alternatives that, according to the designer, will best solve the problem. This choice must be made employing reasoned analysis and experience. The following subsections better explain solutions and their representations.

Back to our sorting program example, let us only consider one aspect of it, the sorting algorithm to be used, and see how many alternatives a designer could generate. A quick search on the Internet returned nine algorithms that respect the growth rate of O(nlogn)O(nlogn) constraint (binary tree sort, heapsort, in-place merge sort, introsort, library sort, merge sort, quicksort, smoothsort, strand sort). So, we have nine design alternatives that can be easily achieved. On the other hand, an experienced designer, who knows that these algorithms may run better or worse according to the input, proposes that two algorithms will added to the design and, on every run, one is elected to be used according to the input. Then, we have more design alternatives being generated. Please notice that the alternative generation can go on and on as the designer considers more aspects of the problem. Nevertheless, she must know when to stop the alternative generation, since design problems have potentially infinite alternative solutions. Such knowledge comes with experience.

Representations

Representations are the language of design. Although the true product of design is a representation for artifact construct, representing the solution is not the only purpose of representation. It also supports the design process. This support happens by allowing communication between stakeholders and by serving as a record of commitments.

A design representation allows communication because it turns alternatives into manipulable products, so they can be described, analyzed, and discussed not only by their author but also by others. Please observe that there are multiple dimensions to be represented on a single software design alternative. These dimensions may comprise runtime behavior, structure, and relation between logical entities to physical entities just to name a few. These dimensions are often exhibited on different types of representations, which later we will name them views.

In order to illustrate design representations, let us present two dimensions of our sorting program example by using two different representations. The first representation, Figure 1, shows the structure from a design possibility of our example using Unified Modeling Language. Observing this representation, we see how the solution was decomposed, how each class of the structure relates to each other, or even see what points could be replaced by ready-made components, which must implement the same interfaces specified on the representation. One thing that must be noticed is that this representation is not self-contained, since knowledge on UML is needed by the reader to fully understand this representation.

Figure 1: Structural representation of a sorting program
Figure 1 (sorting-class-diagram.png)

The second representation, Figure 2, shows the example's runtime behavior when sorting with high level of detail. Although we cannot see from this representation the same information presented on the previous one, this enables us to analyze how the program will asymptotically behave according the growth rate of its input. Also, we can have the notion of how much space is needed to perform the algorithm.

Figure 2: Merge sort pseudocode [11]
Figure 2 (sort-pseudocode.png)

Both representations show important aspects of a system's design, nevertheless one involved on its development might be interested on aspects other than its structure or algorithm asymptotic analysis. As a matter of fact, other representations might be wanted for other purposes and it is the role of the design process to provide them.

In addition, if we have considered multiple versions of a single representation, e.g., multiple versions obtained until the pseudocode shown on Figure 2, we could see the evolution of the design decisions made over time, e.g., the evolution from a standard merge sort to an in-place merge sort. The recording of multiple versions are important to understand what decisions led to the design's current state.

Solutions

A design solution is nothing more than a description enabling system construction that uses one or many representations in order to expose sufficient details. Its characteristics are listed in the following paragraphs.

Design solutions mirror the problem complexity, usually having many attributes and interrelationships. We can observe this characteristic, for example, when designing a solution for managing the inventory of a DVD rental store. Whatever the solution is, it must contain attributes such as movies, DVDs, clients, and genres, which will represent the elements inherent to the problem. However, this is not enough. It must also contain relations such as “a client can rent one or more DVDs”, “a movie have one or more genres”, or “a DVD must contain one or more movies”, which will behave just like the relations on the problem domain. Consequently, when many different attributes have different interrelationships between themselves, complexity emerges.

It is difficult to validate design solutions. The complexity of the solution renders many points of possible validation against design goals. The very problem resides on how well the design goals are described. Usually, only high-level goals are specified for very complex problems, so validation is hardened.

Lastly, most design problems have many acceptable solutions. This is intrinsic to design problems. Since many alternatives can be generated for a single design problem, as many design solutions are eventually reproduced.

The product of the design process is always a design solution. However, despite being a description enabling system construction, nothing is said about the level of detail a solution must incorporate. It comes out that the software design process can occur in many levels of detail. These levels of software design are the subjects of the next section.

Levels of software design

According to the Guide to Software Engineering Body of Knowledge (SWEBOK) [1], software design consists of two activities: top-level design and detailed design.

The top-level design, also called architectural design, is concerned on describing the fundamental organization of the system, identifying its various components and their relationships to each other and the environment in order to meet the system's quality goals. In contrast to top-level design, detailed design is more concerned on describing each component sufficiently to allow for its construction according to the top-level design.

The clear separation of these activities may not always occur during software development process. Sometimes a designer performs both activities in parallel, conceiving a design that will both meet the quality requirements and also allow for the construction of the system. Nevertheless, we primarily consider this conceptual separation to keep the focus only on software architecture, which is the main subject of this book and will be discussed in the following chapters.

However, just before starting our studies on Software Architecture, we would like to present some principles essential to every design activity, which are called enabling techniques.

Enabling Techniques

Enabling techniques are guidelines, approaches, and key notions that are known to result on generally good and sound software designs. Since there are many great books and articles on enabling techniques, the purpose of this section is just to scratch the surface of this subject by giving an overview of it. The essential enabling techniques for an aspiring designer are:

Abstraction

Abstraction is an essential principle used by designers to deal with complexity. This strategy recommends representing an element only by its “essential characteristics that distinguish it from all other kinds of objects and thus provide crisply defined conceptual boundaries relative to the perspective of the viewer” [3]. Considering this approach, the element representation tends to be simpler, since unnecessary details are put aside, and eventually easier to understand, communicate, and analyze.

As a matter of fact, most of the techniques presented help the designer to raise the level of abstraction of the design process in order to lower the level of complexity of the solution.

Information Hiding

“Information hiding involves concealing the details of a [system entity's] implementation from its clients” [4]. By doing this, the coupling between entities is minimized and their contribution to system complexity is restricted to what information they expose.

There are several approaches to perform information hiding: by modularizing the system, by separating its concerns, by separating interface and implementation, or by separating policy and implementation.

Modularization

Modularization is the meaningful decomposition of a system into modules. It introduces well-defined and documented partitions (modules) within a system by deciding how to physically package the logical structure entities of an application. Some benefits of modularization follow:

  • It promotes understanding, since each module can be grasped at a time,
  • It eases development, since each module can be designed, implemented, and tested separately,
  • It shortens development time, since modules can be implemented in parallel or reused or even bought, and
  • It promotes product flexibility, since a module can replace by another if both respect the same interfaces.

Separation of Concerns

Separation of concerns is tightly coupled to the modularization technique. Actually, it is a rule of thumb to define how modules should be separated to each other: different or unrelated concerns should be restricted to different modules.

Coupling and Cohesion

Coupling and cohesion are principles used to measure whether the design was well divided into modules.

Coupling is the strength of interdependence between software modules. The more dependent is module A to module B internals, the stronger is the coupling between A and B. Strong coupling implies the modules involved are harder to understand because they must be understood together, harder to change because these changes will impact more than one module, and harder to correct because the problem may be spread over the tightly coupled modules.

Opposed to coupling, cohesion is an intra-module measure. Cohesion is the strength of relation between tasks performed by a module. The tasks of a module can be related to each other by several levels, then converted on types of cohesion:

  • Functional cohesion:: tasks are grouped because of the similarity of their functions.
  • Sequential cohesion:: tasks are grouped because they belong to the same sequence of operations, they share data at each step, but they don't make up a complete task when done together.
  • Communicational cohesion:: tasks are grouped because they make use of the same data and aren't related in any other way.
  • Temporal cohesion:: tasks are grouped because they are executed at the same time.
  • Procedural cohesion:: tasks are grouped because they are executed in a specified order.
  • Logical cohesion:: tasks are grouped only by a shared control flag that will indicate which task will be performed during execution.
  • Coincidental cohesion:: tasks are grouped without any criteria.

In order to achieve sound designs, we can also sort the types of cohesion from the most to the least desirable on design [7]: functional, sequential, communicational, temporal, procedural, logical, and coincidental.

Separation of Policy and Implementation

This technique enables separation of concerns. The separation of policy and implementation technique simply states: “A [module] of a software system should deal with policy or implementation, but not both.” [4] Modules responsible for implementation should only execute algorithms without any context/domain-sensitive decisions. These decisions must be left to policy modules, which are often application-specific and are often responsible of supplying arguments for the implementation modules.

This separation eases reuse and maintenance of implementation modules, since they are less specific than policy modules.

Separation of Interface and Implementation

Separation of interface and implementation eases modularization. This technique recommends the description of functionality by means of contracts, also called interfaces. Modules will eventually implement these interfaces in order to be part of the system.

Using this technique, the coupling between modules and clients is lowered, since clients are only bound only to interfaces – not to implementations.

Summary

The purpose of this chapter was to provide the fundamental knowledge on Software Design in order to enable the reader to be ready for the study of Software Architecture. We expect that, by now, the reader is able to understand:

  • what software design is and what are its characteristics and benefits,
  • how software design problems can be decomposed, and
  • what are the general enabling techniques for performing software design.

As a matter of fact, since there are many great books on Software Design for the same audience of ours – the inexperienced reader, it was not our intention to go deeper on the subject covered in this chapter. Our intention was just to introduce it. For more detailed information, we recommend the reader to check the books on Software Design indicated in this chapter's bibliography.

Footnotes

  1. We call development the whole process from devising an artifact to eventually build it.

References

  1. Abran, Alain and Moore, James W. and Bourque, Pierre and Dupuis, Robert and Tripp, Leonard L. (2004). Guide to the Software Engineering Body of Knowledge (SWEBOK). IEEE.
  2. Belady, L. (1981). Foreword. In Software Design: Methods and Techniques (L.J. Peters, author). Yourdon Press.
  3. Booch, Grady and Maksimchuk, Robert A. and Engel, Michael W. and Young, Bobbi J. and Conallen, Jim and Houston, Kelli A. (2007, April). Object-Oriented Analysis and Design with Applications (3rd Edition). Addison-Wesley Professional.
  4. Buschmann, Frank and Meunier, Regine and Rohnert, Hans and Sommerlad, Peter and Stal, Michael and Sommerlad, Peter and Stal, Michael. (1996, August). Pattern-Oriented Software Architecture, Volume 1: A System of Patterns. John Wiley & Sons.
  5. Brooks, Frederick P. (1995, August). The Mythical Man-Month: Essays on Software Engineering, 20th Anniversary Edition. Addison-Wesley Professional.
  6. Budgen, David. (2003, May). Software Design (2nd Edition). Addison Wesley.
  7. Mcconnell, Steve. (2004, June). Code Complete, Second Edition. Microsoft Press.
  8. Smith, G. F. and Browne, G. J. (1993). Conceptual foundations of design problem solving. Systems, Man and Cybernetics, IEEE Transactions on, 23(5), 1209–1219.
  9. Taylor, Richard N. and van der Hoek, Andre. (2007). Software Design and Architecture The once and future focus of software engineering. In FOSE '07: 2007 Future of Software Engineering. (p. 226–243). Washington, DC, USA: IEEE Computer Society.
  10. Wiegers, Karl E. (2003, February). Software Requirements, Second Edition. Microsoft Press.
  11. Wikipedia,. (2008). Merge Sort — Wikipedia, The Free Encyclopedia. [[Online; accessed 2-September-2008]].

Content actions

Download module as:

Add module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks