toeb / accounting

3 stars 0 forks source link

Command Handler #53

Closed matthiaszoellner closed 8 years ago

matthiaszoellner commented 9 years ago

Die aktuelle Lösung, in der eine einzige Klasse (z.B. AccountingFacade) die Implementierung mehrerer Commands enthält, führt aus meiner Sicht zu vermeidbaren Designproblemen.

Folgender Plan für ein CommandHandler Interface:


public interface ICommandValidator<TCommand>
{
    bool Validate(TCommand command, out IEnumerable<ValidationException> ValidationErrors);
}
public  interface ICommandHandler<TCommand> : ICommandValidator<TCommand>
{
    void Handle(TCommand command);
}

Jedes Command lässt sich so unabhängig implementieren, die Validierung wird vom Handling getrennt.

Anstelle von AccountingFacade könnte eine Factory Klasse stehen, die die einzelnen CommandHandler Implementierungen zurückgibt und sich um Dinge kümmern kann wie z.B., dass Validate immer vor Handle aufgerufen wird.

public class AccountingFactory
{
    protected ICommandHandler<TCommand> DecorateHandler<TCommand>(ICommandHandler<TCommand> handler)
    {
        return new ValidatingHandlerDecorator<TCommand>(handler);
    }
    public ICommandHandler<OpenAccountCommand> OpenAccountCommandHandler()
    {
        return DecorateHandler(new OpenAccountCommandHandler());
    }
}

Hierbei ist OpenAccountCommandHandler die eigentliche Implementierung und ValidatingHandlerDecorator ein Wrapper, der dafür sorgt, dass Validate IMMER vor Handle aufgerufen wird. Auf ähnliche Weise lassen sich dann auch andere Querschnittaufgaben per Decorator einpflegen - z.B. die UnitOfWork Injection.

matthiaszoellner commented 8 years ago

Die Idee mit AccountingFactory ist in der Form nicht notwenig. Die entsprechenden Methoden passen super in AccountingFacade rein. Habe mal eine Beispielimplementierung für OpenAccountCommand hochgeladen