Design models are not blueprints


Recently I needed to create some code to do the automatic wiring of dependencies using Java annotations. The annotation had an optional parameter specifying a name; if the name was missing, the dependency would be wired by type match.

So of course the basic logic ended up looking like:

private void wireDependency(Field field, Class annotation, Object o) {
  if (!wireByName(field, annotation, o)) {
    wireByType(field, annotation, o);
  }
}

It falls into the “as simple as possible, but not simpler” category. But I would also say that this is an implementation of the Strategy model.

Immediately I sense some objections. The strategy model makes algorithms interchangeable! Policies must implement an interface and each exists in a separate class, so new ones can be added more easily later! In other words:

That’s all well and good, but that brings me to the title of this article, which is that design patterns are not blueprints. A role model is a way of thinking about something and a way of communicating about something. To follow the example of implementing a model without thinking is as silly as doing something else without thinking.

In this case, it would be possible to define a WiringStrategy interface with a wire() method. Then each type of wiring could be a separate class. Top-level logic could get a list of WiringStrategy instances and work on each one until one is successful. This way we could add new ways of wiring without having to make any changes to the existing logic.

But what would we have saved? We still need to add new code to add new wiring strategy. And the list of strategies should still be updated. (In the worst case scenario, we would have really gone wrong with software coding and externalized the list of policies to a configuration file. Even then, we need to update something somewhere.) So the benefits of following the “plan” for the strategy template seem pretty minimal.

And what are we giving up? Previously, someone reviewing and maintaining this code would see two method calls with obvious purposes and understand the priority between them. If we move to separate classes and list in the name of flexibility, the poor maintainer now has to go to several places to figure out what the code is doing. It doesn’t seem worth it.

It may seem like an artificial example, but I have personally witnessed such serious cases. Sometimes this is the person who is convinced that the “magic numbers” in the code are bad, but those same numbers defined as a constant and used once, or loaded from a config file and used once, are sort of OK. Config files have their place, but when they come with the code and are not meant to be updated by the user, it takes as many steps to update the value in the config file as to update it in code. Other times, it is the person who feels the need to move all instantiations of objects to a factory, even though the code calling the factory must provide all the context necessary to instantiate the object, so there is no really has no encapsulation going on.

Ultimately, all of our design patterns and best practices are designed to form our minds so that we write good code. They are not meant to be a substitute for thought. Best users of design models don’t have to label their classes AbcFactory Where XyzStrategy Where AbstractProxyVisitorImpl because the use of the design template is inherent (and maybe even invisible).

As the wise programmer says in the Programming Tao, “Technique? What I am is Tao – beyond all techniques!”


Source link

Previous Collaborators and Libraries: Java Design Patterns for Success
Next Design models are blueprints - Java DZone

No Comment

Leave a reply

Your email address will not be published. Required fields are marked *