Your software sucks if you have the following signs or symptoms:
Rigidity is the tension for software to change. If things are connected in such a complicated way that is hard to make a change, that causes rigidity.
For example, a small change or addition in a monolith can cause changes in several layers in the application. One smell of this example is one day of work, ends up being a one week of work.
Rigidity also causes fragility.
Your code is easy to break. This is a very common symptom. One example can be, if you are using setters and getters in your class definitions and you are consuming your objects through setters and getters. Imagine you have a property which is integer and you decided to make it decimal. If you need to visit several places in your code base to make the necessary changes to have the code compile again, this is a typical sign of bad design.
How about MVC? MVC promises for loose coupling, right? Do you use your models directly in your Views? What happens when you make a change to your model? Do you need to go through a lot of views to make them actually work?
Coupling causes fragility. You can easily spot or recognize the code that is fragile.
If your code is hard to reuse in the same or in different projects, that is immobility. You are not using interfaces enough. Your classes are so focused so that you can’t reuse them or your classes have unnecessary dependencies.
Developers tend to write lot of generic classes or methods for reuse, however, that might cause complexity. Generics are also hard to maintain.
If your software is easy to hack but hard to fix, that is a sign of bad design. When your software requires a change, there is usually more than one way of implementing it. Sometimes, developers preserve the design goals and principles but something they hack their way through. Especially, if maintaining the design goals are challenging. It is usually easy to do the wrong thing but hard to do the right thing.
Everything that is too complicated is destined to fail. We love complicated things and problems. We enjoy it. However, software should be as simple as possible. In my previous post about core software design principles I mentioned about two types of complexity, one is accidental and other is inherent complexity. Inherent complexity is unavoidable, which is the problem domain. We should refrain from accidental complexity, that we make things complicated.
If something is complicated that is almost always bad. Look at technology that people do not use anymore. In java world there was EJB (enterprise java beans). Almost 60 percent of the projects that implemented EJBS didn’t work. 30 percent of remaining was so bad that it required so much time for deployment and configuration. Because, it was all too complicated.
If you have duplicate code and bad structure in your solution or projects, this is a typical symptom of bad design. We have DRY principle that tells you not to repeat yourself. Copy paste is bad. It doesn’t only cause duplication of code but also the effort. In my opinion there is nothing wrong with two lines of method. It is much better than duplication of code. Because, if you have a bug in your code, even a small one, you duplicate it in other places.
If your software is hard to understand, that is a symptom of bad design. This is related to complexity as well. Your code should be clear and easy to understand, not only by you but also by other developers as well.
These are usually the signs, smells or symptoms of bad software design. SOLID principles help for better software design, regardless of the technology you use. There are also other software design principles you can refer to while developing software.