Request degenerates and the LSP

153 views
Skip to first unread message

Tom Oram

unread,
Feb 23, 2014, 8:43:49 PM2/23/14
to clean-code...@googlegroups.com
In previous episodes of Clean Code Uncle Bob, as I understand it, has provided the following pattern.

abstract class Request {
}

interface UseCase {
    public Response execute(Request request);
}

class SpecificUseCase implements UseCase {
    /* implemention */
}

class SpecificRequest extends Request {
    /* Use case specific data
}

In the controller component only the abstract Request and the UseCase interface are known about, the specific implementations are constructed by builders/factories and passed back over the boundary.

The specific use cases and requests have a 1 to 1 relationship - a request implementation is created to be use with 1 and only 1 use case implementation.

In the use case's execute method the request is down cast to the specific request type like so

public function execute(Request request) {
    SpecificRequest specificRequest = (SpecificRequest)request;
    /* Do stuff with request */
}

Now presumably there are tests in place to ensure that the incorrect request type never gets passed in, but even so is this not a violation of the Liskov Substitution Principal since the interface claims to be able to handle any objects which implement Request?

My understanding of why it is done this way is that is a work around for the fact that Java is statically typed. The interface is required so the controller (or any dependent model) has no dependencies on the specific implementations, but since it's got to take an argument which has to be able to accept any specific request type the degenerate is used to allow this. Am I correct?

So is this a case of "because the language is incapable we can bend the rule here"?

BONUS QUESTION:
This is obviously not an issue with dynamically typed languages, however there is PHP which is dynamically typed but allows typehints to be specified. Many PHP programmers are leaning more and more into a statically typed style of writing. So in this situation, if you were writing PHP, would you choose create the interface and abstract Request in the style of the Java code or would you embrace the dynamically typing features of the language and not bother to type hint the request argument at all?

Thanks for your time and I look forward to your replies,
Tom

Tom Oram

unread,
Feb 23, 2014, 8:46:37 PM2/23/14
to clean-code...@googlegroups.com
OR (re: the PHP question), not have an interface for the use case at all and just call the execute method and assume it's been defined (duck typing). This way you could use the correct type hint but have to assume the function exists.

Michel Henrich

unread,
Feb 24, 2014, 9:10:19 AM2/24/14
to clean-code...@googlegroups.com
To me, that kind of architecture doesn't look like a Clean Architecture. As you have pointed out, it has many drawbacks, and requires some "work arounds". Something that requires work arounds smells bad to me.
I have been using the Command pattern for most of my Use Cases, and so far it has proven to be quite flexible and easy to use.
The basic layout is something like this:

interface Command{
    void execute();
}

class SomeUseCase{
    private Request request;
    private Receiver receiver;

    public SomeUseCase(Request request, Receiver receiver){
        this.request = request;
        this.receiver = receiver;
    }

    public void execute(){
        doSomethingThatReadsTheRequestAndSendsMessagesToReceiver();
    }

    ...
}

The main difference is that instead of getting a Response object as a return value from the Command.execute() method, you'll receive the response object(s) through callbacks/messages defined in the Receiver interface. (You can call it Receiver, Callback, Responder, whatever fits best)
This way, you can define the Request and Receiver interfaces inside of each UseCase class, because they are UseCase-specific, and so there is no confusion about which type of Request and Receiver to send into the UseCase constructor.

One interesting advantage of the command pattern for use cases is that you can construct it in a context-sensible place (where the request data is known, for instance), and execute it in a completely context-agnostic place. Works wonders for separation of concerns, and logically, testing. :)

About PHP, I guess the same principles are applicable, with or without type hints, but I'll not make any concrete statements since I haven't seen a line of PHP code for a few years now.
I'm basing this on my experience with this exact pattern in Ruby, which does not offer any kind of type specification. It works just as nicely as in Java.

Hope this was helpful.
Kind regards,
Michel

Dave Marshall

unread,
Feb 24, 2014, 5:58:19 PM2/24/14
to clean-code...@googlegroups.com
I came to the same conclusions, interesting to see what others come back with.

Tom Oram

unread,
Feb 25, 2014, 5:50:03 AM2/25/14
to clean-code...@googlegroups.com
Thanks for your reply Michel, definitely a much better way of doing it IMHO. I think the solution you provided it pretty much perfect however I'm going to leave the thread as uncompleted as I'd like to hear others' thought and hopefully maybe something from Uncle Bob about why he chose the way he did. 

Uncle Bob

unread,
Feb 27, 2014, 2:05:52 PM2/27/14
to clean-code...@googlegroups.com
I agree with the callback solutions that others have posted.  

I will say, however, that downcasts are not always a smell.  If your code already knows what the type must be, there is no smell involved with the downcast.

Tom Oram

unread,
Mar 12, 2014, 2:35:05 PM3/12/14
to clean-code...@googlegroups.com
Thanks for you're replies everyone.

@Uncle Bob, I do agree that downcasts aren't always a smell but I think depending on the language the can be more or less smelly ;)


On Monday, 24 February 2014 01:43:49 UTC, Tom Oram wrote:
Reply all
Reply to author
Forward
0 new messages