SitePoint Sponsor

User Tag List

Page 3 of 16 FirstFirst 123456713 ... LastLast
Results 51 to 75 of 384
  1. #51
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    Is it just me or is this a cue for taking a step back and rethinking?
    I don't agree with you there. Provided that you accept and understand the FrontController (Skeleton thread code), the only new thing here is the two classes FlowController and FormController. If you just need a simple form, you wouldn't really need to tamper with the internals of the statemachine (the FlowController), since the FormController gives you a ready-made interface for the purpose.

    Curiously, I found this with google :
    http://www.sebastian-bergmann.de/tal...on_Servers.pdf
    See page 22-24.

  2. #52
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    My experience is mainly from CakePHP (a Rails-port) and the like, and this seems really odd to me. You all seem to be haphazardly mixing classes and responsibilities together - I have no idea what goes where, much less why or how. The classes would seem awkward and inflexible. Is it just me or is this a cue for taking a step back and rethinking?
    I think you are just watching the ingredients bubble. There are actually many good ideas and comments in there.
    Quote Originally Posted by Ezku
    For one, the InputController and ActionController seem to have melted together. The state machine approach is something to think about, but if it means having to settle for something like this, I'll have to decline.
    I think you are mistaking what we are building for a framework. My hope is that what we are building here are classes from which you can build many different types of frameworks. A framework organizes the underlying classes into something that makes sense. Usually this madness only goes on within one programmer's brain, but here it is wonderfully out in the open to experience
    Christopher

  3. #53
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    I think you are mistaking what we are building for a framework.
    I don't think that's the case, perhaps I didn't express myself properly. I was implying that there must be a cleaner solution than what I'm seeing right now. Many of the clips have a lot of unnecessary object instancing and and such like:
    PHP Code:
            parent::FormController
                new 
    ServerPage("page/forminit.php"), 
                new 
    ServerPage("page/forminvalid.php"), 
                new 
    ServerPage("page/formdone.php"
            ); 
    Isn't exactly clean, at least in my thinking.

    I do realize a lot of this is just experimentation and sketches, and I have to admit I haven't taken a look at kyberfabrikken's latest code. Perhaps my troubles are already gone; is the input validation part with rules and filters perfectly separatable from FlowController?

  4. #54
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    I don't think that's the case, perhaps I didn't express myself properly. I was implying that there must be a cleaner solution than what I'm seeing right now. Many of the clips have a lot of unnecessary object instancing and and such like:
    PHP Code:
            parent::FormController
                new 
    ServerPage("page/forminit.php"), 
                new 
    ServerPage("page/forminvalid.php"), 
                new 
    ServerPage("page/formdone.php"
            ); 
    Isn't exactly clean, at least in my thinking.

    I do realize a lot of this is just experimentation and sketches, and I have to admit I haven't taken a look at kyberfabrikken's latest code. Perhaps my troubles are already gone; is the input validation part with rules and filters perfectly separatable from FlowController?
    Well hopefully with everything separatable that you can pick and choose what pieces you might want. Regarding "a lot of unnecessary object instancing" I think you are just seeing that in the experimental code. We will probably bring back the ObjectHandle class because for this kind of Controller we will probably want to use Lazy Load on all the potential "action" classes and then only load/instansiate the one that is actually used.
    Christopher

  5. #55
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    Many of the clips have a lot of unnecessary object instancing (...) which isn't exactly clean, at least in my thinking.
    Ok. Valid point, but it's more of an implementation-issue. We could provide handles to the actual handlers instead, to save the un-needed instantiation. I just thought that would be bloating the code too much at present time.

    Quote Originally Posted by Ezku
    is the input validation part with rules and filters perfectly separatable from FlowController?
    No, and even though I somewhat agree that it's a mix of interests, I can't see any practical problem associated with it. It may be that I've just not thought it through ? Maybe it would cause troubles if the ApplicationController didn't rely on Request to update/assert it's state, but isn't that a reasonable assumption ?

    If we implement the ApplicationController as a state-machine, we still need to process the transitions. The state-machine is a rather passive player - and the logic which decides to trigger changes in it would have to rely on something like the validator.

    After seeing the pdf-file, which I linked to in post #51, I tried to use the PEAR::FSM as a basis. I ended up with less code (if you count the FSM-class out), but I'm not sure if I like that approach better. How do you think about that ?

    PHP Code:
    require_once('FSM.php');

    class 
    FormController extends FSM
    {
        var 
    $handlers = Array();

        function 
    FormController() {
            
    parent::FSM('INIT'$null NULL);

            
    $this->validator =& new Validator();

            
    $this->addTransition(
                
    'SUBMIT',                            // symbol
                
    'INIT',                                // required state
                
    'NOT_VALID',                        // default ending state
                
    Array($this->validator'validate')    // trigger
            
    );

            
    $this->addTransition(
                
    'SUBMIT',                            // symbol
                
    'NOT_VALID',                        // required state
                
    'NOT_VALID',                        // default ending state
                
    Array($this->validator'validate')    // trigger
            
    );

            
    $this->addHandler('INIT', new ServerPage("page/forminit.php"));
            
    $this->addHandler('NOT_VALID', new ServerPage("page/forminvalid.php"));
            
    $this->addHandler('VALID', new ServerPage("page/formdone.php"));
        }

        
    /**
          * registers a handler for a given state
          */
        
    function addHandler($state, &$handler) {
            
    $this->handlers[$state] =& $handler;
        }

        
    /**
          * returns the handler for the current state
          */
        
    function & getHandler() {
            if (!
    array_key_exists($this->_currentState$this->handlers)) {
                
    trigger_error("no handler registered for state '{$this->_currentState}'");
            }
            return 
    $this->handlers[$this->_currentState];
        }

        function 
    execute() {
            if (
    $_SERVER['REQUEST_METHOD'] == 'POST') {
                
    $this->process('SUBMIT');
            }
            
    $handler =& $this->getHandler();
            
    $handler->execute();
        }
    }

    class 
    Validator
    {
        function 
    validate() {
            if (isset(
    $_REQUEST['foo']) && !empty($_REQUEST['foo'])) {
                return 
    'VALID';
            }
        }
    }

    class 
    ServerPage
    {
        var 
    $filename;

        function 
    ServerPage($filename) {
            
    $this->filename $filename;
        }

        function 
    execute() {
            include(
    $this->filename);
        }
    }

    $controller =& new FormController();
    $controller->execute(); 
    Last edited by kyberfabrikken; Jul 11, 2005 at 12:02. Reason: Linked to PEAR::FSM

  6. #56
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    is the input validation part with rules and filters perfectly separatable from FlowController?
    I got the feeling a little while back that the validation code should be separated out but I'm not sure what the current versions of all the classes look like.

    This is all the kind of thing which TDD is good for. By now, you'd have a bunch of interaction tests using mocks and would probably be looking at consolidating with a refactoring stage.

  7. #57
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I finally got some time last night to actually write some code for this. kyberfabrikken has inspired me and looking at his code has answered some of the questions I had about this thing. I went a little different direction than kyberfabrikken with the states and transitions. I implemented a separate StateMachine class just to show what is going on. This should be integrated into an Application Controller class later (and refactored !).

    I wanted to be able to use our standard Rules (Overrunner's) so I added a check() method to the InputController and InputControllerParameter classes so they can be used as rules. Other than that the Input Controller code is the same as before (with some of the naming and code changes requested here).

    Instead of kyberfabrikken's boolean conditions I implemented "from state" and "to state" values for the transition. This allows a cascade. We would need to add a session object to save the state for more complex action sets, but it works fine without it for the Form Controller case of an Application Controller which is what I have implemented in this example.

    The code dealing with the State Machine looks like this:
    PHP Code:
    include_once 'StateMachine.php';

    // create state machine and set default state
    $statemachine = new StateMachine('init');

    // register states managed by this controller
    $statemachine->addState(new State('init', new InitHandler($controller)));
    $statemachine->addState(new State('submit', new SubmitHandler($controller)));
    $statemachine->addState(new State('done', new DoneHandler($controller)));

    // register register transitions with from state, to states and rule
    $statemachine->addTransition(new Transition('init''submit', new RequiredRule('submit''submit')));
    $statemachine->addTransition(new Transition('submit''submit'$controllerfalse));
    $statemachine->addTransition(new Transition('submit''done'$controller));

    // find state based on transition rules above
    $handler =& $statemachine->findState($request);
    $handler->execute($request$response=null); 
    If you look at the transitions, it starts in 'init' state. If it passes the 'init' (form submitted) rule it moves to 'submit' state. It then checks all rules in 'submit' state (controller isError and isValid). If it passes one of those rules it changes state. I don't technically need the first 'submit','submit' transition because the State Machine is already be in 'submit' state at that point. The StateMachine::findState() method returns a Handler like ActionMapper::mapRequest() does so ultimately the Application Controller would work in a similar way to the Front Controller.

    The code can be downloaded here. It adds the StateMachine class and puts the code above into the example_inputcontroller.php file.
    Christopher

  8. #58
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Ok. Valid point, but it's more of an implementation-issue. -- I just thought that would be bloating the code too much at present time.
    You're right about that, but the implementation does worry me just a bit. Without forethought you can come up with a great solution that in actuality is difficult to implement.
    I somewhat agree that it's a mix of interests, I can't see any practical problem associated with it. It may be that I've just not thought it through?
    I thought it was quite obvious. As it is, I can't pick the data validation part and use it in my own ApplicationController if I so wish.

    This separation is easily done:
    PHP Code:
    /**
     * Validates and filters input data
     * 
     * @author        Ezku (dmnEe0@gmail.com)
     * @since        Jul 11, 2005
     */
    class Validator
    {
        protected 
    $rules NULL;
        protected 
    $filters NULL;
        
        
    /**
         * Add filter to stack
         * @param    object    IInputFilter
         */
        
    public function addFilter(IInputFilter $filter)
        {
            
    $this->filters[] = $filter;
        }
        
        
    /**
         * Add rule to stack
         * @param    object    IInputRule
         */
        
    public function addRule(IInputRule $rule)
        {
            
    $this->rules[] = $rule;
        }
        
        
    /**
         * Run filters and match rules on DataObject, log errors to Logger
         * @param    object    DataObject
         * @param    object    ILogger
         * @return    boolean    is valid
         */
        
    public function validate(DataObject $dataILogger $logger)
        {
            
    $errors 0;
            foreach (
    $this->filters as $filter)
            {
                
    $data $filter->process($data);
            }
            foreach (
    $this->rules as $rule)
            {
                
    $error $rule->validate($data);
                if (!empty(
    $error))
                {
                    
    $logger->log($error);
                    ++
    $errors;
                }
            }
            return (
    $errors == 0);
        }
    }

    interface 
    IInputFilter
    {
        
    /**
         * Returns filtered DataObject.
         * @param    object    DataObject
         * @return    object    DataObject
         */
        
    public function process(DataObject $data);
    }

    interface 
    IInputRule
    {
        
    /**
         * Returns error message on failure, empty on success.
         * @param    object    DataObject
         * @return    string    error message
         */
        
    public function validate(DataObject $data);

    Your FlowController would thus look like this:
    PHP Code:
    class FlowController implements IHandler
    {
        protected 
    $success NULL;
        protected 
    $failure NULL;
        protected 
    $validator NULL;
        
        public function 
    __construct(IHandler $successIHandler $failure)
        {
            
    $this->success $success;
            
    $this->failure $failure;
            
    $this->validator = new Validator;
        }
        
        public function 
    execute(Request $requestResponse $response)
        {
            
    $logger = new Logger;
            if (
    $this->validator->validate($request$logger))
            {
                
    $this->success->execute($request$response);
            }
            else
            {
                
    $this->request->set('errors'$logger->getMessages());
                
    $this->failure->execute($request$response);
            }
        }
        
        public function 
    addFilter($filter)
        {
            
    $this->validator->addFilter($filter);
        }
        
        public function 
    addRule($rule)
        {
            
    $this->validator->addRule($rule);
        }

    This solution seems a lot more solid to me. It's clean - rules are logger-agnostic, for example - and responsibilities don't overlap. If you're worried about writing to the Request, cloning it should be trivial. Anyone agree with me here? :)

    (We didn't yet decide on the name of the data holder class, did we?)

  9. #59
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Off Topic:

    Quote Originally Posted by McGruff
    This is all the kind of thing which TDD is good for. By now, you'd have a bunch of interaction tests using mocks and would probably be looking at consolidating with a refactoring stage.
    So you're saying that if testing a class is a PITA, then there's likely a flaw in its design? TDD methodologies are still new to me. :)

  10. #60
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    Off Topic:

    So you're saying that if testing a class is a PITA, then there's likely a flaw in its design? TDD methodologies are still new to me.
    To quote Jason's sig, it would be detestable:

    Detestable (adjective): software that isn't testable.

    Regards,
    Douglas
    Hello World

  11. #61
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    I got the feeling a little while back that the validation code should be separated out (...)
    Quote Originally Posted by ezku
    This solution seems a lot more solid to me. (...) and responsibilities don't overlap.
    I concur.

    Quote Originally Posted by ezku
    We didn't yet decide on the name of the data holder class, did we?
    Nope - I didn't intend for a hostile takeover, the name is still open for debate. Whether we should use a logger for the validator/rules is also still an open topic. My vote is most definately a 'Yes'.

    Quote Originally Posted by arborint
    I wanted to be able to use our standard Rules (Overrunner's) so I added a check() method to the InputController and InputControllerParameter classes so they can be used as rules. Other than that the Input Controller code is the same as before (with some of the naming and code changes requested here).
    I believe it was Ezku who pointed out to me, that rules shouldn't be attatched to parameters, since a rule may relate to more than one (or even none) of the parameters.
    Or did I miss your point ?

    Quote Originally Posted by arborint
    The code dealing with the State Machine looks like this
    Wow. That looks almost identical to what I just posted in post #55. That's totally cool - maybe we should get married or something ?
    Regardless - I definately like this design better than what I posted in post #48.

    Shouldn't we try to stick with the post #55 variant though, since it utilizes some really nice and stable code from the PEAR repository?

  12. #62
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    So you're saying that if testing a class is a PITA, then there's likely a flaw in its design? TDD methodologies are still new to me.
    Yes - indeed. The less a class does, the easier it is to test and that helps keep you focussed on lean classes doing just one thing.

  13. #63
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    I believe it was Ezku who pointed out to me, that rules shouldn't be attatched to parameters, since a rule may relate to more than one (or even none) of the parameters.
    Or did I miss your point ?
    I don't think I missed the point. I wanted to use the Rule interface because it is our current standard for this. By making the InputController itself a rule I don't tie it to a parameter. The great thing about using Rules is that you can encaptsulate any condition behind a standard interface and feed it to the state machine.
    Quote Originally Posted by kyberfabrikken
    Wow. That looks almost identical to what I just posted in post #55. That's totally cool - maybe we should get married or something ?
    Sorry already married, but this pair/team process is very satilsfying because the good ideas naturally become obvious as we iterate.
    Quote Originally Posted by kyberfabrikken
    Regardless - I definately like this design better than what I posted in post #48.

    Shouldn't we try to stick with the post #55 variant though, since it utilizes some really nice and stable code from the PEAR repository?
    I would actually like to avoid PEAR if possible. As I said above, I don't think the State Machine class will stay as it is. I think it should become the Application Contoller which has a State Machine inside if it. My code is also following on from the work by Overrunner and Ezku on the Input Controller which I would like to continue.
    Christopher

  14. #64
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    I wanted to use the Rule interface because it is our current standard for this. By making the InputController itself a rule I don't tie it to a parameter. The great thing about using Rules is that you can encaptsulate any condition behind a standard interface and feed it to the state machine.
    Fine - I got your post wrong then.
    Quote Originally Posted by arborint
    I would actually like to avoid PEAR if possible.
    I have a general antipathy against PEAR, but this particular class looks well layed out.

    Quote Originally Posted by arborint
    As I said above, I don't think the State Machine class will stay as it is. I think it should become the Application Contoller which has a State Machine inside if it.
    In what way do you see it changing ?
    The relationship between ApplicationController and StateMachine may be composite or through inheritance, but either way the enhancements will happen in the ApplicationController - not in the StateMachine ?

  15. #65
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Originally Posted by ezku
    We didn't yet decide on the name of the data holder class, did we?

    Nope - I didn't intend for a hostile takeover, the name is still open for debate. Whether we should use a logger for the validator/rules is also still an open topic. My vote is most definately a 'Yes'.
    I asked a while back what to name this but no one responded. I tend to do whatever the last interested person requested, so I change it to DataSpace. I actually like DataSource better because I think of Data Sources as simple low level get/set interfaces to external data.

    I'm still not convinced of the Logger.
    Christopher

  16. #66
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm still not convinced of the Logger.
    I am I see it as being an extension over what basic error reporting you would implement in it's (the Logger) absense? You can do more with an object, than simply putting errors to an array (I assume this is the default alternative?).

  17. #67
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    Detestable (adjective): software that isn't testable.
    That had me laughing. (And thanks for the tip, too.)
    Quote Originally Posted by kyberfabrikken
    Nope - I didn't intend for a hostile takeover, the name is still open for debate.
    Let's reiterate our options: DataSource, DataSet, DataSpace, DataObject... is there more? Ah - as I remember, Agavi has a class named ParameterHolder.

    DataSource, as said, implies read-only. DataObject, while accurate, is a bit awkward for a name. On the other hand, DataSpace just seems odd, which leaves me with DataSet. And doesn't that name imply something "dynamic"?

    Well - suggestions, votes?
    Whether we should use a logger for the validator/rules is also still an open topic. My vote is most definately a 'Yes'.
    I agree.

  18. #68
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    DataSource, as said, implies read-only. DataObject, while accurate, is a bit awkward for a name. On the other hand, DataSpace just seems odd, which leaves me with DataSet. And doesn't that name imply something "dynamic"?

    Well - suggestions, votes?
    Nice re-cap. I don't like DataSet, since it implies a Set ~ an array, rather than a hash. How about calling it Dictionary ? Or simply HashMap ?

    WACT originally used the term DataSpace, but changed it to DataSource ... I'm not quite sure why, but I think they changed the implementation at the same time, so it may be more than just an arbitrary namechange.

    Edit:


    Phrame has a HashMap class. The nice thing about this name is that it's used in java. The drawback is that it implies putting a couple of methods into the class which we might not want to include in order to match the original. But I'm not sure that's so bad, since it's just about half a dozen and rather usefull ones.

    Considering, I think my vote goes for HashMap, even though I think DataSpace sounds much cooler.
    Last edited by kyberfabrikken; Jul 11, 2005 at 16:20.

  19. #69
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    Let's reiterate our options: DataSource, DataSet, DataSpace, DataObject... is there more? Ah - as I remember, Agavi has a class named ParameterHolder.

    DataSource, as said, implies read-only. DataObject, while accurate, is a bit awkward for a name. On the other hand, DataSpace just seems odd, which leaves me with DataSet. And doesn't that name imply something "dynamic"?

    Well - suggestions, votes?
    First, I am not sure where the idea that "DataSource, as said, implies read-only" comes from? Perhaps a literal interpretation of the word source. But that is not how it is used, especially in the Java world where it is an interface over a Connection to a "source" (usually in the data layer).

    I think DataObject and DataSet mean other things so shouldn't be used. That leaves us with DataSpace implying like NameSpace an area, or DataSource implying an origin. I'd say that for what we might use it for (the Reqest, Session, etc.) that DataSource makes more sense.
    Christopher

  20. #70
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    In what way do you see it changing ?
    The relationship between ApplicationController and StateMachine may be composite or through inheritance, but either way the enhancements will happen in the ApplicationController - not in the StateMachine ?
    Well a couple of things have me thinking about this. Fowler say that the Input Controller gets the Command or Commands (Model and View) from the Application Controller (which the StateMachine does in my example). So my StateMachine acts more like our ActionMapper, and indeed a version of the StateMachine that takes a map to lookup the state makes sense.

    Also, the Input Controller needs to add some logic to "control" the Application Controller and dispatch the Command(s). So far the InputController class is just a Request Processor so controlling the Application Controller needs to be added.

    The Commands also need a way to directly set the state or forward. For example you might implement a three form sequence with the Transitions:
    PHP Code:
    Transition('initpage1''submitpage1', new RequiredRule('submit'))
    Transition('submitpage1''donepage1'$controller)
    Transition('donepage1''initpage2', ????)
    Transition('initpage2''submitpage2', new RequiredRule('submit'))
    Transition('submitpage2''donepage2'$controller)
    Transition('donepage2''initpage3', ????)
    Transition('initpage3''submitpage3', new RequiredRule('submit'))
    Transition('submitpage3''donepage3'$controller
    but you need the 'donepage1' and 'donepage2' Commands to move to the next page init state when done saving the data. How do we handle this?

    And we really haven't dealt with MVC support yet. An MVC Applicaition Controller would return a Model and View. It would be in the 'skeleton' style to support either a single Command Handler or have a MVCHandler that can create both the Model and View. Then the question is: who passes the Model to the View and then passes the Response along? The MVCHandler or the InputController?

    All these and more give me the sense that when the StateMachine class turns into an Applicaition Controller class it will have more to it. The findState() function is a is really the extent of the State Machine and it is pretty trivial to meet the Applicaition Controller's needs.
    Last edited by arborint; Jul 11, 2005 at 20:32.
    Christopher

  21. #71
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ezku
    This separation is easily done....
    Sorry I missed this earlier: I'd go further and split filtering off from Validator. Filtering != validation.

    In general, you'll get hamstrung if you don't parcel out different responsibilities in nice, tight classes. I've a feeling it could be a good idea to get to work with a scalpel but I'm not sure where you're at right now.

  22. #72
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    Sorry I missed this earlier: I'd go further and split filtering off from Validator. Filtering != validation.

    In general, you'll get hamstrung if you don't parcel out different responsibilities in nice, tight classes. I've a feeling it could be a good idea to get to work with a scalpel but I'm not sure where you're at right now.
    I think there has been some experiments at combining them, but you should take a look at the Input Controller code. It has separate FilterChain and Validator classes that allow you to add Filter and Rule objects. Pretty standard but very functional and no methods are more than a few lines. There is also a good start at unit test coverage as well. Small, tight, testable classes has been a goal for the 'skeleton' throughout. Ezku, Overrunner and I went around a few times on the code. It still needs some clean-up but is very useful right now.

    I would recommend to anyone who is not currently using Filter/Rule style processing of the request to give this code a try. It will focus you on each parameter you are accepting and probably improve the security of you code.
    Christopher

  23. #73
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    Sorry I missed this earlier: I'd go further and split filtering off from Validator. Filtering != validation.
    I was a bit reluctant to do that, but I guess you're right. This is what I have now, and I guess arborint has more or less the same solution:
    PHP Code:
    /**
     * Facade for InputValidator and InputFilterChain
     * 
     * @author        Ezku (dmnEe0@gmail.com)
     * @since        Jul 12, 2005
     */
    class InputController
    {
        protected 
    $validator NULL;
        protected 
    $filter NULL;
        
        public function 
    __construct()
        {
            
    $this->validator = new InputValidator;
            
    $this->filter = new InputFilterChain;
        }
        
        
    /**
         * Process input
         * @param    object    DataObject
         * @param    object    ILogger
         * @return    boolean    validity
         */
        
    public function process(DataObject $dataILogger $logger)
        {
            
    $data $this->filter->process($data);
            
    $validity $this->validator->validate($data$logger);
            return 
    $validity;
        }
        
        public function 
    addRule($rule)
        {
            
    $this->validator->addRule($rule);
        }
        
        public function 
    addFilter($filter)
        {
            
    $this->filter->addFilter($filter);
        }

    PHP Code:
    /**
     * Validates input data
     * 
     * @author        Ezku (dmnEe0@gmail.com)
     * @since        Jul 11, 2005
     */
    class InputValidator
    {
        protected 
    $rules NULL;
        
        
    /**
         * Add rule to stack
         * @param    object    IInputRule
         */
        
    public function addRule(IInputRule $rule)
        {
            
    $this->rules[] = $rule;
        }
        
        
    /**
         * Match rules on DataObject, log errors to Logger
         * @param    object    DataObject
         * @param    object    ILogger
         * @return    boolean    is valid
         */
        
    public function validate(DataObject $dataILogger $logger)
        {
            
    $errors 0;
            foreach (
    $this->rules as $rule)
            {
                
    $error $rule->validate($data);
                if (!empty(
    $error))
                {
                    
    $logger->log($error);
                    ++
    $errors;
                }
            }
            return (
    $errors == 0);
        }

    PHP Code:
    /**
     * Filters input data
     * 
     * @author        Ezku (dmnEe0@gmail.com)
     * @since        Jul 12, 2005
     */
    class InputFilterChain implements IInputFilter
    {
        protected 
    $filters NULL;
        
        
    /**
         * Add filter to stack
         * @param    object    IInputFilter
         */
        
    public function addFilter(IInputFilter $filter)
        {
            
    $this->filters[] = $filter;
        }
        
        public function 
    process(DataObject $data)
        {
            foreach (
    $this->filters as $filter)
            {
                
    $data $filter->process($data);
            }
            return 
    $data;
        }

    Someone mentioned saying you could use just a filter instead of a chain, just a rule instead of a validator etc - and I'm seeing that here now. So should IInputRule be changed to match Validator so Validator could implement it, and should InputController implement IInputRule as well? In the FlowController context this would feel natural.

    Am I asking things that are already resolved? Sorry for lagging behind, as I see most of you are already at the ApplicationController implementation, full steam.

  24. #74
    SitePoint Zealot Overunner's Avatar
    Join Date
    Mar 2004
    Location
    Sweden
    Posts
    180
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm, we seem to have a lot of Controllers and stuff in the air, so I'm going to ask a bunch of questions

    1. How is the Application Controller, Input Controller and Flow Controller related to each other? Do they
    co-operate anything? By just looking at the code, I think the responsibilities of the Flow Controller overlap with the Input Controller.

    2. In one of kyberfabrikken's example (here), he seem to have put request/(form) validation code in the Application controller, which we also have in the Input Controller. Do we need such validation in both places?

    3. arborint: Why did you introduce a Transition object? How does it work exactly?

    4. Should a Form Controller inherit from the AC or IC or neither?

    5.
    Quote Originally Posted by arborint
    I'm still not convinced of the Logger.
    I'd like to hear your opinion about the Logger.

    arborint: I think you should rename the processRequest method in the InputControllerParameter class to processParameter. Since the entire request will get processed in the Input Controller rather than in a single parameter.

    Quote Originally Posted by Ezku
    DataSource, as said, implies read-only. DataObject, while accurate, is a bit awkward for a name. On the other hand, DataSpace just seems odd, which leaves me with DataSet. And doesn't that name imply something "dynamic"?
    I vote for DataSpace.

    Sorry for lagging behind, but I think we should primarly focus on the AC / Statemachine etc, and leave the Input Controller for a moment.

  25. #75
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Overunner
    1. How is the Application Controller, Input Controller and Flow Controller related to each other? Do they
    co-operate anything? By just looking at the code, I think the responsibilities of the Flow Controller overlap with the Input Controller.
    There have in fact been two slightly different designs in the discussion. There is what we could call the FlowController-design, which is mostly my brainchild. Then there is the design which arborint is toying with. We could call that the StateMachine-design. I presented a variation over this in post #55, but they are more or less equal.

    The main difference between the two designs is that in the FlowController-design, there is no InputController. Instead that resposibility is pushed into the FlowController which acts as a combination of Validator, InputController and Transition. The actual implementation may seperate theese into different components, which would make the FlowController a composite of thoose. This is what Ezku have been moving towards in post #58

    On the contrary, the StateMachine-design has an InputController as the main catalyst, which use the StateMachine for holding state (Transitions describe a change in state). It has a 1:1 relationship between Transition<->Validator like the FlowController-design, but they are passive players, in contrast to the FlowController-design.

    Quote Originally Posted by arborint
    Also, the Input Controller needs to add some logic to "control" the Application Controller and dispatch the Command(s). So far the InputController class is just a Request Processor so controlling the Application Controller needs to be added.
    This is rather important, and I think the main reason why we're bugging around with the design.
    I have a sneaky feeling that as begin to work on the InputController, the code will end up looking more like the FlowController-design.

    Quote Originally Posted by Ezku
    Someone mentioned saying you could use just a filter instead of a chain, just a rule instead of a validator etc - and I'm seeing that here now. So should IInputRule be changed to match Validator so Validator could implement it, and should InputController implement IInputRule as well?
    Yes, I think that would be nice if possible.

    Quote Originally Posted by Overunner
    Sorry for lagging behind, but I think we should primarly focus on the AC / Statemachine etc, and leave the Input Controller for a moment.
    Actually I'd say no. We need to consider the strength/weekness in the FlowController- vs. StateMachine-design. The InputController belongs to the latter.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •