SitePoint Sponsor

User Tag List

Page 2 of 2 FirstFirst 12
Results 26 to 50 of 50
  1. #26
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    996
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Just to put what ServerStorm was hinting towards on the table and re-introducing some flexibility and separation of concerns. I've severely cut down the class for ease of demonstration:


    PHP Code:
    interface DogRenderer {
        public function 
    render($name$age);
    }

    class 
    Dog {
        protected 
    $name;
        protected 
    $age;
        
        public function 
    dispatch(DogRenderer $renderer) {
            
    $renderer->render($this->name$this->age);
        }
        
    }


    class 
    MyDogRenderer implements DogRenderer {
        protected 
    $html;
        
        public function 
    render($name$age) {
            
    $this->html 'Name: ' $name ' Age: ' $age;
        }
        
        public function 
    output() {
            return 
    $this->html;
        }
    }


    $dog = new Dog();
    $renderer = new MyDogRenderer();
    $dog->dispatch($renderer);
    echo 
    $renderer->output(); 
    Which should remove some of the valid criticism noted above.

    However, my issue still stands, adding a single field e.g. "weight" requires:

    -Adding the protected property
    -Extending the interface (we can't modify DogRenderer as we don't know where it's currently used)
    -Either adding a new dispatch method for the new interface to Dog
    --Or adding some logic to the dispatch function to check which interface it's been passed (of course, if php supported method overloading this wouldn't be an issue)

    Wheras with a getter or public property, you add the property and change the HTML. The former method is a maintainability nightmare, in my opinion.

  2. #27
    Foozle Reducer ServerStorm's Avatar
    Join Date
    Feb 2005
    Location
    Burlington, Canada
    Posts
    2,699
    Mentioned
    89 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by Jeff Mott View Post
    I don't mean to pile on, but I agree with itmitică and Tom. The describe method is doing templating in a class that otherwise handles application logic. If that's the cost of avoiding getters, then that cost is too high. Using getters would actually be better. And the age, isGoingGrey, and changeCollar methods are still getters and setters even if you avoid the words "get" and "set".

    On an unrelated note, the dateDiff method is probably unecessary. You can use the built-in dateDiff.
    Hi,

    Yes there is still a need to get or set logic within an object. You are right that I could have called them getColour(), getAge(), setGetCollar(). Out of these the only public of them is setGetCollar(). The getColour() and getAge() are coupled to internal logic. this type of coupling does not break encapsulation; setGetCollar() does.

    As far as the templating in an object that handles application logic, yup. In hind-sight it would have been best to do this in at least two objects on that handles the template and the other that handles the applicaiton logic. As mentioned earlier this was an attempt to build something that used some of the ideas and did not force people to worry about that part of it. Does not look as it has served the intended purpose, but still it should not diminish the idea that encapsulation still an important pillar in Object Oriented Methodology.

    BTW thanks for the dateDiff() reference.

    Regards,
    Steve
    ictus==""

  3. #28
    Foozle Reducer ServerStorm's Avatar
    Join Date
    Feb 2005
    Location
    Burlington, Canada
    Posts
    2,699
    Mentioned
    89 Post(s)
    Tagged
    6 Thread(s)
    Hi,


    I am not sure if you know of or agree with Martin Fowler, but I can say that I know why he writes books like Patterns of Enterprise Application Architecture


    He has some interesting ideas on what we've been discussing, not all support my angle in this discussion, so here are a few one page articles surrounding this topic:


    http://martinfowler.com/bliki/Constr...alization.html
    http://martinfowler.com/bliki/SetterInitialization.html
    http://martinfowler.com/bliki/GetterEradicator.html
    /* Interace Publication */
    http://martinfowler.com/ieeeSoftware/published.pdf


    These and more articles can be found at http://martinfowler.com/tags/API%20design.html. His main site is www.martinfowler.com


    Regards,
    Steve
    ictus==""

  4. #29
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    As promised, this is my fiddle modeling for today: http://i1054.photobucket.com/albums/...mitica-dog.png

    Tomorrow it's code day.

    Feel free to ask a question or dismantle the model.

  5. #30
    Foozle Reducer ServerStorm's Avatar
    Join Date
    Feb 2005
    Location
    Burlington, Canada
    Posts
    2,699
    Mentioned
    89 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by itmitică View Post
    As promised, this is my fiddle modeling for today: http://i1054.photobucket.com/albums/...mitica-dog.png

    Tomorrow it's code day.

    Feel free to ask a question or dismantle the model.
    Hi itmitică,

    When I try to open your link I get the following error:
    An HTTP error occurred while getting:http://i1054.photobucket.com/albums/...mitica-dog.png
    Details: "Unable to contact target server after 5 tries.".
    ictus==""

  6. #31
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)

  7. #32
    Foozle Reducer ServerStorm's Avatar
    Join Date
    Feb 2005
    Location
    Burlington, Canada
    Posts
    2,699
    Mentioned
    89 Post(s)
    Tagged
    6 Thread(s)
    Ruff, Rufff... Spot fetch setters and getters... Good Boy! Spot don't pee on encapsulation. Oh wait that's not a cool cat, go ahead boy. (Dog wags tail obsessively).

    I see were your positioned.

    Thanks,
    Steve
    ictus==""

  8. #33
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ServerStorm View Post
    I see were your positioned.
    I'm trying to base our talk on an example so that we can actually talk specifics. I'm also going somewhere with all this, once the code is in place too. I figured I'd cut down the whole scenario to just one possibility and make classes design target that possibility, thus slimmer and clearer.

    I'm not so sure why you're saying I'm ruining encapsulation? Maybe you're misinterpreting something? Like I said, feel free to ask a question or dismantle the model. I won't mind.

  9. #34
    Foozle Reducer ServerStorm's Avatar
    Join Date
    Feb 2005
    Location
    Burlington, Canada
    Posts
    2,699
    Mentioned
    89 Post(s)
    Tagged
    6 Thread(s)
    Sorry, it was too lighten the mood a little;

    Would you say you would normally favour constructor initialization or do you favour setter initialization?

    In the articles by Martin Fowler, he makes a good point that if you add a setter for a new property or a new getter that are public that search and place is relatively easy. He also talks about how it is not normally a problem when the code stays in his team (or himself), but does affected people when he releases library code out for the public domain. Then if we adds or removes setters/getters he can't use search and replace and therefore breaks other that use the older code base.

    Have you every tried to write your objects to have very focused responsibilities and then based on the objects that you set with constructor initialization are composited within another object that makes use of their run() or like command?

    Have you used traits to more effectively use inheritance?

    Thanks for your work on this.

    Regards,
    Steve
    ictus==""

  10. #35
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,313
    Mentioned
    19 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by TomB View Post
    Just to put what ServerStorm was hinting towards on the table and re-introducing some flexibility and separation of concerns. I've severely cut down the class for ease of demonstration:
    It's a clean and interesting example, for sure, but I'm not sure it solves the original concern. The original concern put forth by the article with the hyperbole title is that getters subtly break encapsulation by revealing a private member's data type -- which is true. If "age" was once a timestamp integer and now we want to change it to a DateTime object, we can't do that without breaking backward compatibility, because even though "age" may be private, it's data type isn't. And the same problem exists with the renderer example, because the renderer class depends on "age" being a certain data type.

    I see two competing design decisions here. If we ensure that all private members are fully private, data types and all, then the Dog class must handle every task that uses Dog data, including templating. Or if we ensure good separation of concerns, then we must extract data from Dog, one way or another, which will reveal data types. I don't see how we can have it both ways, and if I had to pick the lesser of two evils, I'd say it's better to have good separation of concerns.

  11. #36
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ServerStorm View Post
    Would you say you would normally favour constructor initialization or do you favour setter initialization?
    I'd say constructor initialization. Normally.

    I have part of my code finished... it goes there, but hardly still... but for a complete discussion about encapsulation and getters/setters on an example I think it's better to finish it first. Anyway, here it is what I have so far:

    Code:
    // start of app
    
    $earth = new World('Earth');
    
    $dog_barking = new Sound(
        'barking', 
        'Spot', 
        array(
            'type'  => 'house',
            'owner' => 'John' 
        )
    );
    
    $earth->event( $dog_barking );
    Code:
    class World {
        protected $name;
        protected $event;
        
        protected __contruct ($_name) {
            $this->name = $_name;
        }
        
        public event( $_event ) {
            $this->event = $_event;
        
            if ( $this->event->location['type'] == 'house' ) {
                $this->man = new Man( $this->event->location['owner'] );
                $this->man->alert( $this->event->name, $this->event->source );
            }
        }
    }
    Code:
    class Sound {
        protected $name;
        protected $source;
        protected $location;
        
        protected __construct( $_name, $_source, $_location ) {
            $this->$name = $_name;
            $this->$source = $_source;
            $this->location = new Location($_location);
        }
    }
    Feel free to ask a question or dismantle this one too.

  12. #37
    Foozle Reducer ServerStorm's Avatar
    Join Date
    Feb 2005
    Location
    Burlington, Canada
    Posts
    2,699
    Mentioned
    89 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by Jeff Mott View Post
    It's a clean and interesting example, for sure, but I'm not sure it solves the original concern. The original concern put forth by the article with the hyperbole title is that getters subtly break encapsulation by revealing a private member's data type -- which is true. If "age" was once a timestamp integer and now we want to change it to a DateTime object, we can't do that without breaking backward compatibility, because even though "age" may be private, it's data type isn't. And the same problem exists with the renderer example, because the renderer class depends on "age" being a certain data type.

    I see two competing design decisions here. If we ensure that all private members are fully private, data types and all, then the Dog class must handle every task that uses Dog data, including templating. Or if we ensure good separation of concerns, then we must extract data from Dog, one way or another, which will reveal data types. I don't see how we can have it both ways, and if I had to pick the lesser of two evils, I'd say it's better to have good separation of concerns.
    Hi Jeff,

    What about standardizing the render interface in each object that needs to play together. So we have a public method render() on each object. This render method does not take any parameters. We tell each object to render its' state. In the most simplistic form we could put each object in an array and issue the render() method. Each render() method could have their own details implemented and dictated by what each class needs to do. The logic inside could be changed by a little or lot and as long as they are wired to the render() method it would create a data output suitable for the medium (such as a web page)? This keeps the encapsulation, and adheres to a strict interface. In this way the Private Objects would likely have Model Contoller and View?

    Steve
    ictus==""

  13. #38
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ServerStorm View Post
    What about standardizing the render interface in each object that needs to play together.
    This has already been done in frameworks that use different templating systems.

    One way they do it is like this:
    - the main framework on one hand, with a view property and a corresponding render() method
    - the "original" view framework on the other hand, with a parseHTML() method, for example
    - an interim view class between them, that takes the place of the view property and transforms the render() method for the main framework to the parseHTML() method or whatever method the "original" view framework has assigned for outputing

  14. #39
    Foozle Reducer ServerStorm's Avatar
    Join Date
    Feb 2005
    Location
    Burlington, Canada
    Posts
    2,699
    Mentioned
    89 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by itmitică View Post
    This has already been done in frameworks that use different templating systems.

    One way they do it is like this:
    - the main framework on one hand, with a view property and a corresponding render() method
    - the "original" view framework on the other hand, with a parseHTML() method, for example
    - an interim view class between them, that takes the place of the view property and transforms the render() method for the main framework to the parseHTML() method or whatever method the "original" view framework has assigned for outputing
    I see... that was not exactly what I was thinking, more like:

    PHP Code:
    class Dog {
      
    /* private things */

      
    public function render(){
        
    /* My way of rendering myself */
      
    }
    }

    class 
    Human {
      
    /* private things */

      
    public function render(){
        
    /* My way of rendering myself */
      
    }
    }

    $animals = array( 'Dog' => new Dog(), 'Human' => new Human()); 
    Some where in the webpage

    PHP Code:
    <div>
    <?php
       $animals
    ['Dog']->render();
    ?>
    </div>
    Some where else in the webpage

    PHP Code:
    <?php
       $animals
    ['Human']->render();
    ?>
    or

    PHP Code:
    foreach($animals as $type => $animal){
        
    $animal->render();} 
    ictus==""

  15. #40
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,313
    Mentioned
    19 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by ServerStorm View Post
    I was thinking, more like:

    PHP Code:
    class Dog {
      
    /* private things */

      
    public function render(){
        
    /* My way of rendering myself */
      
    }
    }

    ...

       
    $animals['Dog']->render(); 
    The problem here, though, is that you're still doing templating inside the Dog class. What if there's more than one way to render a dog? What if you want to render a short snippet for a dog list page, or full content for a dog detail page, or what if you want to render to JSON format, or XML, or what if you want to render an email message, or what if you want to render all those things but with multiple themes? Suddenly the Dog class is taking on far too much responsibility and knows far too much about the application.

  16. #41
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ServerStorm View Post
    I see... that was not exactly what I was thinking, more like:

    PHP Code:
    class Dog {
      
    /* private things */

      
    public function render(){
        
    /* My way of rendering myself */
      
    }
    }

    class 
    Human {
      
    /* private things */

      
    public function render(){
        
    /* My way of rendering myself */
      
    }
    }

    $animals = array( 'Dog' => new Dog(), 'Human' => new Human()); 

    Or maybe like this?

    PHP Code:
    class Mammal {
      
    /* private things */

      
    public function render(){
        
    /* Mammal way of rendering itself */
      
    }
    }

    class 
    Dog extends Mammal {
      
    /* private things */
      
    private smells_real_good;

      public function 
    render(){
        
    parent::render();
        
    /* +Dog way of rendering itself */
      
    }
    }

    class 
    Human extends Mammal {
      
    /* private things */
      
    private drives_cars;

      public function 
    render(){
        
    parent::render();
        
    /* +Human way of rendering itself */
      
    }
    }

    $animals = array( 'Dog' => new Dog(), 'Human' => new Human()); 
    Let's not forget inheritance. It may hinder with your design a little.

    Though it's not clear from your example, but if you completely (and, most likely, redundantly) handle the render method inside each class rather then delegating it to view-centric classes, you're kissing DRY and reusability good bye. The very reasons why this kind of encapsulation and why making a goal out of erasing getters/setters are not worth it.

  17. #42
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    996
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Quote Originally Posted by Jeff Mott View Post
    It's a clean and interesting example, for sure, but I'm not sure it solves the original concern. The original concern put forth by the article with the hyperbole title is that getters subtly break encapsulation by revealing a private member's data type -- which is true. If "age" was once a timestamp integer and now we want to change it to a DateTime object, we can't do that without breaking backward compatibility, because even though "age" may be private, it's data type isn't. And the same problem exists with the renderer example, because the renderer class depends on "age" being a certain data type.
    Indeed. Of course in a strongly typed language you'd specify the return types in the DogRenderer interface and that wouldn't be an issue.

    I see two competing design decisions here. If we ensure that all private members are fully private, data types and all, then the Dog class must handle every task that uses Dog data, including templating. Or if we ensure good separation of concerns, then we must extract data from Dog, one way or another, which will reveal data types. I don't see how we can have it both ways, and if I had to pick the lesser of two evils, I'd say it's better to have good separation of concerns.
    I think that's a very eloquent description of the problem at hand. In my example, if the interface could enforce data types, the dog class would deal with exporting the data. As usual it's a trade-off and I'd agree that good separation of concerns is far more important. Even the added complexity of the double dispatch code I posted above is a huge negative in my opinion.

    I think one thing to remember here is that every class has an API. Once that's published and in use in production it shouldn't change without breaking. This is fundamental in OOP. If getAge() was designed to return an integer timestamp then it always should. How that time is represented within the Dog class is irrelevant as long as the Dog class returns the value in the type required of it when getAge() is called. getAge() can transparently do the conversion internally if needed.

  18. #43
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,313
    Mentioned
    19 Post(s)
    Tagged
    1 Thread(s)
    Agree with all of that.

  19. #44
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ServerStorm View Post
    PHP Code:
    <?php
       $animals
    ['Human']->render();
    ?>
    A key aspect of MVC (at least how I understand it) is that the view has full control over what it outputs, not the class. So by giving choice of how to render to the class, that makes the view semi-redundant.

    I like a data-holding class to be in full control of its data and how other things access that data, but I don't like it doing much more than that. Then there are classes which control flow, and then the views which throw that all together and display them as they want. Of course, that's just the way I like it done
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  20. #45
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Jeff Mott View Post
    It's a clean and interesting example, for sure, but I'm not sure it solves the original concern. The original concern put forth by the article with the hyperbole title is that getters subtly break encapsulation by revealing a private member's data type -- which is true. If "age" was once a timestamp integer and now we want to change it to a DateTime object, we can't do that without breaking backward compatibility, because even though "age" may be private, it's data type isn't. And the same problem exists with the renderer example, because the renderer class depends on "age" being a certain data type.
    I can always extend classes and change all that without breaking backwards compatibility. There are some concerns in doing that, but it is a viable and it's a used solution.

  21. #46
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    996
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Changing the return type of a method in a child class would break polymorphism and in my opinion is worse than adding another method which gets the same data in a different format.

  22. #47
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    Actually I was thinking about another method in the child class. This because method overload is not that straightforward in PHP. I was also thinking about code I'm not authoring directly, i.e. third party frameworks. As such, I don't want to worry about in-file code details whit every new version of the frameworks I may use, by directly changing the code in the original class.

    Going back to what you said, method overloading doesn't break polymorphism. And, in this case, getters/setters would also need overloading.

    And backward compatibility and encapsulation are not the same thing.

  23. #48
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    996
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Ah I thought you were suggesting overloading the method in the child class which, as you say, isn't easy in PHP. Method overloading in PHP does break polymorphism because PHP doesn't support it properly.

    e.g.

    PHP Code:

    class Dog {
      public function 
    setBirthday($d$m$y) {
       
      }
    }

    class 
    Dog2 extends Dog {
     public function 
    setBirthday(DateTime $date) {

     }

    In some languages this is allowed and would work as expected. Obviously in PHP it won't.

  24. #49
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    Method overloading in PHP does break polymorphism because PHP doesn't support it properly.
    It doesn't mean it can't be done. Exception is your friend.

    Anyway, I'm almost done with the code. You know, a little procrastination, a little busy at work. Tomorrow I'll post it so we'd have something to talk about specifically.

  25. #50
    Non-Member
    Join Date
    Feb 2012
    Posts
    892
    Mentioned
    10 Post(s)
    Tagged
    0 Thread(s)
    As promised, a code we can discuss about.

    The short story... picture-short: http://i1054.photobucket.com/albums/...tica-dog-2.png

    The short story... php-short:
    PHP Code:
    // A short story
    echo '<h1>World events</h1>';

    // Once upon a time on Earth.
    $earth = new World'Earth' );

    // Something was happening.
    echo '<hr>';
    echo 
    '<h2>Event #1</h2>';

    // A dog named Spot was barking at John's house.
    // John, like a good master, feeds Spot.
    // Spot is eating now.
    $spot = new Dog'Spot' );
    $spot -> bark();

    $john = new Man'John' );
    $john_house = new Location'house'$john );

    $spot_barking = new Sound$spot$john_house );
    $earth -> event$spot_barking );

    // Another thing happen then.
    echo '<hr>';
    echo 
    '<h2>Event #2</h2>';

    // A dog named Rex sees Spot eating and barks at John's house too.
    // John is not Rex's master. He's chasing Rex away.
    $rex = new Dog'Rex' );
    $rex -> bark();

    $rex_barking = new Sound$rex$john_house );
    $earth -> event$rex_barking );

    // Rex runs to his master's house, Bob, and barks.
    // Bob is also a good master. He feeds Rex.
    // Rex is eating too now.
    echo '<hr>';
    echo 
    '<h2>Event #3</h2>';
    $bob = new Man'Bob' );
    $bob_house = new Location'house'$bob );

    $rex_barking -> changeLocation$bob_house );
    $rex -> bark();
    $earth -> event$rex_barking );

    // The End.
    echo '<hr>'
    The whole deal in one file:
    PHP Code:
    <?php

    trait Base {

        public function 
    getProperty$property ) {
            return 
    $this -> $property;
        }
    }


    class 
    World {
        
        use 
    Base;
        
        protected 
    $name;
        protected 
    $event;
        
        public function 
    __construct $name ) {
            
    $this -> name $name;
        }
        
        public function 
    event$event ) {
            
    $this -> event $event;
            
            echo 
    '<h3>' .
                    
    $this -> event -> getProperty'source' ) -> getProperty'name' ) . ' is ' .
                    
    $this -> event -> getProperty'source' ) -> getProperty'activity' ) . ' at ' .
                    
    $this -> event -> getProperty'location' ) -> getProperty'owner' ) -> getProperty 'name' )  . '\'s ' .
                    
    $this -> event -> getProperty'location' ) -> getProperty'type' ) . '.' .
                 
    '</h3>';
                 
            if ( 
    $this -> event -> getProperty'location' ) -> getProperty'type' ) == 'house' ) {
                
    $this -> event -> getProperty'location' ) -> getProperty'owner' ) ->
                    
    alert$this -> event -> getProperty'source' ) );
            }
            
            echo 
    '<p>' 
                    
    $this -> event -> getProperty'location' ) -> getProperty'owner' ) -> getProperty 'name' ) . ' is ' 
                    
    $this -> event -> getProperty'location' ) -> getProperty'owner' ) -> getProperty 'activity' ) . ' ' .
                    
    $this -> event -> getProperty'source' ) -> getProperty'name' ) . '. ' .
                    
    $this -> event -> getProperty'source' ) -> getProperty'name' ) . ' is ' .
                    
    $this -> event -> getProperty'source' ) -> getProperty'activity' ) . '.' .
                 
    '</p>';
        }
    }


    class 
    Sound {
        
        use 
    Base;

        protected 
    $source;
        protected 
    $location;
        
        public function 
    __construct$source$location ) {
            
    $this -> source $source;
            
    $this -> location $location;
        }
        
        public function 
    changeLocation$newlocation ) {
            
    $this -> location $newlocation;
        }
    }


    class 
    Location {

        use 
    Base;
        
        protected 
    $type;
        protected 
    $owner;
        
        public function 
    __construct$type$owner ) {
            
    $this -> type $type;
            
    $this -> owner $owner;
        }
    }


    class 
    Man {

        use 
    Base;
        
        protected 
    $name;
        protected 
    $activity 'idle';
        protected 
    $alertsource;
        
        protected 
    $dogResponse = [
          
    'feeding' => 'eat',
          
    'chasing'  => 'run'
        
    ];
        
        public function 
    __construct$name ) {
            
    $this -> name $name;
        }
        
        public function 
    alert$source ) {
            
    $this -> alertsource $source;
            
            switch( 
    $this -> alertsource -> getProperty'activity' ) ) {
                case 
    'barking':
                    
    $this -> handleDog();
            }
        }
        
        protected function 
    handleDog () {
            if ( 
    $this -> alertsource -> getProperty'master' ) == $this -> name ) {
                
    $this -> activity 'feeding'
            } else {
                
    $this -> activity 'chasing';
            };
            
            
    call_user_func( [ $this -> alertsource$this -> dogResponse$this -> activity ] ] );        
        }
    }


    class 
    Dog {
        
        use 
    Base;
        
        protected 
    $name;
        protected 
    $master;
        protected 
    $activity 'idle';
        
        protected 
    $dogMaster = [
          
    'Spot' => 'John',
          
    'Rex'  => 'Bob'
        
    ];
        
        public function 
    __construct $name ) {
            
    $this -> name $name;
            
    $this -> master $this -> dogMaster$this -> name ];
        }
        
        public function 
    bark() {
            
    $this -> activity 'barking';
        }
        
        public function 
    eat() {       
            
    $this -> activity 'eating';
        }
        
        public function 
    run() {
            
    $this -> activity 'running';
        }
    }


    // A short story
    echo '<h1>World events</h1>';

    // Once upon a time on Earth.
    $earth = new World'Earth' );

    // Something was happening.
    echo '<hr>';
    echo 
    '<h2>Event #1</h2>';

    // A dog named Spot was barking at John's house.
    // John, like a good master, feeds Spot.
    // Spot is eating now.
    $spot = new Dog'Spot' );
    $spot -> bark();

    $john = new Man'John' );
    $john_house = new Location'house'$john );

    $spot_barking = new Sound$spot$john_house );
    $earth -> event$spot_barking );

    // Another thing happen then.
    echo '<hr>';
    echo 
    '<h2>Event #2</h2>';

    // A dog named Rex sees Spot eating and barks at John's house too.
    // John is not Rex's master. He's chasing Rex away.
    $rex = new Dog'Rex' );
    $rex -> bark();

    $rex_barking = new Sound$rex$john_house );
    $earth -> event$rex_barking );

    // Rex runs to his master's house, Bob, and barks.
    // Bob is also a good master. He feeds Rex.
    // Rex is eating too now.
    echo '<hr>';
    echo 
    '<h2>Event #3</h2>';
    $bob = new Man'Bob' );
    $bob_house = new Location'house'$bob );

    $rex_barking -> changeLocation$bob_house );
    $rex -> bark();
    $earth -> event$rex_barking );

    // The End.
    echo '<hr>';

    ?>
    You'll need PHP 5.4 for it. I've added a trait, just for fun, and I've used shorthand for arrays. You can change the Base trait to Base class, extend the classes, remove use and replace the shorthand for arrays with full 5.3 declaration.


    <hr>


    The base of the story is this: all objects are brought back together in a world. A sound is happening at a location, but it can change its location. A man responds to an event by identifying the source and taking appropriate action. A source (dog) will react to the action of the man.

    The parallel would be web requests. The web server is a world. A sound is a request by a user (a dog). A man is the app delegated to handle the request and to send back a response to the user.


    <hr>


    The result is something like this:
    Code:
    World events
    
    Event #1
    Spot is barking at John's house.
    John is feeding Spot. Spot is eating.
    
    Event #2
    Rex is barking at John's house.
    John is chasing Rex. Rex is running.
    
    Event #3
    Rex is barking at Bob's house.
    Bob is feeding Rex. Rex is eating.
    Feel free to ask a question or dismantle the model. I won't mind, I promise.


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
  •