Jump to content

Command & Front Controller


KevinM1

Recommended Posts

I'm not sure if this is more suited to the design forum, so please feel free to move it there.

 

Is there any reason to use the Command pattern if you're already employing a Front Controller?  Both are pretty similar (albeit different in size and scope).  I'm just wondering what the general consensus is regarding a 'real' project (CMS, blog, that sort of thing).

Link to comment
Share on other sites

If you have a large application, with many different features, there is. Otherwise it can generally be considered superfluous to use both.

 

Yeah, that's more or less what I thought, but just wanted to make sure I wasn't missing anything obvious.

 

Thanks!

Link to comment
Share on other sites

In large application architectures, the front controller is reponsible for initialising the first "command" object and then iterating through each of the command executions that occur. They're different. Are you referring to a page controller vs front controller?

Link to comment
Share on other sites

In large application architectures, the front controller is reponsible for initialising the first "command" object and then iterating through each of the command executions that occur. They're different. Are you referring to a page controller vs front controller?

 

Nope, Front Controller vs. Command, as described in Zandstra's book (PHP Objects, Patterns, and Practice).  The two seem pretty similar, and I believe Zandstra himself basically says that Front Controller itself is derived from Command (although, don't quote me on that as I don't have the book at hand at the moment).

 

I should probably re-re-read those two sections of the book, but I'm still having problems seeing how the two would be used in concert.  Command just seems redundant to me if there's a Front Controller in place.

Link to comment
Share on other sites

In which case I can confirm you are confusing the 2. I have the book to hand, the front controller is reponsible for loading up commands and "execute()" -ing them.

 

You're right, I was confusing the two.  That said, while FC uses Command objects, would it be necessary to use a CommandContext/RequestHelper object if your Controller is already employing an ApplicationHelper?  I think that's where my initial gut feeling of redundancy stems from.

Link to comment
Share on other sites

In which case I can confirm you are confusing the 2. I have the book to hand, the front controller is reponsible for loading up commands and "execute()" -ing them.

 

You're right, I was confusing the two.  That said, while FC uses Command objects, would it be necessary to use a CommandContext/RequestHelper object if your Controller is already employing an ApplicationHelper?  I think that's where my initial gut feeling of redundancy stems from.

 

Nevermind, I'm an idiot.  The two (CommandContext and ApplicationHelper) aren't really similar.  I don't know why I kept thinking otherwise.

Link to comment
Share on other sites

Yeah i had a few reservations about some of the stuff in the book. I wasn't too keen on the xml config that builds the forwarding options, and trialed a command forwarding using a linked list builder approach (like the chain of responsibility pattern). In essence:

<?php

abstract class Command {

  protected $next;

  final public function execute(){
    $this->doExecute();
    if(($next = $this->getNext()) !== NULL){
      $next->execute();      
    }
  }

  final public function getNext(){
    return $this->next;
  }

  final public function setNext(Command $cmd){
    $this->next = $cmd;
  }

  abstract public function doExecute();
}

class concrete1 extends Command {
  public function __construct(){
    $this->setNext(new concrete2());
  }

  public function doExecute(){
    echo "con1";
  }
}

class concrete2 extends Command {
  public function doExecute(){
    echo "con2";
  }
}


$cmd = new concrete1();
$cmd->execute();

?>

 

This way you can chain commands using the command itself. It allows the command logic to decide what it does next instead of relying on the STATUS_ conditions that the xml options contained. I'm not sure if this method is better, but it does remove the reliance on the xml and the CommandHelper that decided whether to continue or not. I haven't put it into production, and the code above was from memory. So treat it lightly ;)

Link to comment
Share on other sites

I don't believe I've gotten to the point in the book where XML is used to control the ordering of command execution.  The only XML I've seen so far is where he loads a config file into his ApplicationHelper object in order to obtain a hyptothetical dsn.  It'll be interesting to see how his method differs from yours.

 

 

Link to comment
Share on other sites

I figured I'd ask this here, so as to not create more top-level threads.

 

I got a very simple Front Controller to work by basically just copying Zandstra's code.  One of the things that bugs me about his code (which is why I modified his Registry classes) is his habbit of creating redundant functions that don't actually do anything, at least, to my inexperienced eye.

 

Case in point - his code (with the exception of the class name) for the abstract base Command class is:

<?php
   abstract class MP_command_Command{
      final function __construct(){}

      function execute(MP_controller_Request $request){
         $this->doExecute($request);
      }

      abstract function doExecute(MP_controller_Request $request);
   }
?>

 

I fail to see why there needs to be two execute functions, especially since they both have the same signature, and neither one is private, or access private attributes.  Wouldn't it make more sense to simply:

<?php
   abstract class MP_command_Command{
      final function __construct(){}

      abstract function execute(MP_controller_Request $request);
   }
?>

 

It just seems as though he's delegating for no real reason.

Link to comment
Share on other sites

Ah, indeed the very same question I asked myself while studying it. Work to abstractions not implementations ;)

The doExecute() is abstract, meaning that you initialise it in the child classes, however by keeping the execute() a concrete method in the base class you can be assured that this is what it will remain (name wise) and also it allows you to insert other functions inside it at a later date. e.g.

<?php
...
function execute(MP_controller_Request $request){
         $this->doExecute($request);
         $this->captureLog();
}

abstract function doExecute(MP_controller_Request $request);
abstract function captureLog();
?>

 

Now you can STILL call the execute function in your front controller SAFE in the knowledge that nothing has changed (essentially), while in actual fact because of the abstraction you have added additional functionality to the Command structure causing no ill effects (although you now have to implement the captureLog() function throughout your commands, of course you could always give it a blank functionality)

Link to comment
Share on other sites

Hmm..I see what you're saying.  It's just that my (albeit limited) *nix/C++ background has ingrained into my mind that lazy = good.  Bare minimum to get the job done efficiently, and nothing else.  To borrow a term from Zandstra, the extra layer of abstraction gives off a funny 'smell' to me.

 

Just something I'll have to get used to.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.