mercredi 25 février 2015

Problems with OO design for application with pluggable components

I'm trying to refactor an ugly code and make it easly extendable in the future.


The application should be nothing else but a series of components that have input(s) and output(s). The components are chained in such manner that the current component's input is the output of one (or more) previous components.


Here's a quick overview of what I have so far:




  1. Reader



    • Denotes a data source

    • Can be a file on HDD, online resource, database, etc.




  2. Splitter



    • Input is Reader(s)

    • Splits the contents of what reader delivers into parts

    • Outputs are split contents of Reader(s)




  3. Model



    • Input is Splitter(s)

    • Creates a model of something based on Splitter(s) outputs

    • Output is silent, but you can say that the output is an internal state that can be queried for individual inputs




  4. Tester



    • Input is a model

    • It can query a model for a result on some data

    • Output is optional, but in case it is used, it's a stream of (queryInput, queryOutput) data




  5. Writer



    • Input is practiacally anything that produces a collection of objects

    • Writes that collection to wherever

    • I dunno what the output should be right now




So, I want to do have the ability to plug them in the following manner:


-->Reader-->Splitter-->Model-->Tester-->Writer-->


However, this would also be a valid combination (it obviously does nothing more but a simply data transfer)


-->Reader-->Writer-->


Now, since I'd like to be able to plug (almost) everything to everything and (possibly) create quite long chains, I'd assume I'd have to have some sort of Pluggable interface.


Also, when creating such big chain, I'd probably want to wrap it behind a Facade. And since I'd want each pluggable component (class) to be replaced by some other, then Strategy pattern comes to mind.


Now, since I've already mentioned the term chain here, Chain of Responsibility pattern comes to my mind, in the following (or similar way):



public interface Pluggable<InputType, OutputType> {
public void consume(Pluggable<?, InputType> previous);
public Collection<OutputType> produce();
}


For example, if I wanted to have my Splitter to split a list of Files provided by Reader, it might looks something like this:



public class Splitter<InputType, OutputType> implements Pluggable<?, InputType> {
public void consume(Pluggable<?, InputType> previous) {
// retrieves for example a list of InputType objects
}

public Collection<OutputType> produce() {
// filters the collection it got and returns a sublist for example
}
}


In the end, the components might look something like this:


Reader<File, Foo> --> Splitter<Foo, Foo> --> Model<Foo, Void> --> Test<Model, Bar> --> Writer<Bar, DAO>


I don't know how else to describe the problem I'm having, but I'm sure something like this is quite achieveable. For visual example, here's the image of RapidMiner's process


RapidMinerChainExample


Note that I'm not trying to replicate or copy Rapid Miner, it's just that the project I was assigned looks like it can be implemented in simiar way.


I'd appreciate any help regarding how to design such application.


Aucun commentaire:

Enregistrer un commentaire