views:

344

answers:

4

How does one design loosely-coupled systems which may often require data from each-other but don't necessarily belong in the same category?

For instance, lets take the old Pet-shop example one-step further and create a pet-store franchise. Each pet-store has its own website listing their contact information, promotions, and current stock.

The franchise owners want to have a listing of all the franchised pet-stores along with contact information and possibly a few photos available on their corporate site. They want to be able to update this information, and have any updates pushed automatically both-ways. They also want to provide the promotions information to all stores' sites in an automated way.

So, in this instance the stock lists are "owned" by the stores, and the contact information is part-"owned" by both entities, and the promotion information is "owned" by HQ. Due to arbitrary reasons all this data can't be stored in the same place.

Are there some best-practices or common strategies for coping with a situation like this?

+1  A: 

Hi Phillip, My understanding is that this kind of problem is most often addressed using a technique called "data federation" -- the independent entities function independently, but there exists an umbrella-like entity that provides ability to look at the system as a whole.

Here's an article that may be useful: http://www.soamag.com/I22/0908-1.asp

When planning your architecture, keep in mind what happens when one of the participants is unavailable. For example, I would recommend that the promotion information be replicated to all stores, either as a batch process, or when the reference data changes. That way if the network goes down, the individual stores still have promotion information and can function.

SquareCog
+1  A: 

I've been thinking about that problem, and I express it by saying that the relationships between classes are contextually determined. And any model that assumes global static associations (inherent coupling) between classes is problematic.

Another example I like to use is Products.

A Product can play a bunch of different roles. It's associated with an OrderItem, which is associated with an Order, which is associated with a Customer.

It's provided by a Vendor.

It's in a Catalogue, maybe by Section and Page.

It's the responsibility of a Buyer, with availability from multiple Vendors.

The ability to handle this complexity easily is the fundamental benefit of the Relational data model; and I've not seen it well dealt with in terms of OOP.

Aside: There's another ORM (Object Role Modeling, see VisioModeler, InfoModeler, etc.) that looks at the question from the Relational side, quite usefully (IMHO).

When you isolate yourself from the relationality of the database (by using CRUD generators, ActiveRecords, etc.) you are hiding this important aspect. (I think LINQ has the same problem, as well as introducing fundamental coupling problems, but I haven't worked it out very completely yet.)

I think you can successfully work your way through it if you're careful, but it becomes easy to embed coupling in the design, especially if you work from the database back to the rest of the application, rather than the other direction.

le dorfier
+1  A: 

It seems SOA can be helpful in this case. I specifically mean business-level SOA as described by e.g. Bill Poole and Udi Dahan with pub-sub async event-based implementation.

You described several business functions with separate owners: Franchising and Sales. You want to achieve loose coupling between them.

In SOA way you define Franchising service, and several instances of Sales services, one for each shop. Shops are initially very similar, but can evolve separately.

Then you define business events of mutual interest that occur in these services. Franchising service can publish NewPromotion event that all Sales services subscribe to. This event message contains all details about promotion, and consumers pick what they need. Sales service in turn publishes ContactDetailsChanged event to be consumed by Franchising.

Each service has its own multi-tier implementation on the inside, complete with database, customer-facing web site, private integration points with other systems etc.

Each service stores privately all the data it is interested in: stock lists, contact information, promotion information - in the form it finds suitable. Updates to information in one service propagate to other services through events.

On the implementation side you need some kind of service bus between service, with support for durable messaging over unreliable internet, e.g. NServiceBus. No WebServices(tm) necessary.

Your services are loosely coupled in implementation, because they share only contracts (description of messages and endpoints they publish) and can evolve internal representations independently. They are also loosely coupled in time, because if at no point they send each other synchronous requests that can time out over internet. All messaging is handled by infrastructure (service bus).

Hope this helps :)

Alexander Abramov
A: 

I mostly agree with the above proposed solution (using SOA). ESB might be a good approach depending upon the complexity of the application. But, I think that ESB has a large footprint and brings unnecessary complexity for most real-world applications.

But, IMHO any good Architecture should be easily adaptable to Applications servers without major architectural/design changes.

Assuming a Java-based medium-large scale n-tier application, here are my suggestions for the middle-tier and EIS-tier:

  1. Separate each of the subSystem implementations and expose it's functionality through a service interface and hide the implementations from directly used or referenced.

  2. Create one JAR (or EAR) file for each of the subSystems and determine the runtime and compile time dependencies between the above identified subSystems/JARs.

  3. Invest a good amount of time in determining the correct granularity of the service interface methods and the subSystem dependencies.

  4. During this effort, try to identify the DAO layer (assuming that a DB is involved) for each of the modules and separate the database tables for each of the SubSystem.

For the web-tier, try to do the same as above by partitioning the presentation layer by subSystems. Create one WAR file per each of the subSystems. Try to put the presentation layer WAR in to the appropriate EAR file identified above, if necessary.

A good validation of this above architecture is to deploy this in OSGi using each of the services as OSGi service (after creating the appropriate manifest files).

Keep in mind that event-based/asynchronous communication can be setup between any of these subSystems too, if necessary.

This gives an opportunity to split the subSystems and deploy them in different farms of servers for better scalability opportunities.

Good luck..!