linkedin
Solid Design Principles In Java Development

A solid design approach is a set of five principles in object-oriented programming that are designed to eliminate code rot and improve value, functionality, and maintainability. 

 

Users can develop less coupled code by using SOLID principles.

 

A tightly coupled codebase is dependent on the other.

 

To avoid maintenance and readability problems, it is preferable not to have tightly coupled code bases. 

 

In this section, we give examples of each SOLID principle.

 

SOLID Design Principles: What Are They?

 

 

With an extensive test suite, you can avoid code rot by using SOLID principles at a class-level, object-oriented design. 

 

An acronym for solid design consists of the following five principles:

 

 

 

 

 

 

It is important for developers to adhere to these principles to avoid "code rot," and instead to build applications that provide lasting value to customers and sanity for the future developers of the project.

 

SOLID Design Principles

 

1. Single Responsibility Principle

 

According to the Single Responsibility Principle (SRP), a class should never be changed because of more than one reason.

 

Every class, or similar structure, should only perform one function. 

 

The whole class should revolve around this single goal.

 

However, this does not imply that you should limit your classes to just one method or property. 

 

As long as their responsibilities are related, a lot of members can be involved.

 

It is possible that multiple members of the class may need to be changed when one reason to change occurs. Additional classes may also need to be updated. 

 

ex: 

 

java_img4

 

One class contains all logic related to pay calculation, database logic, and reporting logic.

 

Changing one part of a class that combines multiple responsibilities might be difficult without affecting others. 

 

By mixing responsibilities, it's also more difficult to understand the class and harder to test, resulting in a decrease in cohesion. 

 

A simple solution is to divide the class into three classes, each with only one responsibility: accessing the database, calculating pay, and submitting reports. 

 

2. Open-Closed Principle

 

In general, Open-Closed Principles require classes to be open for additions but closed for changes. 

 

The term "open to extension" refers to the strategy of designing classes to allow new functionality to be added as new requirements arise. 

 

If a class is "closed for modification" it means that you should not modify it once it has been created, except to fix bugs. 

 

It appears that these two parts of the principle are in conflict.

 

You can add functionality without modifying existing code by structuring classes and their dependencies appropriately.

 

Instead of using concrete classes, you should generally refer to abstractions for dependencies like interfaces or abstract classes.

 

A new class that implements the interfaces can be used to add functionality. 

 

Once your source code has been written, tested, and debugged, the OCP restricts you from changing it. 

 

By doing so, the risk of adding new bugs to existing code is reduced, resulting in more robust software. 

 

ex: 

 

The use of interfaces for dependencies has the additional benefit of reducing coupling (i.e. change in class A forces changes in class B) and enhancing flexibility.

 

java_img1

 

Would it be possible to add credit card support with an "if" statement like this? That would violate OCP, though.

 

java_img2

 

This is the perfect solution:

 

java_img3

 

Be aware that OCP only applies when the change to come is predictable, so only use it if a similar change has already occurred.

 

The easiest thing to do is to start simple and then find out what changes will be requested so you can better predict the future.

 

In other words, you need to wait for a customer to make changes and then make abstractions that will protect you against a similar change in the future.

 

3. Liskov Substitution Principles

 

Liskov Substitution Principle (LSP) states that you should design classes in an inheritance hierarchy in such a way that client dependencies can be replaced with subclasses without the client having any knowledge of the change. 

 

Therefore, all subclasses must function in the same way as their base classes.

 

Subclasses may have different functionality, but their behavior must be in line with that of the base class. 

 

It should also follow the implied behavior of the base class, in order to be considered a true behavioral subtype.

 

LSP is generally violated if a subtype of a supertype does something the supertype's client does not expect.

 

Think about a derived class throwing an exception that the superclass would not throw, or having a derived class with unexpected effects.

 

The basic rule is that derived classes should never do less than their base classes. 

 

An example of a class deriving from a Rectangle class that violates LSP is a Square class. When the Square class is applied, the width and height are always equal. 

 

Using a Square in a context where a Rectangle is expected may cause unexpected behavior since Squares cannot (or rather should not) be modified independently.

 

ex: 

 

There is no easy fix for this problem. If the setter methods in the Square class can be modified so that they preserve the Square invariant, then this will weaken the post-conditions necessary for the Rectangle setters, which implies that dimensions can be modified independently. 

 

java_img5

 

As you can see above, the LSP is violated.

 

java_img6

 

Undefined behavior is caused by violations of LSP, which can lead to weeks of wasted time trying to locate the problem.

 

4. Interface Segregation Principle

 

Clients shouldn't be forced to rely on interface members they don't use according to Interface Segregation Principle (ISP).

 

