Software is rarely just written down flawlessly and never has to be looked at again. As the world evolves and the requirements inevitably change, software needs to be maintained. So it's important to design software that is maintainable and doesn't start to rot the minute it has been committed to version control. It is crucial that software engineers and designers develop a good nose for smelly code and fishy design decisions.
Girish Suryanarayana, Ganesh Samarthyam, and Tushar Sharma define a design smell as "certain structures in the design that indicate violation of fundamental design principles and negatively impact design quality". Their book Refactoring for Software Design Smells will help you train your sensory organ to become better at finding, naming, and fixing smells in your software's design. They present a catalog of 25 smells and relief in the form of a refactoring strategy to get rid of the smells.
Design smells can have many roots, some are caused by limitations in the programming language (e.g. lack of generic programming support in early Java versions, or the missing lambdas prior to Java 8) others by inexperienced programmers (e.g. applying design patterns without understanding their drawbacks) or quick hacks that are made under time pressure. The book focuses on structural design smells in common object oriented languages like Java, C# and C++, so it's not about software architecture or implementation smells specific to a programming language.
The catalog is partitioned into four categories: abstraction, encapsulation, modularization, and hierarchy smells (for an overview, have a look at the table of contents). Each smell is discussed, listing potential causes and a suggested refactoring, and comes with many examples and anecdotes. Because some smells are known under different names, it can be helpful to check out the aliases section. For example, Missing Abstraction is also known as Primitive Obsession – the use of primitive types (e.g. strings, integers) where a class might be a more appropriate abstraction. This can be refactored – but not over-engineered – by introducing abstractions (e.g. by applying the replace type code with class refactoring)
Girish, Ganesh and Tushar spoke to InfoQ about their motivation and how they approached collecting and writing about design smells.
InfoQ: What made you write a book about design smells?
We were working on creating a method for assessing the design quality of industrial software. We were trying to understand the potential problems or smells in software design and how we could refactor them. As we started exploring design smells, we came across smells scattered across numerous sources such as books, papers, and theses. We collected more than 530 smells! We wanted to make sense of this huge collection and set out on a mission to meaningfully classify them. After struggling for a few months to solve this problem, we got an insight:
When we view every smell as a violation of one or more underlying design principle(s), we understand how that smell occurred; but perhaps more importantly, it naturally points us towards a potential refactoring approach for that smell.
We built on this fundamental concept and classified the smells based on how they violated Booch’s fundamental design principles (abstraction, encapsulation, modularization, and hierarchy). We published our initial work as a paper; some of the reviewers of this paper also suggested that it would be a good idea to expand the work into a book. We started giving trainings on this work and found that designers and architects really liked the smell catalog and found it useful. Building on this positive feedback, we have developed our work into this book. Our objective for writing this book was to provide a framework for understanding how smells occur as a violation of design principles and how they can be refactored by applying design principles so that technical debt can be kept under control. We hope that this core message reaches the readers through this book.
InfoQ: Are you targeting a specific audience with your book?
This book is meant mainly for software developers and architects. The knowledge of fundamental principles and enabling techniques as well as specific design smells and the suggested refactorings provides immediately usable ideas for improving the quality of the designs they create or maintain. This book will also help them understand how to apply design principles in practice. In addition, this book may help project managers understand how to manage technical debt in their projects. From our architecture and design trainings, we find that smells approach is an especially effective way to approach software design in practice; hence students will find this book useful for learning software design.
InfoQ: By teaching how not to design software?
We first present Booch's principles and corresponding enabling techniques we have identified for applying these principles. They would appear simple and obvious when they are presented (e.g., “hide variations” as an enabling technique for encapsulation). Following that, we present segments of “real-world smelly designs” and ask them to identify potential smells and suggest refactoring. In many cases, identifying smells and corresponding refactoring will be easy. But some involved problems trigger deeper analysis and participants start slowly realizing that it is a hard task. There are also some “aha!” moments when we start discussing how design qualities are affected and practical considerations. Anecdotes from the trenches on dealing with the smells are also often revealing. At the end, we cover tools for refactoring and process aspects as well.
After a break of a couple of weeks, participants present smells from the projects they are working on and how they plan to address them. With that, many real-world considerations are bought out.
The end result is a richer exposition on design principles and a grounded understanding on how to deal with smells and refactoring in practice.
InfoQ: How did you decide which smells to include in the book?
As mentioned earlier, we had a huge collection of 530 smells. Refactoring improves internal structure, and our focus was on design, and hence we decided to focus only on structural design smells. During our design assessments and when analysing smells in OpenJDK 7, we found that certain kinds of smells are especially common in real-world software. Hence, we decided to limit our focus only on such common smells found in real-world projects. We covered these design smells in our architecture and design training programs - feedback from the architects helped us refine our catalog. This resulted in 25 smells that are covered in this book.
InfoQ: Did you do this by just reading the code or have you used/built tools for this?
We used both manual analysis and analysis tools. Most tool results require manual analysis. For instance, the code clones from JDK is available online. We ran numerous tools (including PMD CPD, Understand, iPlasma, Simian, JArchitect, and Structure101) on the OpenJDK codebase and analyzed the results. Our book also discusses many smells that aren’t detected by widely used analysis tools (Examples: missing hierarchy, unexploited encapsulation). To detect those smells, we wrote scripts in Groovy.
InfoQ: The focus of the book are structural design smells. Do you have any plans for a second book?
This book took three years to complete and was released only late last year. We believe there are a number of new directions that we can embrace from this point. Architectural smells is one such direction; however, we are still in the process of exploring the landscape around design smells, so it is a bit early to predict what we will write about next. We are hopeful that the software engineering community will continue this work and catalog other kinds of smells based on the framework we described in the book (i.e., smells as violation of principles).
InfoQ: After reading your book, how should I start reviewing and refactoring my code?
When designing new software, apply design principles through enabling techniques. When maintaining existing software, identify smells and refactor them (guided by underlying principles the smells violate). We recommend continuous refactoring as part of the development process (i.e., refactor the code while adding any new features or fixing defects). In addition, if you are an architect or team-lead, sensitise the team members about the role of design principles for high-quality software: how violating principles can result in smells and how principles can guide refactoring.
InfoQ: Which is your favorite smell?
Girish: Rebellious Hierarchy – this is a common smell in industrial software and arises because developers don't seem to be aware that they are violating the Liskov Substitution Principle (LSP) while designing a hierarchy.
Ganesh: My favorite smell is Missing Encapsulation smell – it is one of the most widely found smells in real-world software but also a difficult smell for tools to detect automatically. Further, this is one of the smells where design patterns (such as Strategy, Decorator, or Bridge depending on the context) can be used for refactoring.
Tushar: All smells are interesting but the context of the smell in which it occurred, the inherent reason that lead to the smell, constraints imposed on the future design decisions by the smell and the impact of the smell that amplified the effect of other smells is much more interesting and intriguing for me.
InfoQ: Thank you for the interview!
The book's website comes with additional material and related articles (e.g. a checklist for design reviews) and is continuously updated. Designite – a commercial design smell detection tool for C# has adopted the catalog, classification, and naming convention proposed in the book.
About the Book Authors
Girish Suryanarayana is currently a Senior Research Scientist at Research and Technology Center, Siemens Technology and Services Pvt. Ltd. Bangalore, India. Girish received a PhD in Information and Computer Science from the University of California, Irvine, in 2007. His research interests include software architecture, design patterns, design smells, refactoring, cloud computing, and security. He is an IEEE-certified Software Engineering Certified Instructor (SECI) and regularly conducts training for the IEEE SWEBOK Certificate Program (SCP) and IEEE Certified Software Development Associate (CSDA) programs. You can reach Girish via Twitter @girish_sur.
Ganesh Samarthyam has more than 13 years of experience in the IT industry. He is an independent consultant and corporate trainer based in Bangalore. Earlier, he worked for the Software Architecture and Development team in Siemens Corporate Research & Technologies in Bangalore. Before Siemens, he worked in Hewlett-Packard’s C++ compiler team, Bangalore. He has Software Engineering Certified Instructor (SECI) and Professional Software Engineering Master (PSEM) certifications from IEEE. You can reach him through his LinkedIn page.
Tushar Sharma is currently a Technical Expert at Research and Technology Center, Siemens Technology and Services Pvt. Ltd. Bangalore, India. His work at Siemens involves researching and providing consultation on topics related to software design, refactoring, design smells, code and design quality, design patterns, and change impact analysis. He has co-authored two books; his first book "Oracle Certified Professional Java SE 7 Programmer Exams 1Z0-804 and 1Z0-805" published in February 2013 and the second book "Refactoring for Software Design Smells" published in November 2014. You can reach Tushar via Twitter @Sharma__Tushar