shemp has asked for the wisdom of the Perl Monks concerning the following question:

This is more of a software design question, but it is being implemented in perl, so hopefully not too OT.

I have a class called DataManager which is a reader and/or writer for some specific types of data that our company deals with. (the format is immaterial to this discussion). I also have a collection of funcitonal programs that do a variety of reports on the data, but dont currently use the DataManager. This is a side effect of 2 programmers (myself being 1) not coordinating our projects very well in the past, and various shortsighted, partial upgrades.

I am creating a collection of reporter classes so that our data processing cycle can run more smoothly, and all have a common codebase.

So the real question is this. The reporter modules will be general enough that they can be used for things other than what the DataManager specifically deals with, so i am struggling a bit with the interaction between the reporters and the DataManager.

The Reporter will need to be fed the records in the DataManager in one way or another. One thought is to have the DataManager feed the Reporter directly, but if i do this, other things that use the Reporter will need to have their own methods to spoon-feed the Reporter.

Also, i could have the Reporter know how to get the data out of the DataManager and let the Reporter get the data itself. This sounds like a very bad plan, because then the Reporter will be forever tied to the DataManager - so no.

The third thought is to have no direct interaction between the 2 parts, and have an interface function that coordinates the 2. Then a different interface function will be needed for other DataManager like modules.

The first and third ideas dont seem very different to me, and im leaning toward the first, but i think i might not be seeing the whole picture yet.

I hope my question is clear, ask for clarification, flame me, whatever. Thanks :)

Replies are listed 'Best First'.
Re: Designing a thin interface
by skyknight (Hermit) on Jun 24, 2004 at 20:01 UTC

    I have three words for you: Model, View, Controller. You want to split your application framework up such that it makes solid distinctions between these three categories of code.

    Model refers to the underlying data in your system. It includes your classes that embody any and all collections/associations of data.

    View refers to the various ways in which data is rendered either to users or other systems. It includes your filters, formatters, mungers, etc.

    Controller refers to the mechanisms that mediate interactions between all players in the system, namely Users, the Model, and the View. It's job is to accept input from Users, load things from the Model, feed that stuff through the View, hand the result to Users, and repeat.

    If you do a good job making these distinctions, then you will be able to plug the components of your system together in myriad unpredicted ways, making it highly flexible and extensible.

    As an example, think of an Apache/mod_perl web application framework for delivering finance reports... The Model will consist of the classes that embody various financial thingies. The View will consist of the classes that accept things from the Model and format them into pretty HTML for PHBs to look at in Internet Exploiter. The Controller consists of the Apache handlers that parse the incoming URLs, load the requested objects, pipe them through the appropriate View classes, and then forward the results of the View to the User.

Re: Designing a thin interface
by shemp (Deacon) on Jun 24, 2004 at 23:12 UTC
    I very much appreciate the comments. A little part of brain is saying that i misrepresented the question a bit though. Both of these subsystems DataManager and Reporter are low level, related parts of a generalized data crunching system, and are both part of the processing.

    So i guess i keep thinking that the interaction (API) that im working on designing is at a lower level than what has been discussed. (maybe not) I am almost entirely self taught - have been programming Perl for 10 years, but my big design projects are designed via my own methods, which are mostly bits and pieces of formal (academic) design philosophies.

    On the statement of considering fixing all the code right now - thats exactly what the current crusade is. My boss has been too busy to give me any direction, so since mid april , i've been working under the instructions 'do whatever you think needs doing'. (its our companys off season, so there isnt a lot of time critical work - just retooling).
    Its a great place to be these days
Re: Designing a thin interface
by bilfurd (Hermit) on Jun 24, 2004 at 23:05 UTC
    skynight has the right idea in this case.

    As an interrim step, you can create an interface to sit between the Reporter and DataManager to handle business rules, etc. I've had to do a couple of these to handle data between different packaged products in the past.

    This is not the best solution -- you would be best served by taking/making the time to finalize the code. Having said that, I will admit to having several bits of code that I have wanted to perfect for a few years now. You never know when you will have the time to do it right, so consider doing it right now.

    Good luck!

Re: Designing a thin interface
by stvn (Monsignor) on Jun 25, 2004 at 16:18 UTC

    You might try looking at some of the classic Design Patterns, your problem could be solved (possibly) by any number of them. For instance, several of the Structural patterns might do the trick:

    • The Adaptor Pattern
      Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
    • The Facade Pattern
      Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
    • The Proxy Pattern
      Provide a surrogate or placeholder for another object to control access to it
    Or possibly even these more Behavioral patterns:
    • The Command Pattern
      Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
    • The Mediator Pattern
      Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
    NOTE: these links are to a C# specific site, but the UML they show and the patterns they describe are langauge independent.

    In my current project, I have solved something similar by using the Mediator pattern (and a little bit of the Command pattern as well). I have a number of Report classes, each which takes a Calculation class, a Graphing class and a Request (which is where the Command pattern comes in) and then makes various calls to the Calculation modules with data in the Request, and then feeds the results to the Graphing class and then returns its output.

    This allows me not only to vary the interactions of the Calculation and Graphing modules (similar maybe to your DataManager and Report), but also to re-use a my Calculation classes in a number of different situations, as well as easily allow me to add, modify and subclass my Graphing modules.

    -stvn
      Good advice, looks like i'll have to dust off my design patterns book. :)