Impact of Design Patterns on Software Complexity and Size

Many different factors influence the quality of software. Among the most important of these factors is software complexity. One way to improve software quality, therefore, is to minimize its complexity making it more understandable and maintainable. The design phase of the software development life cycle plays an instrumental role in fostering quality in software. Seasoned designers often use past design best practices codified in the form of design patterns to make their designs and the resultant code more elegant, robust, and resilient to change. Little work, however, has been done to empirically assess the quantitative impact of design patterns on software complexity. This research is an attempt to fill this gap. A comparative analysis of before and after versions of program pairs written without and with design patterns was performed for all twenty-three GoF (Gang of Four) design patterns. These program pairs were collected (or, in some cases, developed) and compared with respect to their complexity and size. The results of this comparative analysis reveal that the cyclomatic complexity of the programs written using design patterns was less for most of the design patterns as compared to the programs written without using design patterns. However, the values of CK metrics, number of classes, and software size SLOC (Source Lines of Code) increased when design patterns were used.


INTRODUCTION
Software has become an invisible driving force of our individual and collective existence. It is now playing an indispensable role in our international trade, our stock exchanges, our educational institutions, our healthcare, and our entertainment. Yet, despite the fact that software has penetrated different aspects of our lives, it is still engineered following a set of steps which together constitute the SDLC. Some of these steps focus on the problem domain while others on the solution domain. The first step, and probably the most important, in the solution domain is design.
Design is the step in which the software engineer starts to think about solving the problem which has been understood in the upstream SDLC steps like requirements engineering and analysis. Designers focus on different aspects of the solution e.g. design of interfaces, design of data and data storage, design of software configuration, etc. Needless to say, most of the times it is impossible to get the design right the first time. Usually, multiple iterations are required and for most medium and large scale software-intensive systems design is a challenging exercise.
Software designers, however, often face recurring problems. Such problems can be solved using similar solutions called design patterns. In simple terms, a design pattern can be defined as a template or description for solving a recurring design problem [1]. Gamma et al. [1], commonly referred to as the GoF, were the first to catalog a collection of 23 commonly used design patterns. Apart from enabling the reuse of 343 design concepts, these design patterns were considered useful for making designs more flexible and elegant.
Past research has shown that these design patterns have a positive impact on different software quality factors e.g. reusability, understandability, maintainability, etc. [2]. Software quality, however, can also be improved by reducing its complexity. Naturally, code that is less complex is easy to understand, maintain, modify, and reuse. It is also less error prone.
One of the commonly used metrics for quantitatively measuring code complexity is the cyclomatic complexity metric proposed by McCabe [3]. Given a program, it identifies the number of linearly independent paths through that program [3]. Generally speaking, the more the number of conditional statements (representing branching logic) in a program, the more the value of its cyclomatic complexity. Apart from the number of conditional statements (e.g. if-else, switch-case, etc.), the size of the software itself has an impact on its complexity. SLOC (Source Lines of Code) is one of the mostly commonly used metric for measuring the physical size of a program [4].
For object-oriented programs (including those written using design patterns), the well-known suite of OOmetrics proposed by Chidamber and Kemerer [5] can be used to measure complexity. This suite consists of six metrics which are commonly referred to as the CK metrics. Table 1 includes a brief description of each of these six CK metrics.
Even though researchers have conducted different studies to explore the impact of design patterns on different aspects of software quality [2,6], little work has been done to empirically examine the impact of design patterns on software complexity -one of the most important quality factors [6]. To the best of our knowledge, no past research has systematically assessed the impact of all 23 GoF design patterns on cyclomatic complexity, values of CK metrics, number of classes, and size measured using SLOC. This research is an attempt to fill this gap. We gathered before and after versions of programs written to solve the same problem. The only difference between the before and after versions was that the before version was written without using any design pattern whereas the after version used one of the 23 GoF design patterns. The before/after program pairs were then analyzed to quantitatively assess the impact of using design patterns on software complexity and size.
The next section briefly summarizes the relevant work in this area. Section three provides the details of our research methodology while section four contains a discussion on the main results of our research. Finally, section five concludes this paper by summarizing our main findings and providing directions for future work in this area.

