Peter Stuifzand

The structure of dispatching controllers

Yesterday we looked at the structure inside of two simple controller actions. Now let us look at the outside. The structure of the two actions can be shown as a tree.

  • Guestbook
    • list
  • Orders
    • list

I hid the rest of methods that would normally be in these controllers. In front of these controllers there is another class, called the Dispatcher. This Dispatcher uses a request and calls the appropriate controller and action.

The Dispatcher translates a URL into two pieces of information: the controller and the action. The Dispatcher then translates the controller name into a class name like this.

my ($controller, $action, $id) = ($url =~ m{^/(\w+)(?:/(\w+)(?:/(\d+))?)?});
my $classname = 'AppName::Controller::' . ucfirst $controller;
eval "require $classname";
my $obj = $classname->BUILD();
$obj->$action();

This simplified version of the code calls the controller. This contains no error checking, which is really important in a secure web application.

While I was thinking about writing this article at one point I thought about the direction of the calls and which part controls the execution flow. In the example the URL is passed to the Dispatcher which finds the controller. It looks up the controller class, then looks up the method and calls it. This way the URL and the code is coupled.

The URL determines the class and method that gets called. In this design we can’t split up classes, because all controller methods need to be contained in the same class. We can’t split or join classes or create smarter software because of this design decision. Furthermore, because the controller is created at the start of a request, we can’t use the same controller for different URLs. Each URL needs its own piece of code. I argue that because of these problems we can’t even use the techniques we know to improve the design.

We could increase the flexibility of the design by using objects instead of classes. Objects are more flexible, we can replace parts of the system by setting an instance variable to a different object.

To find out how we can redesign the code with this new knowledge, we have to take a look at the structure of more controllers.

I have still a few questions about the structure of the system. Where is the boundary between controllers and actions. Is there a boundary? Do we need controllers at all, or is having actions enough? As always we have to consider more sides of this problem.

© 2023 Peter Stuifzand