Fluent interface design and code smell

Posted by Jiho Han on Stack Overflow See other posts from Stack Overflow or by Jiho Han
Published on 2010-03-17T02:47:43Z Indexed on 2010/03/17 2:51 UTC
Read the original article Hit count: 634

public class StepClause
{
    public NamedStepClause Action1() {}

    public NamedStepClause Action2() {}
}

public class NamedStepClause : StepClause
{
    public StepClause Step(string name) {}
}

Basically, I want to be able to do something like this:

var workflow = new Workflow().Configure()
    .Action1()
    .Step("abc").Action2()
    .Action2()
    .Step("def").Action1();

So, some "steps" are named and some are not.

The thing I do not like is that the StepClause has knowledge of its derived class NamedStepClause.

I tried a couple of things to make this sit better with me. I tried to move things out to interfaces but then the problem just moved from the concrete to the interfaces - INamedStepClause still need to derive from IStepClause and IStepClause needs to return INamedStepClause to be able to call Step(). I could also make Step() part of a completely separate type. Then we do not have this problem and we'd have:

var workflow = new Workflow().Configure()
    .Step().Action1()
    .Step("abc").Action2()
    .Step().Action2()
    .Step("def").Action1();

Which is ok but I'd like to make the step-naming optional if possible.

I found this other post on SO here which looks interesting and promising. What are your opinions? I'd think the original solution is completely unacceptable or is it?

By the way, those action methods will take predicates and functors and I don't think I want to take an additional parameter for naming the step there.

The point of it all is, for me, is to only define these action methods in one place and one place only. So the solutions from the referenced link using generics and extension methods seem to be the best approaches so far.

© Stack Overflow or respective owner

Related posts about c#

Related posts about fluent-interface