LITERATURE REVIEW
After design patterns were first introduced by Gamma et al. [1], people have shown immense interest in the use of design patterns. Lange and Nakamura, for instance, looked at how design patterns improve program understandability [7]. Their study, however, 344 focused on only one quality attribute and was applicable on only a few design patterns.
Wydaeghe et al. [8] built an OMT (Osteopathic Manipulative Treatment), editor and presented a detailed study on the use of six different design patterns. They described the impact of these patterns on modularity, reusability, understandability, and flexibility. They concluded that, while design patterns have various advantages not all design patterns have a positive impact on software quality. This study also was limited to authors' own experiences and the evaluations made and conclusions drawn may not be applicable to all design patterns.
McNatte and Bieman [9] evaluated the coupling between design patterns and their impact on quality attributes. Their results reveal that maintainability, reusability, and performance can be greatly improved when design patterns are abstracted and loosely coupled. Subburaj et al. [10] also assessed the effect of design patterns on software reusability. Their results reveal that design patterns improve architecture-level reusability of software.
Prechelt et al. [11] carried out an experiment on four systems to analyze the impact of five design patterns (i.e. Abstract, Factory, Composite, Decorator, Observer and Visitor) on maintainability. They concluded that design patterns are highly preferable even for simple design solutions. Hegedus et al. [12] also assessed the impact of design patterns on software maintainability. They took into account a total of three hundred revisions of the J Hot Draw software system. Their results revealed that the system's maintainability showed great improvement after using design patterns. This conclusion is corroborated by another experiment, conducted by Abdullah [13], to study the impact of design patterns on maintainability and performance. The results of this experiment also show that applying design patterns helps in attaining fairly good maintainability.
Rudzki [14] chose a slightly different approach. He assessed the impact of two distinct design patterns (i.e. Command and Façade) on the same software to see how the two differed in their respective impact on the level of performance of the software. While conducting this study, he ran the software in nine different test cases and reached the conclusion that the Command design pattern worked better than Façade and had a positive impact on software performance. Jeanmart et al. [15] assessed how the Visitor design pattern affects quality factors like understandability and maintainability. They concluded that the Visitor pattern is more time consuming in understanding and handling of tasks that require adjustments to be made. However, it was also revealed that when the Visitor design pattern is used in its canonical form, much less work and effort is required for adjustment tasks.
Aydinoz [16] applied refactoring on object-oriented programs with design patterns and found that complexity in terms of CBO (Coupling Between Objects), WMC (Weighted Method Per Class), and RFC (Response for a Class) had reduced. Huston [17] theoretically evaluated the impact of design patterns on class metric scores. He compared the complexity score of three design patterns (i.e. Bridge, Mediator, and Visitor) with non-pattern solutions. His results indicated that quality could improve by reducing the NOC (Number of Children) value.
Hsueh et al. [18] theoretically analyzed the impact of design patterns using QMOOD (Quality Model for Object Oriented Design). Their results showed that polymorphism and abstraction can be improved by using design patterns and Singleton design pattern does not contribute to quality improvement. Yu and Ramaswamy [19] analyzed the impact of 13 design patterns on class structure quality extracted from five different open source projects. Their results revealed that the use of design patterns can increase class complexity. Fig. 1 shows the main steps of our research process. The first step was the selection of design patterns for this experiment. We selected only GoF design patterns since they are widely used in the software industry. These 23 patterns are divided into three purposes (i.e. creational, behavioral and structural) and two scopes (i.e. object and class). The choice of appropriate object-oriented programming languages was the next step. C++ and Java were selected as they are popular object-oriented languages and a lot of applications patterns.

RESEARCH METHODOLOGY
The third step was the collection of programs written with and without design patterns for the same problem. For most of the GoF design patterns, we found such programs with before and after versions at SourceMaking.com [20]. Before versions of just four design patterns were missing there. These were written by the first author herself [21]. Fig. 2 depicts the before/after program pair for the Builder design pattern.

346
In the fourth step, we used "Source Monitor" [22] and "CCCC" [23] -two measurement/assessment tools -to compare the programs written using design patterns with those written without using design patterns. These tools were selected because they can measure values of selected metrics for both C++ and Java programming languages. The program pairs were compared using average and aggregate cyclomatic complexity and four CK metrics (i.e. WMC, DIT, NOC and CBO) since "CCCC" provides values for just these four metrics. Size was measured by counting the non-blank and non-comment SLOC. Table 2 summarizes the choices made at each step of our research process.  Table 3 shows the detailed comparison of program pairs with respect to size and cyclomatic complexity. It contains the values of SLOC, number of classes, average cyclomatic complexity, and aggregate cyclomatic complexity for programs written before and after using design patterns. Note that 24 program pairs (instead of 23) are selected and analyzed since the Adapter design pattern has two variants -one for class scope and one for object scope. The data in Table  3    This slight increase in the program size and the number of classes is the necessary by-product of using design patterns which achieve design reusability by introducing additional classes and hence program statements.

CONCLUSIONS
The aim of this research was to evaluate, quantitatively, the impact of all 23 GoF design patterns on software size and complexity. Program pairs written with and without these design patterns were selected and analyzed for this purpose. The results of this study reveal that design patterns have a positive impact on the average cyclomatic complexity of the system i.e. average complexity decreases for most of the patterns. The impact on the values of CK metrics, number of classes, and size (SLOC) of software, however, is mostly negative.
This research is the first attempt in studying the quantitative impact of all 23 GoF design patterns on software complexity and size. Even though the results seem promising, there is lots of room for further exploration and experimentation. For instance, so far we have looked at programs with medium complexity level. It would be interesting to determine the impact of design patterns on more complex industrial and open-source projects (obtained, for instance, from GitHub). Another beneficial exercise would be to study the impact of using a combination of related design patterns (e.g. Abstract Factory and Factory Method) on program size and complexity. Different assessment tools (other than the ones we selected) could be used for this purpose. Similarly, it also seems worthwhile to replicate this experiment for different programming languages, project sizes, and application domains. Broadening the scope of this study may help us in drawing further insights regarding the impact of design patterns.