I have recently refactored a piece of our product to improve its maintainability. It was a part responsible for (1) receiving messages from outside of the system, (2) calculating appropriate operation and optionally (3) adjusting the data in the database.
Unfortunately, the code was a total mess:
switch
with a branch for each mode of operation.public class UglyService {
@EJB
private EquallyUglyService otherService;
public void processMessage(Message msg) {
// ...
}
public boolean isOpen(Message msg) {
return msg.getStatus() == Status.OPEN;
}
public void doSomething() {
otherService.doSomething();
}
public void updateCase1(Entity ent, Message msg) {
if (/* conditions */) {
ent.setSomeProperty(msg.getPropertySource());
}
}
public void updateCase2(Entity ent, Message msg) {
if (/* other conditions */) {
ent.setSomeOtherProperty(msg.getOtherPropertySource());
}
}
}
What I did was:
switch
statement
and only use original enumeration to request a specific strategy
from a factory. Each of them implemented an interface.public class SlightlyBetterService {
public void processMessage(Message msg) {
MessageAdapter ma = MessageAdapter.wrap(msg);
Entity original = retrieveOriginal();
// Adjuster is usually a composite of several different
// strategies responsible for updates of different properties
// of the object
Adjuster adjuster = ma.produceAdjuster();
adjuster.adjust(original);
}
}
With the above enhancements, it is easy to introduce new actions, each of them is easy to test and if the objects (messages) received by our system change, only the adapter needs to be adjusted.
That was fun!
This work by Piotr Mieszkowski is licensed under CC-BY-SA 4.0