SitePoint Sponsor

User Tag List

Page 3 of 3 FirstFirst 123
Results 51 to 71 of 71
  1. #51
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Agree. The control of button press, is like the navigation in a site links. It looks like a state machine.
    If you implemented an event based system it could handle the request events and things like divide by zero and overflow as well.
    Christopher

  2. #52
    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 Captain Proton
    So, what do we choose?
    The calculator model in both cases is the same.

    In the first case, the controller takes "(( 4 + 30 ) / 2.5) - 30" directly from $_POST and passes it to the Model, then sends the result off to the View.

    In the second case, it depends what type of calculator we are building:

    • For a scientific calculator, it will build up the above string step by step, and when the user clicks the "equals" or "execute" button (depending on which brand our calculator is ) it will pass the whole thing to the model. It is basically a satateful version of Case 1, so we would probably have a State model. This bit is better written in Javascript, but then it becomes cade 1!
    • For a regular calculator, the "building up" process is a little simpler. Whenever an operator button is pressed (+, -, =) the current string will be passed to the model, and the result sent to the View for display.


    Douglas
    Hello World

  3. #53
    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 DougBTX
    In the first case, the controller takes "(( 4 + 30 ) / 2.5) - 30" directly from $_POST and passes it to the Model, then sends the result off to the View.
    In MVC, the model - or domain - exists in a cosseted, abstract world of its own. If it wants a grape, a servant peels it first. Parsing an input string is a job for the controller layer, I think. The controller receives input, figures out which type of calculation was requested, calls the appropriate method on a domain object, and passes args to the method (rather than the entire input string).

    Also, the controller shouldn't be an intermediary between the model and view. After manipulating the domain, the controller would tell the view to update and then the view fetches its own data from the domain layer (model).

  4. #54
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It is an interesting decision. Is the Controller a parser, and the Model just deals with primatives? Or does the Model accept only equations and the Controller turns everything into an equation string?
    Christopher

  5. #55
    SitePoint Zealot
    Join Date
    Feb 2003
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by BerislavLopac
    The MVC concept, should be the same even in a web or desktop app.
    Perhaps I don't really understand what you're trying to say, but this sentence is simply incorrect.
    Yes, BerislavLopac is of course correct. Here is another post that makes it pretty clear: http://jroller.com/page/kame/2004102...litany_goes_on

    JSP Model 2 has very little to do with MVC as used in Desktop apps. Most people (me included) always say MVC when they talk about either, but this can be very confusing for people who have only worked with either one of them, and not the other. It is important to know the difference.

  6. #56
    SitePoint Addict timvw's Avatar
    Join Date
    Jan 2005
    Location
    Belgium
    Posts
    354
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    It is an interesting decision. Is the Controller a parser, and the Model just deals with primatives? Or does the Model accept only equations and the Controller turns everything into an equation string?
    Well, the controller has to make sure that the model is updated according to the user input.

    So if the model accepts complete expressions, all it has to do is make sure the expression is valid (only numbers + * - / or allowed for example) and pass it to the model.

    If the model accepts only "atomic operations" the controller would have to parse them, make sure they are valid, and pass them one by one to the model.

    We could also implement an Expression Parser in the model, and then connect the controller to this EP.

    Conclusion: It depends on the interface the model provides us...

  7. #57
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think it makes sense to keep the Controller, Parser and Calculator separate for testing purposes. Whether the Parser is in the Controller or Calculator (Model) I am not sure. I do like the idea of keeping the Controller to simple filtering and validation.
    Christopher

  8. #58
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by neves
    Ren, can you explain how works your grammar?
    The grammar is converted into PHP (in this case an PHP5 class). This is basically a bunch of arrays describing the automata. PHP code in the preceding each grammer rule is inserted into a switch.

    Attached is a basic cli runnable version.
    Code:
    php cli.php 1+2
    3
    ExpressionParser.php is generated from stock PHP code template and the grammar.

    Lemon is what I used in this case (well a not-yet-quite complete port/adaption of).

    If want to read more about grammars and generation, I recommend "Compilers: Principles, Techniques and Tools" (also commonly know as "The Dragon Book") by Aho, Ullman & Sethi. ISBN 0201100886 .

    There are also lots of articles on the 'net.


    nondeterministic & deterministic finite state automata
    finite state machines
    parser generators
    yacc
    bison
    Attached Files Attached Files

  9. #59
    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 McGruff
    If it wants a grape, a servant peels it first.
    That would be urldecode, which PHP does automatically.

    The controller receives input, figures out which type of calculation was requested...
    The controller only remarks that a calculation was requested. The rules of that calculation are handled by the model. Not just handled by the model, those rules are the model.

    The model in this case is Ren's ExpressionEvaluator, which should be the same regardless of what type of controller/view is used.

    In Ren's cli.php, you could add a method to ExpressionEvaluator to return the last calculated value of $r then pass the whole ExpressionEvaluator to the view. But, consider $r as a read-only version of the model. The view should not manipulate the model, so passing the view a read-only version of the model is perfectly fine.

    Douglas
    Hello World

  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)
    Here's a simple web interface for Ren's model. (edit: now with clear button! )

    Douglas
    Attached Files Attached Files
    Last edited by DougBTX; Jun 4, 2005 at 11:10.
    Hello World

  11. #61
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A string "(( 4 + 30 ) / 2.5) - 30" which you receive via POST is input, and input in a specific format.

    The first decision to make is whether to attempt a calculation at all or dump the user in a 400 page - or do nothing and just redisplay the calculator or whichever other way you want to handle it. This is application controller logic ie deciding which out of a range of possible responses should be made to a request.

    Validation might initially involve some kind of regex check like: [0-9/*+\-()]+. (You should really validate GET and COOKIE as well - even if you're not using them at least assert they are empty). The POST input could pass this simple regex check but still be unparsable. Ask the Parser:

    PHP Code:
                    if($parser->isParsable($request->getCalculationString())) {
                        
    // etc
                    

    There could be a big difference between failing the [0-9/*+\-()]+ check and other kinds of unparsable input. The former is more likely to be a hacking attempt (you won't be expecting < script > as part of the calculator input..). The latter is more likely to be an application error, ie you messed up somewhere in the UI. Nothing is conclusive but it maybe pays to try to tease the two apart as much as you can so that you can choose how you want to respond. Of course if you're testing you won't have any application errors

    If the input string represents a valid calculation, this has to be interpreted into domain calls. If you put interpretation in the model, the model is tied to a particular input format. Clearly, that's cutting across the presentation/domain layers. It's definitely the job of the controller layer to identify the request and map this to domain calls. In this case the controller migth make several manipulations of the model, in sequence:

    PHP Code:
                    $calculator =& new Calculator;
                    
    $calculator->add(4);
                    
    $calculator->add(30);
                    
    $calculator->divideBy->(2.5);
                    
    $calculator->subtract(30); 
    In a calculator, the domain logic/business rules/model or whatever you call it are very simple (unless you start adding complex statistical functions etc). If it's not, that's a sign something is wrong. The controller's got all the hard work to do.

    The Parser is really part of a "request model" rather than the problem domain. It carries out controller-layer logic (interpreting input & mapping this to a response) rather than the actual calculations themselves. Other aspects of the request model are the basic GPC checks mentioned above.

    A request model can of course ask domain objects for information - the presentation layer is free to roam across the domain. However, in this case, I don't think the Parser is a domain object.

    After manipulating the domain, the controller would tell the view to update - the view just asks the calculator for the current total and displays it.

  12. #62
    SitePoint Zealot
    Join Date
    Jul 2004
    Location
    Brazil,Maringá-PR
    Posts
    128
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Smile

    Quote Originally Posted by McGruff
    If the input string represents a valid calculation, this has to be interpreted into domain calls. If you put interpretation in the model, the model is tied to a particular input format. Clearly, that's cutting across the presentation/domain layers. It's definitely the job of the controller layer to identify the request and map this to domain calls. In this case the controller migth make several manipulations of the model, in sequence:

    PHP Code:
                    $calculator =& new Calculator;
                    
    $calculator->add(4);
                    
    $calculator->add(30);
                    
    $calculator->divideBy->(2.5);
                    
    $calculator->subtract(30); 
    IMHO, that's true. Suppose a desktop calculator, where the user click a button. As you can see, there's no string to be parsed. So, I would hava my model, and a layer above the model, that translate the input. And this layer, I could swap as I need.
    That's the right way to me, cause it's very loose coupling.

  13. #63
    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 neves
    IMHO, that's true. Suppose a desktop calculator, where the user click a button. As you can see, there's no string to be parsed.


    The string I'm talking about is the line which reads "1234567890x2" in the image above.

    I guess validation of the input is easier there, as the only symbols that can get in the string are directly related to the buttons on the calculator I don't think that the controller side of the validation should go beyond checking that the input consists only of things which can result from button presses.

    So, I would hava my model, and a layer above the model, that translate the input. And this layer, I could swap as I need.
    See the zips above, they do this! Compare web.php with cli.php.

    You still need the parser if you want to support the command line. Whether you think the M/C line is drawn on the left or the right of the parser, you still need one I find that when I have more work to do in the controller than the model, there is probably something wrong. I guess McGruff prefers a simple model to a simple controller. In this project, we can use tools like Lemon to generate the model from simple grammar rules, so you get simplicity in M and C without sacrificing power!

    Douglas
    Last edited by DougBTX; Jun 4, 2005 at 14:54.
    Hello World

  14. #64
    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 neves
    Let's take the windows calculator as inspiration
    My one comes up with something like this from microsoft.com!



    Hello World

  15. #65
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The Parser is really part of a "request model" rather than the problem domain. It carries out controller-layer logic (interpreting input & mapping this to a response) rather than the actual calculations themselves. Other aspects of the request model are the basic GPC checks mentioned above.
    Not by definition, I think, since the Parser does not determine what view to display. I think it should be considered a model object.

  16. #66
    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 McGruff
    The Parser is really part of a "request model" rather than the problem domain. It carries out controller-layer logic (interpreting input & mapping this to a response) rather than the actual calculations themselves.
    How would you separate the parser from the calculations in this example? Currently the atomic calculations themselves are in the private yyReduce method of the ExpressionParser class. What benifit would this give us in the CLI case?

    Douglas
    Hello World

  17. #67
    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 DougBTX
    How would you separate the parser from the calculations in this example?
    I don't know. I didn't look at the code - just tried to think it through starting from the POST string. Is the parser doing the calculations as well as the input parsing? That doesn't sound good.

    I'm sticking with the view that the problem domain associated with a calculator is calculation, not input string parsing. I suppose it might be convenient to blur the two together and I guess you can "de-normalise" an application design as you might with db design, provided you're fully aware of possible consequences.

  18. #68
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    I don't know. I didn't look at the code - just tried to think it through starting from the POST string. Is the parser doing the calculations as well as the input parsing? That doesn't sound good.
    I could have written it like

    PHP Code:

    interface Expression
    {
        function 
    getValue();
    }

    class 
    SubExpression implements Expression
    {
        protected 
    $expression;
        function 
    __construct(Expression $subExpression) { $this->subExpression $subExpression; }

        function 
    getValue() { return $this->subExpression->getValue(); }
    }

    abstract class 
    BinaryExpression implements Expression
    {
        protected 
    $left;
        protected 
    $right;
        
        function 
    __construct(Expression $leftExpression $right)
        {
            
    $this->left $left;
            
    $this->right $right;
        }
    }

    class 
    AddExpression extends BinaryExpression
    {
        function 
    getValue() { return $this->left->getValue() + $this->right->getValue(); }
    }

    class 
    SubtractExpression extends BinaryExpression
    {
        function 
    getValue() { return $this->left->getValue() - $this->right->getValue(); }
    }

    class 
    MultiplyExpression extends BinaryExpression
    {
        function 
    getValue() { return $this->left->getValue() * $this->right->getValue(); }
    }

    class 
    DivideExpression extends BinaryExpression
    {
        function 
    getValue() 
        {
            
    $r $this->right->getValue();
            if (
    $r == 0
                throw new 
    DivisionByZeroException();
            return 
    $this->left->getValue() / $r
        }
    }

    class 
    ConstantExpression implements Expression
    {
    }

    class 
    NumberExpression extends ConstantExpression
    {
        protected 
    $value;
        function 
    __construct($value) { $this->value $value; }
        function 
    getValue() { return $this->value; }
    }

    interface 
    ExpressionFactory
    {
        function 
    createSubExpression(Expression $subExpression);

        function 
    createAddExpression(Expression $leftExpression $right);
        function 
    createSubtractExpression(Expression $leftExpression $right);
        function 
    createMultiplyExpression(Expression $leftExpression $right);
        function 
    createDivideExpression(Expression $leftExpression $right);
        function 
    createNumber($value) { return new NumberExpression($value);
    }


    class 
    DefaultExpressionFactory implements ExpressionFactory
    {
        function 
    createSubExpression(Expression $subExpression) { return new SubExpression($subExpression); }

        function 
    createAddExpression(Expression $leftExpression $right) { return new AddExpression($left$right); }
        function 
    createSubtractExpression(Expression $leftExpression $right) { return new SubtractExpression($left$right); }
        function 
    createMultiplyExpression(Expression $leftExpression $right) { return new MultiplyExpression($left$right); }
        function 
    createDivideExpression(Expression $leftExpression $right) { return new DivideExpression($left$right); }
        function 
    createNumber($value) { return new NumberExpression($value); }

    And written the grammar like...

    Code:
    expression(A)	::= OPENPARENTHESIS expression(X) CLOSEPARENTHESIS.		{ A = $factory->createSubExpression(X);  }
    expression(A)	::= expression(X) PLUS expression(Y).					{ A = $factory->createAddExpression(X, Y); }
    expression(A)	::= expression(X) MINUS expression(Y).					{ A = $factory->createSubtractExpression(X, Y); }
    expression(A)	::= expression(X) ASTERIX expression(Y).				{ A = $factory->createMultiplyExpression(X, Y); }
    expression(A)	::= expression(X) FORWARDSLASH expression(Y).			{ A = $factory->createDivideExpression(X, Y); }
    
    expression(A)	::= NUMBER(X).											{ A = $factory->createNumber(X); }
    Which then gives an abstract syntax tree of the expression.

    and then use $expression->getValue() to evaluate.

    But what do I gain from doing so? I've just written alot more code which I dont really need yet, or may never.

  19. #69
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ren, in your Expr.zip example, which parts of the code were generated from the grammar and which parts did you write yourself?

    Dogulas
    Hello World

  20. #70
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not sure about Expression classes. They don't have any state and just one method. The state is the running total of various calculations so maybe it's better to encapsulate this with the methods which act upon it in a calculator class.

    A Parser could make calls to calculator methods as it identifies calculations to perform, in the proper sequence. Identifying the sequence is the tough bit.

  21. #71
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DougBTX
    Ren, in your Expr.zip example, which parts of the code were generated from the grammar and which parts did you write yourself?

    Dogulas
    Lemon takes a grammar and a code template. [Template attached.]
    And outputs ExpressionParser.php, there is a minor bug preventing the generated directly (a miss placed }, hence why I havent released it yet).

    The template is general and should be common to most parsers, with %% as placeholders where lemon inserts data/code.
    Attached Files Attached Files


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
  •