views:

48

answers:

1

I have a system I've been working on this week where I'm having a hard time balancing separation of concerns with easy extensibility. I'm adding new types to the system, and it feels like shotgun surgery.

The basic idea is that data is collected (polled) from a remote system and then made available to a number of different kinds of clients. To support their interface type (protocol), I'm doing a lot of translation.

I'm going to try to simplify this so I can fit it in a question box.

There's a FruitService out in the world with an SNMP interface. My publisher's job is to collect that data and then publish it.

  1. So for each kind of new Fruit we decide to publish, I create a class that knows how to pull the attributes for that fruit via SNMP.
  2. Internally Fruit is translated to DTOs (the same objects used to talk to client #1 (RMI)).
  3. A cache is updated and checked for changes to trigger async notifications.
  4. A class to translate the fruit into the xml schema used by another client (#2).
  5. A class to translate the fruit into simple attribute/value pairs used by another client (#3).

In the end I create 5 classes and edit 8 more to plug in a new type. It's not a lot of work; couple hours to write code, test, and check-in for a simple type. Note that there isn't a lot of commonality in the fruit types (e.g.: pear and coconut), so most of the common abstractions are based around the process of updating the data and not the data itself.

My design concerns are:

  1. The SNMP interface changes 2-3 times a year
  2. The xml schema (client 2) changes 10 times a year.
  3. Adding new types happens less frequently, generally when someone gets around to it. But maybe if it was easier...

So the notional goal with the design was to handle those external changes easily. This lead to all the separation in the translation layers. But adding types feels harder than I'd like.

Is there a technique or example I might look into? An idea I'm missing? Am I applying SRP wrong and there should be an Apple type that speaks SNNP, xml schema, DTO, etc?

alt text

+1  A: 

My first impression is that your design needs some refactoring to be more object oriented. You have different types for different structures, however the behaviour is important. If it is possible rather than creating new Fruit type, describe generic Fruit structure and create objects for concrete Fruit. This way you can include behaviour which will describe the structure in Fruit and create generic translation classes, which will just use the information about the structure to create the 8 objects you need when you add new fruit type. This could be done also using metaprogramming, but depends on your language and skills and effort needed to create something like that.

So the idea is to translate Coconut.getMilk() and Pear.getSeeds() into Fruit.getAttributes() and so on. Does this help a bit?

Gabriel Ščerbák
It really depends on the client. Two of them are interested in just displaying some information about generic fruit. One is interested in only Pears and wants to see every possible detail about that pear without any information about coconuts. What I think you're describing is essentially what's done in my translation layers for client #2 and #3, but client #1 benefits from a pear-specific object with pear-specific domain concerns.
Steve Jackson