Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have "logic engine" which executes set of user configured steps. These steps are saved in the database as "Step" entities. The engine gets the first step and then executes steps until there are no more steps to execute:

public void Execute(details, data, Step firstStep)
{
    var step = firstStep;
    while (null != step)
    {
        step = step.Execute(details, data);
    }
}

The different types of steps are expressed as derived classes. Each of them must implement the Execute method. The data and details parameters are used by the step to execute some logic. As fas as the logic engine knows it is just executing step after step without any knowledge what those steps do.

The problem:

Some of the steps need to access external services to get data or maybe even the same or different database where the actual step entities are stored. The information is usually used by other steps. One could say that some of the steps are just for loading data from external sources/database and other steps are using that data to make decisions. This separation is done so that we can use different data sources (as long as they produce the same kind of output to us) without the need to write any additional code.

Is there a better way to handle this type of domain? If I separate the actual Step and the logic (i.e. loading data from external service or from database) then my whole domain model (steps) doesn't have any logic. I would most likely have something like:

var handler = dictionary[step];
handler.Execute(step, details, data);

Now the logic and any external dependencies are in the handler object but the actual domain object (step) is just a dummy place holder for the information. That doesn't sound right either.

share|improve this question
    
Is there any particular reason you don't like have a step load data from an external data source? –  JGWeissman Jan 6 '12 at 18:16
    
@JGWeissman No not really. It seems natural but since I have never done it (use external service or repository from inside the actual domain entity) it seems a bit strange. Usually my domain entities have been about validation and state (e.g. account.Disable()). –  Toni Parviainen Jan 6 '12 at 19:20
    
At least make sure that you late bind the service urls, meaning that you do not save them in the db. Also make sure that you save some sort of indication of version and definition of the service you want to call in the db. This will help you in the long run, as the coupling will at least be described. –  casper Jan 12 '12 at 15:50

1 Answer 1

up vote 2 down vote accepted

I suggest implementing a new object type, Step Data Source, in your domain. You can make it implement an interface so that the individual source won't matter so long the sources use the same interface. Just like you have different types of steps, you can have different types of StepDataSources. Since the steps are user-configured, you could even have a list of available data sources for the user to choose from (if that were a user story you wanted to implement).

Here's what a step that uses a step data source might look like:

public class DerivedStep : Step, IStepWithData
{
    ...
    public IStepDataSource IStepWithData.GetDataSource() { ... }
    public void IStepWithData.Execute(IStepDataSource DataSource, ...)
    {
        ...
        // use the data source to get the data to pass to Step.Execute
        var data = DataSource.SomeMethodWhichReturnsData(...)
        Execute(data, ...);
    }

    // overridden from Step parent class
    public void override Execute(data, ...)
    {
    }
}

// logic engine might do something like this
...
Step step = ...
if (step is IStepWithData)
{
    IStepWithData dataStep = step as IStepWithData;
    var source = dataStep.GetDataSource();
    dataStep.Execute(source);
}
else
{
    step.Execute(...);
}
...

I'm not exactly clear on your domain, so that is just a stab at it. There are a lot of implementation details that are not shown obviously, and may not be exactly right for your domain.

I wouldn't worry too much about your classes not having "enough" behavior, and here's why; Your domain itself is of a transactional nature (users defining steps to execute on objects), so it's only natural for your domain model (code) to reflect that and become more transactional.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.