Daniel Pitts’ Tech Blog

Posts Tagged ‘decoupling’

Assembly line: Separation of concerns with Inversion of Control.

Friday, February 1st, 2008

If you decide to go the route of using Inversion of Control and Dependency Injection, it can make your program a lot more flexible. If you do this manually, you’ll find that even a complex system can be managed well this way.

A common idiom is to use Dependency Injection to separate the creation of the object from the use of the object. The client object has some way to receive other objects it needs to “talk” to, but the client object doesn’t care how they were created:

class MyClient {
   MyFooService fooService;
   MyBarService barService;
   public MyClient(MyFooService fooService, MyBarService barService) {
      this.fooService = fooService;
      this.barService = barService;
   }

   public void doStuff() {
      fooService.iLikeFooFighters();
      barService.buyRoundsForEveryone();
   }
}

From this code snippet, FooService and BarService could be interfaces, abstract classes, or even concrete classes. If you change your mind later about them, MyClient doesn’t have to change at all

Another common approach for DI is to use setter based injection. This approach is useful for complex object graphs that have cyclic dependencies. I’ll leave it as an exercise for the reader to re-write MyClient with setters.

So, in this phase one, you’ve separated the concern of object creation and wiring from object usage. It is perfectly acceptable to stop here. However, depending on how complicated your object system is, you may wish to separate the concerns even further. You can do this via the Builder pattern (nb. The current Wikipedia entry on Builder pattern is incorrect and misleading.)

With the builder pattern, you separate the concern of creation from the concern of “wiring”. The builder accepts a series of objects that belong in a graph. The builder knows how to connect the objects through DI, but doesn’t care where the objects came from or how they were created/configured.

In a recent project of mine, I had to create a Robot instance, and wire it with a lot of components. To make things worse, some of the components also needed sub-components, and some components needed to know about other components, and some needed to know about the robot itself. I had successfully created a class that would create the components and wire them together, but it was a bit fragile (do things in the wrong order and you get an NPE, since not all of the components were created yet).

To solve this design issue, I created a class (HardwareContext), which held a reference to every component that it takes to build a robot. Those fields were populated using setter based dependency injection. Once those references are all created, hardwareContext.wireRobot() is called, and that is where all of the object graph is connected. This would allow me to create a new hardware context that wired the components differently if I needed to. It also allows me to create a new HardwareSpecification (the class that creates components), which creates different configurations for the robot.

This leads to a highly extensible and configurable system. It also makes it easy to figure out where to add a line of code. If the line is doing wiring, it goes into the Context, if it is creating an object, it belongs in the Spec. Easy, clean, clear.

The Art of Decoupling.

Monday, December 3rd, 2007

Some people think the power of OO design is that the classes represent real-life concepts that are easier for a human to understand. Others think that its power comes from code reuse. Still other just accept OO as the paradigm that they are supposed to use, simply because they were told so.

The truth is that using any of those approaches to design may well leave you with a brittle, unmanageable, ugly mess. Personally, I strive for the “real-life concepts” as one top-level goal. The other top level goal is decoupling. Transcending all goals, of course, is creating a “correct” program. Not necessarily “correct” in the academic sense. I don’t verify every algorithm I use, and I don’t necessarily determine valid pre/post conditions. I mean correct in as much as, it works for what I need it to work for.

For small programs, this is pretty easy. When you get to larger systems, this becomes a slightly different problem to solve. In the days of goto, spaghetti code arose due to poor organization and ad hoc control transfer. Structured programming helped some by organizing the control codes into a set of well-defined idioms. Object oriented programming helped further by organizing responsibility into encapsulated modules. All of these paradigms had something in common; you could write brittle code or malleable code in any one of them. Granted, writing flexible code has gotten easier with Object Oriented programming, but only if you know what makes code brittle.

Over dependence of one section of code on another section of code. In software engineering, we call this coupling. If the behavior of A is dependent on the behavior of B, then A is dependent on B. Changing the behavior of B could change the behavior of A. This isn’t always a bad thing, but if A and B are written by different people (or the same person at different times) with different goals, it could be catastrophic. It isn’t always feasible to decouple two classes, or two methods, or even two lines of code, but if you can do it easily, consider what might be gained by that.

One syndrome I’ve noticed is that with any concept, some people take it to the extreme. For those readers who stopped at the above paragraph and decided I was right, and everything should be as decoupled as possible, you might see a design that I would call disintegrated. It is possible to create code that is so decoupled as to be impossible to figure out how one thing affects another, even though the overall system is design for A to affect B. Don’t do this :-)

One approach to decoupling two classes is to have them communicate through an event system. This will couple them both to the event system, but not to eachother. This approach allows you to replace one of the pair without changing the other side at all. This makes a lot of sense for GUI applications, for example, where user interactions with the component (such as a button) generates an event that can be handled very differently, depending on the needs of the program. Most object oriented languages, and Java in particular, already has a useful mechanism for invoking behavior on other objects. Its called method invocation, the act of making a method call. Event systems are useful for decoupling the method call from the class that needs to know about the call, its not so useful as a replacement for normal method invocation.

There are plenty of other ways to decouple you code (often through use of patterns), but I won’t get into them here. GIYF

