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:
Reader
- Denotes a data source
- Can be a file on HDD, online resource, database, etc.
Splitter
- Input is
Reader(s)
- Splits the contents of what reader delivers into parts
- Outputs are split contents of
Reader(s)
- Input is
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
- Input is
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
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 File
s 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
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