Notes (3)
Notes (3)
Poorly designed applications can lead the team to very difficult situations
when the application scope goes up, or the implementation faces certain
design issues either in production or maintenance.
On the other hand, a set of well designed and written classes can speed up
the coding process, while reducing the tech debt and the number of bugs in
comparison.
In other words, we should write, change, and maintain a class only for one
purpose. A class is like a container. We can add any amount of data, fields,
and methods into it. However, if we try to achieve too much through a
single class, soon that class will become bulky. If we follow SRP, the
classes will become compact and neat where each class is responsible for
a single problem, task, or concern.
Example
We can find plenty of classes in all popular Java libraries which follow
single responsibility principle. For example, in Log4j2, we have different
classes with logging methods, different classes are logging levels and so
on.
In the given example, we have two classes Person and Account. Both
have single responsibility to store their specific information. If we want to
change the state of Person then we do not need to modify the
class Account and vice-versa.
Person.java
OCP is the second principle which we should keep in mind while designing
our application. It states:
If other developers are not able to write the desired behavior due to
constraints put by the class, then we should reconsider refactoring the
class.
I do not mean here that anybody can change the whole logic of the class,
but one should be able to override the options provided by software in a
non harmful way permitted by the software.
Example
If we take a look into any good framework like struts or spring, we will see
that we can not change their core logic and request processing, but we
modify the desired application flow just by extending some classes and
plugin them in configuration files.
Example
Spring can register one property editor for one data type and it is required
to follow the constraint mandated by base
class PropertyEditorSupport. So if any class
extends PropertyEditorSupport class, then it can be substituted by
everywhere the base class is required.
For example, every book has an ISBN number which is always in a fixed
display format. You can have separate representations of ISBN in database
and UI. For this requirement, we may write property editor in such a way –
IsbnEditor.java
import java.beans.PropertyEditorSupport;
import org.springframework.util.StringUtils;
import com.howtodoinjava.app.model.Isbn;
public class IsbnEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
setValue(new Isbn(text.trim()));
} else {
setValue(null);
}
}
@Override
public String getAsText() {
Isbn isbn = (Isbn) getValue();
if (isbn != null) {
return isbn.getIsbn();
} else {
return "";
}
}
}
NO. He will have to implement both the methods, out of which one is an
extra burden put on him by the designer of the software. Either he will
implement another method or leave it blank. This is not a good design.
The best place to look for IPS examples is Java AWT event handlers for
handling GUI events fired from keyboard and mouse. It has different
listener classes for each kind of event. We only need to write handlers for
events, we wish to handle. Nothing is mandatory.
FocusListener
KeyListener
MouseMotionListener
MouseWheelListener
TextListener
WindowFocusListener
Anytime, we wish to handle any event, just find out a corresponding listener
and implement it.
MouseMotionListenerImpl.java
public class MouseMotionListenerImpl implements MouseMotionListener
{ @Override
public void mouseDragged(MouseEvent e) {
//handler code
}
@Override
public void mouseMoved(MouseEvent e) {
//handler code
}
}
Dependen
Most of us are already familiar with the words used in principle’s name. DI
principle says:
In other words. we should design our software in such a way that various
modules can be separated from each other using an abstract layer to bind
them together.
Example