Software design is about making difficult choices. If you didn’t have to make choices, then it would be easy to create a simple program that can design software. Your job as an engineer is to decide what should be decoupled from what. Decoupling can be a great tool to create a reusable component, but not everything should be designed to be reusable. If you’ve written something that was coupled, but needs to be made reusable… Well, thats what refactoring is for. Decoupling two classes that only communicate with each other can actually add complexity for that use case, so unless you strongly believe that at least one of the two classes will be useful in other situations, it is a waste of cognitive power to separate them.

My goal for production-quality software design? Create the simplest design that meets all my requirements, but is flexible enough to adapt to future requirements.

Primitive Obsession II: (Im)mutability and Redefining Primitive

Sunday, November 4th, 2007

Last week I discussed some of the techniques for and benefits of not using simple “Primitive” values to represent your data. This article is all about taking that concept to the next level.

Let’s say that I have a value that represents an angle. I could use a double to represent the radians, or I could create a class called Angle, which internally might use a double to represent radians. If you are trying to avoid primitive obsession, you would use the latter. Now you have value objects of type Angle which can be used in meaningful ways. So, we’re done, right? I say no.

Angle is now its own form of primitive. Just as an Integer object is an abstraction of a numeric value in a specific set of reals, an Angle instance is an abstraction of a geometric/trigonometric angle. This means that it can be the building block for other more specific types. For instance, a 2 dimensional vector can be represented in “polar form” as an Angle and a Magnitude. In a physical simulation, a Magnitude is often a Distance, so we’ll assume that case for this article.

So, we can create a Vector interface (not to be confused with the java.util.Vector class). We can then create a PolarVectorImpl class which uses Angle and Distance. We can even create a CartesianVectorImpl which uses two Distance objects to represent the vector. Whats more, is these can both be used by anything that expects a Vector, with no extra work in the client code. We can easily create a rotate(Angle) method, or any other useful methods.

Another important and related concept that we haven’t touched on is mutability. If an object is mutable, that means that the apparent state of the object can change over the lifetime of the object. If an object is immutable, the apparent state of the object will appear the same throughout the lifetime of the object. This means that any invocation of one method on that object will always have the same outcome as any other on that same method. Also, any object that is returned from those methods must either be immutable themselves, or be distinct instances. Why is this important? Immutable objects have some benefits.

  • Immutable objects are inherently thread safe.
  • Immutable objects are easy to reason about.
  • Immutable objects are easier to debug.
  • Immutable objects can be passed around freely without defensive copying.

On the down side, immutability makes a pretty boring universe. If you’re object is expected to do different things depending on what has happened to it in the past, that object must be mutable. It must have state.

What does this have to do with primitive values? Its common to create immutable value objects. If we design the Angle class to be immutable, then we can safely say that one instance represents exactly one angle throughout its lifetime. All of our Angle objects are value objects. They are utility objects and reusable in many projects. On the other hand, if we’re doing a simulation of sorts, it might be useful to have a mutable angle, something that we can adjust over time. Lets call this class Heading. What’s in a Heading? An Angle, of course. Now here’s where things get interesting…

Since an Angle is a measurable thing, its easy to compare two values for equality. For Angles specifically, they are equal if their values represent the same geometric angle. Once equality is established, those objects are equal for ever. Not so with Heading. A Heading may represent the same angle at one moment in time, but at another moment they represent very different angles. For this type of object, equality only makes sense for the identity. A Heading instance is its own object, and can be queried/manipulated by many other objects/methods within the project.

The benefit of this design, is a manipulator/querier need not know who “owns” the Heading instance. A Robot might have a Heading, and a SteeringServo might manipulate that Heading. You can create the Robot and the SteeringServo objects independently of each other. The SteeringServo doesn’t even need to know its the Heading of a Robot. Once the Robot and SteeringServo both have the same Heading instance, they become connected without being coupled. This is huge goal for Object Oriented designers/programmers. The correct functioning of a SteeringServo isn’t dependent on the correct functioning of a Robot, or even of a Heading, only on itself. Similarly, a Robot’s correct functioning isn’t dependent on the correct functioning of the SteeringServo. The program as a whole may not work if there is a bug, but it easier to look at one class and ask yourself “Is there anything wrong with this code,” than it is to ask the same question about the whole project.

If you think all of this abstraction is unnecessary or unhelpful, think about all the layers beneath our Heading class. Lets have some fun and break it down into its most primitive parts.

  • Heading instance is an identity value containing an Angle and representing a direction at a point in time.
  • An Angle is an equal-comparable value containing a double and representing a direction.
  • A double is a equal-comparable and order-comparable value containing an ordered set of bits and representing a real number.
  • A bit is an equal-comparable value containing a memory cell representing true or false.
  • A memory cell is often times a capacitor that is either charged or uncharged

If you had to think about the implementation details of a bit every time you used a double, it would make the mental weight of programming so immense that no useful programs could be written. Heading can now be used very easily without adding the mental weight of how its implemented. SteeringServo can be implemented without the mental weight of what it is steering. Overall, the practice of this kind of decoupling will make your program easier for the most important source-code interpreter. You.