Design Principles in Java
In Java, the design principles are the set of advice used as rules in design making. In Java, the design principles are similar to the design patterns concept. The only difference between the design principle and design pattern is that the design principles are more generalized and abstract. The design pattern contains much more practical advice and concrete. The design patterns are related to the entire class problems, not just generalized coding practices.
There are some of the most important design principles are as follows:
SOLID Principles
- SRP
- LSP
- ISP
- Open/Closed Principle
- DIP
Other Principles
- DRY Principles
- KISS Principle
- Composition Over Inheritance Principle
Let’s understand all the principles one by one:
DRY Principle
The DRY principle stands for the Don’t Repeat Yourself principle. It is one of the common principles for all programming languages. The DRY principle says:
Within a system, each piece of logic should have a single unambiguous representation.
Let’s take an example of the DRY principle
Both Dog and Cat speak differently, but they need to eat food. The common functionality in both of them is Eating food so, we can put this common functionality into the parent class, i.e., Animals, and then we can extend that parent class in the child class, i.e., Dog and Cat.
Now, each class can focus on its own unique logic, so there is no need to implement the same functionality in both classes.
After compile and run the above code, we will see the following output:
Output:
Eat food Cat Meow! Eat food Dog Woof!
Violation of the DRY Principle
Violations of the DRY principles are referred to as WET solutions. WET is an abbreviation for the following things:
- Write everything twice
- We enjoy typing
- Write every time
- Waste everyone’s twice.
These violations are not always bad because repetitions are sometimes advisable to make code less inter-dependent, more readable, inherently dissimilar classes, etc.
SRP
SRP is another design principle that stands for the Single Responsibility Principle. The SRP principle says that in one class, there should never be two functionalities. It also paraphrases as:
The class should only have one and only one reason to be changed. When there is more than one responsibility, there is more than one reason to change that class at the same point. So, there should not be more than one separate functionality in that same class that may be affected.
The SRP principle helps us to
- Inherit from a class without inheriting or implementing the methods which our class doesn’t need.
- Deal with bugs.
- Implement changes without confusing co-dependencies.
LSP
LSP is another design principle that stands for Liskov Substitution Principle. The LSP states that the derived class should be able to substitute the base classes without changing our code.
The LSP is closely related to the SRP and ISP, So, violation of either SRP or ISP can be a violation (or become) of the LSP. The reason for violation in LSP because if a class performs more than one function, subclasses extending it are less likely to implement those two or more functionalities meaningfully.
DIP
Another most important design principle is DIP, i.e., Dependency Inversion Principle. This principle states that the low and high levels are decoupled so that the changes in low-level modules don’t require rework of high-level modules.
The high-level and low-level modules should not be dependent on each other. They should be dependent on the abstraction, such as interfaces. The Dependency Inversion Principle also states that the details should be dependent on the abstraction, not abstraction should be dependent on the details.
KISS Principle
It is another designing principle that stands for Keep It Simple and Stupid Principle. This principle is just a reminder to keep our code readable and simple for humans. If several use cases are handled by the method, we need to split them into smaller functions.
The KISS principle states that for most cases, the stack call should not severely affect our program’s performance until the efficiency is not extremely important.
On the other hand, the lengthy and unreadable methods will be very difficult for human programmers to maintain and find bugs. The violation of the DRY principle can be done by ourselves because if we have a method that performs more than one task, we cannot call that method to perform one of them. So, we will create another method for that.
ISP
ISP is another design principle that stands for Interface Segregation Principle. This principle states that the client should never be restricted to dependent on the interfaces that are not using in their entirety. This means that the interface should have the minimal set of methods required to ensure functionality and be limited to only one functionality.
For example, if we create a Burger interface, we don’t need to implement the addCheese() method because cheese isn’t available for every Burger type.
Let’s assume that all burgers need to be baked and have sauce and define that burger interface in the following way:
Now, let’s implement the Burger interface in VegetarianBurger and CheeseBurger classes.
The VagitarianBurger has Cabbage and Tomato, whereas the CheeseBurger has cheese but needs to be baked and sauce that is defined in the interface. If the addCheese() and addTomatoandCabbage() methods were located in the Burger interface, both the classes have to implement them even though they don’t need both.
Open/Close Principle
Open/Closed Principle is another important design principle that comes in the category of the SOLID principles. This principle states that the methods and objects or classes should be closed for modification but open for modification. In simple words, this principle says that we should have to implement our modules and classes with the possible future update in mind. By doing that, our modules and classes will have a generic design, and in order to extend their behavior, we would not need to change the class itself.
We can create new fields or methods but in such a way that we don’t need to modify the old code, delete already created fields, and rewrite the created methods.
The Open/Close principle is mainly used to prevent regression and ensure backward compatibility.
Composition Over Inheritance Principle
The Composition over inheritance principle is another important design principle in Java. This principle helps us to implement flexible and maintainable code in Java. The principle states that we should have to implement interfaces rather than extending the classes. We implement the inheritance when
- The class need to implement all the functionalities
- The child class can be used as a substitute for our parent class.
In the same way, we use Composition when
- The class needs to implement some specific functionalities.