What is software design quality? How do we create high-quality designs? How do we evaluate software design quality? These are some of the questions that a developer or an architect may have. In this article, we attempt to bring out our perspective on these aspects.
What is design quality?
Software design has an all-pervasive impact on product quality. For instance, design decisions can (positively or negatively) impact various software quality attributes. A well-known approach to dealing with general terms such as “software quality” is to decompose it and look at it in terms of quality attributes (as done in case of ISO 25010 standard for software quality ). In a similar vein, a pragmatic approach to answering the question “what is design quality?” is to decompose “design quality” into quality attributes such as understandability, changeability, extensibility, reusability, testability, and reliability.
The above table provides a definition of these quality attributes.
How to create high-quality designs?
How to create high-quality designs? Since we view design quality in terms of attributes, when we say high-quality designs, it means a design that has mostly positive influence on these quality attributes in the context of the software. Of course, each quality attribute affects other quality attributes and therefore we need to consider trade-offs (e.g., focus on extensibility and reusability could have negatively impact on understandability) and come up with a design that achieves the quality goals defined by the context. Now, the question we are discussing is, “how do we ‘create’ high-quality designs?”
The answer is that applying design principles is the key to creating high-quality designs. Consider an analogy of marvelous designs in civil engineering such Taj Mahal and Hagia Sophia. The design applies fundamental architectural principles such as axis, symmetry, rhythm, datum, hierarchy, and transformation .
How about software design? What are the fundamental principles for creating high-quality designs in software? Grady Booch’s object model gives an answer: abstraction, encapsulation, modularization, and hierarchy. These are very fundamental, yet powerful, design principles for creating high-quality software.
How to evaluate software design quality?
When we grappled with this question (How to evaluate software design quality?) a few years back, we tried finding answer from existing software design assessment methods. The main observation we found was that design assessment methods focus on evaluating design quality (in other words, software design quality attributes similar to what we discussed earlier). However, when we tried to apply this idea in practice, we struggled and ultimately failed. With this real-world experience, we realized that this view (where we look software design quality in terms of design quality attributes) is insufficient.
The natural question arise was – what is missing here in the ility-view? After some exploration and brainstorming, we start gaining clarity on other parts of the equation. Design principles play a key role in software design quality. Further, software design in industrial contexts needs to adhere to various constraints. With this insight, we created a three-view model  for representing design problems in which each design problem is viewed as a violation of design principle(s) and/or project-specific constraint(s) in addition to its impact on design quality attributes.
Let us consider a few examples to make it clear.
Example 1: Consider a class with multiple responsibilities – it is changed because of multiple reasons. Hence, the design violates Single Responsibility Principle (SRP) which states that responsibility refers to encapsulating an “axis of change”. Hence, this design problem can be considered as a violation of a design principle, which in this case is SRP, or the principle of Abstraction which is a more fundamental design principle. We name this smell a “Multifaceted Abstraction” and describe it as negatively impacting understandability, changeability, extensibility, reusability, testability, and reliability . Note that constraints don’t appear in this discussion.
Example 2: Consider a software system implemented in C#.NET. In this software, assume that most classes that hold unmanaged resources (such as system handles or database handles which are system resources) do not implement Dispose pattern as required by the .NET framework guidelines . Since most classes don’t implement Dispose pattern when they are required to do so, it may be considered a violation of the underlying platform and framework constraint that the design needs to adhere to. This design problem negatively impacts design quality (e.g., negatively impacts reusability and reliability). Note that it is hard to argue that this design violates any fundamental design principles, but it is clear that it violates the constraint(s) that the design needs to adhere to.
Example 3: Consider a GUI application that uses Model-View-Controller (MVC) style but the code that corresponds to display logic, control logic, and processing data aren’t strictly separated as required by the MVC style. One way to look at the current underlying design is that it violates the principle of Separation of Concerns, and the underlying fundamental principle of Modularization. Another way to look at the underlying design is that the design does not adhere to the architectural constraint imposed by the MVC style. The current design negatively impacts design quality attributes such as flexibility and extensibility. For this reason, this design problem can be viewed as a violation of design principles as well as constraints.
In general, any design problem can be viewed effectively using this three-view model. Here is a quick summary of the three views:
a) Design principles: Coarse-grained principles are abstraction, encapsulation, modularization, and hierarchy. The next level of granular principles maps to one of the coarse-grained principles; for example, granular principles such as generalization, localization, ordering, factoring, and substitutability map to the principle of hierarchy.
b) Constraints: Project-specific constraints that the design should adhere to such as language constraints, platform constraints, framework and library constraints, domain constraints, architectural constraints, hardware constraints, and process constraints.
c) Design quality attributes: Quality attributes such as understandability, changeability, extensibility, reusability, testability, and reliability.
Revising the question, “How do we evaluate software design quality?” our answer is to use the three-view model and adopt a process that uses this model such as MIDAS  to evaluate software design quality.
To summarize, software design quality could be measured effectively by viewing a design problem from following three different views: ility-view (where the design problem impacts certain quality attributes of the software design), principle-view (where the problem violate one or more design principles), and constraints-view (where the problem violates one or more constraints imposed by the context).
- ISO/IEC 25010:2011, Systems and software engineering — Systems and software Quality Requirements and Evaluation (SQuaRE) — System and software quality models, ISO/IEC, 2011.
- Architecture: Form, Space, and Order, Francis D. K. Ching, Fourth Edition, Wiley, 2014.
- MIDAS: a design quality assessment method for industrial software, Ganesh Samarthyam, Girish Suryanarayana, Tushar Sharma, Shrinath Gupta, ICSE ’13 Proceedings of the 2013 International Conference on Software Engineering, pp 911-920, IEEE Press Piscataway, NJ, USA, 2013.
- Refactoring for Software Design Smells: Managing Technical Debt, Girish Suryanarayana, Ganesh Samarthyam, Tushar Sharma, Morgan Kaufmann, 2014.
- Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, Krzysztof Cwalina, Brad Abrams, Addison Wesley, 2005.
Image Source: http://en.wikipedia.org/wiki/Taj_Mahal#mediaviewer/File:Taj_Mahal_(Edited).jpeg (CC BY-SA 4.0 license)