ISPs guide us to creating multiple, smaller, cohesive interfaces when there are non-cohesive interfaces.

 

With ISP, classes communicate through tightly-focused interfaces, so you minimize dependency on unused members and thus reduce coupling.

 

The implementation of smaller interfaces improves flexibility and reuse ability.

 

By sharing interfaces among fewer classes, the number of changes required to respond to a change in an interface is reduced, resulting in higher robustness.

 

ex:

 

What if we had an ATM that has a screen where various messages can be displayed. If we wanted to add a message that appears only during withdrawals, how would that work? 

 

If you were to add an interface method to the Messenger interface and be finished with it, you would have to recompile almost the entire system, which would violate OCP. 

 

The issue was that adjusting withdrawal functionality caused changes to other totally unrelated functions as well, and now we are wondering how this happened. 

 

The issue really arises from the fact that each function that uses this Messengers interface is dependent upon methods it does not need but is necessary for other functionality. Let me show you.

 

 

It would be better if you split up the Messenger interface so that each ATM function requires its own Messenger. 

 

java_img8

 

5. Dependency Inversion Principle

 

High-level modules should not depend on low-level modules, they should depend on abstractions, according to the Dependency Inversion Principle. 

 

In addition, abstractions should not rely on details; details should rely on abstractions.

 

Essentially, we separate our class from the rest by forming a boundary with the abstractions the class depends upon. 

 

As long as all the details behind those abstractions remain the same, the class is still safe.

 

As a result, this keeps coupling low and allows us to change our design more easily. DIP also allows us to test things separately. 

 

ex:

 

The reader and writer interfaces in a program are abstractions, and the keyboard and printer are details based on the abstractions.

 

As CharCopier is oblivious to the low-level details of Readers and Writers, it works with any device that implements the Reader and Writer interface. 

 

java_img9

 

CONCLUSION

A solid understanding of solid principles should be considered when designing your next feature or application, one of the valuable tools in your toolbox. 

 

Work with world leading tech businesses

We connect high-performing software engineer talent in the Philippines with some of the world’s leading and most innovative Tech companies.

Submit CV
career3

Author

Jake_Hall_Feb2021-11
Jake Hall
Chief Technology Officer
Work with world leading tech companies from the Philippines

Be up to date!

Sign up for our newsletters and get our latest outsourcing and tech news, and exclusive promotions.

Cloud-employeeCover

If you’re interested to know more about our employee benefits and perks, you can download the booklet.

Download Now

Submit your CV today

One of our recruitment officers will get in touch with you!

    Our live jobs

    • Senior Front - End Developer - ANGULAR 6+

      Work with a leading UK company that works across multiple verticals within professional services globally, and has a skilled development team of 70 working remotely, operating across multiple continents. This is an outstanding opportunity for interested candidates to join a diverse team of experts, utilising some of the newest leading practises within frontend development.

    • Senior Full-Stack Ruby on Rails Developer

      A UK based award-winning Edutech platform business, working with Health & Social care organisations to ensure front line teams are fully trained and ready to help those in need. The company has seen an explosion of traction since Covid and their vision is to help save people’s lives.

    • Ruby on Rails Developer

      As the sole developer in the team, you'll lead on all aspects and have a leading hand in shaping the future of the platform, working from back to front and playing a crucial part in the design, development and production of quality code. We're a close knit, remote working team and as such, you'll need to be self motivated and goal driven to keep everything moving at pace.

    • Senior PHP / Laravel Developer

      A leading UK company and is rapidly growing and recognised for their innovative service capabilities. With a legacy of many years at the forefront of the technology industry, they operate both nationally and internationally and place a premium on honesty, commitment and teamwork. With a solution strategically designed to support the ever-changing needs of service providers.

    • Senior Fullstack.Net Developer

      The company offers product and service stack presents end-to-end solutions for travel agents, tour operators, loyalty brands, hotels, conference destinations, OTAs and tourism organisations.

    • React JS Developer

      UK Company specialises in CRM memberships and subscription end clients.

    • Senior C++ Developer 14/17

      A UK leading institutional-grade exchange for trading asset-backed tokens (digital securities, security tokens, etc.).

    • React JS Developer

      A leading UK company well established in creating content apps and websites for their clients.

    • Dynamics 365 Expert

      IT and Microsoft Gold Partner specialising in Azure, Microsoft 365 and Dynamics 365.

    • Full Stack Developer - React & .Net

      IT and Microsoft Gold Partner specialising in Azure, Microsoft 365 and Dynamics 365.

    How many hours do you want the developer to dedicate to working with you?

    What skillsets are you looking to hire?

    When do you need your developer to start ?