SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 27
  1. #1
    Non-Member melancholic's Avatar
    Join Date
    Nov 2004
    Location
    Australia
    Posts
    447
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    When does one use Static Methods/Variables/Classes?

    Hi everyone,

    With static variables/methods being one of the big punches in Singleton Pattern bashing, I'm paranoid of using them.

    I've been running thoughts through my recent widget implementation. I've bounced from one idea to another.

    Here's what I've implemented:

    I have a Widget interface which specifies that it's users need to implement a paint method and expect a Widget_Config object. The paint method reads the Widget_Config object and returns rendered HTML.

    A widget factory/decorator with one method called "draw()"
    This class takes a widget configuration object and a widget name as a parameter.

    The draw method dynamically determines the widget required and instantiates the Widget Object.

    It then returns the invoked paint() method which expects the widget configuration object.

    The Widget Factory/decorator class is bound to the View object as a helper.

    I also had a look at giving the widget a static paint() method. Which was disregarded shortly after as I found that I needed to dynamically determine some things in the paint method for the Form_Element widget in run time.

    I also had a look at creating the Widget Factory as a static class.
    Which did not seem so bad, more on the same level really. Does it come down to preference or is there one big rule or reason that determines for and against static methods/classes?

    Would implementing the Widget Factory/Decorator with static methods be considered the "correct" thing to do?


    Thanks in advance,

  2. #2
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Believe me, you are not the only one wrestling with this issue:
    http://framework.zend.com/wiki/space...ZFMLGEN&id=954

    Regarding the decorator with a static method, this does seem a bit wrong to me. The capability to add a static method exists so you can have class methods, code which affects all instances of a class. The purpose of the Decorator pattern is to alter the behavior of a single instance of a class. You would seem to have a class at the purpose level.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  3. #3
    Non-Member melancholic's Avatar
    Join Date
    Nov 2004
    Location
    Australia
    Posts
    447
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Jason,

    The capability to add a static method exists so you can have class methods, code which affects all instances of a class.
    I've been so gunned up to tackle more advanced issues that I overlook the textbook definitions.

    I've not looked at the Zend Framework closely just yet, but well, why do you think they are using so many static calls? Is it to dumb it down by creating utility classes like Zend_Log?

    Had a squiz at the discussion you posted and as all discussions go, this one looks to be a stalemate.

    Regards,

  4. #4
    SitePoint Guru
    Join Date
    Nov 2003
    Location
    Huntsville AL
    Posts
    706
    Mentioned
    4 Post(s)
    Tagged
    1 Thread(s)
    I have been participating in the Zend discussion. My very humble opinion is that using a dynamic object should be the default design approach. So if you decide you need to be able to log things then it makes sense to create a log object.

    Having said that one can then start to examine specific use cases. An object such as a log can cut across many different classes and it may sometimes be a pain to provide a given method with direct access to the log object. So in these cases it might make sense to add a static method or two in order to simplify your code.
    Allowing
    Zend_Log::log('Some message');
    Instead of requiring
    $log->log('Some message');

    Keep the implementation dynamic and use static methods to simplify user operations.

  5. #5
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think Christopher and others have argued eloquently for the object oriented approach, but I am not sure it will win in the end. Their is a belief that Zend_Log::log('a message'); is the simplest route to go and it solves the majority of problems. It is my personal believe that one should hide object assebly in a factory, have that factory automatticaly inject a specific log object, and then do $this->logger->log('a message'); Your factory should keep the end use simple, but the injection will keep the hard coded Zend_Log dependancy out of your code, make it more testable, etc. It does not appear this will end up the recommended approach.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  6. #6
    Non-Member melancholic's Avatar
    Join Date
    Nov 2004
    Location
    Australia
    Posts
    447
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yah, from what I've read, Andi seems to have his mind set on making ZPF simple by default and leave optimisation to the more experienced users.

    I can see the point, I mean it's PHPs BnB - "easy to pick up".

    The implementation you've suggested would have taken me a few days of solid focus to digest if I saw it about a year ago. It would have scared me off.

    Seems that the ZFW is following this principle. Easy to pick up...


    Regards,

  7. #7
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    We had a pretty long discussion about this a while ago. IMO it comes down to a tradeoff between simplicity and flexibility; and given PHP's procedural roots and obsession with "The PHP way", it's not suprising they chose the former over the latter. Going for the full object oriented approach would either require the end user to do a lot of wiring themselves, or a pretty full featured Assembly/DI layer, which is stuff even experienced OO developers sometime have trouble getting their head around. The fact that the Zend Framework is designed as seperate components complicates the issue, as it's harder to abstract away object creation.

  8. #8
    SitePoint Zealot DerelictMan's Avatar
    Join Date
    Oct 2005
    Posts
    123
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    Believe me, you are not the only one wrestling with this issue:
    http://framework.zend.com/wiki/space...ZFMLGEN&id=954
    Wow. I find it hard to believe that those in that discussion who are arguing in favor of static methods calls have a true understanding and familiarity with unit testing. They may be familiar with it as a concept, but I don't think any of them have actually tried to put it into practice. Similarly, I don't believe they "get" polymorphism either. Or else they wouldn't argue (as one poster did) that there is no justification for creating an object instance when that object doesn't have any state. Objects without state can still be used as (polymorphic) callbacks (which I personally prefer over PHP's callback pseudo-type).

    I'm not saying all this to act or feel superior... I say this because I used to be the same way. It just takes experience to learn (the hard way) that static methods are more often than not a mistake, and it seems like most of the people involved in that conversation have not learned that yet. (As kyberfabrikken once said, they are "procedures in disguise".)

    From an outsider's perspective, it seems to me that most of the Zend guys (the ones making the decisions anyway) are C coders at heart and tend to think in a procedural way. I wonder if that would explain the tendency towards procedural programming (regardless of whether or not it is dressed up in OOP clothing).

    I have to admit that the OOP vs. procedural debates that are so prevalent in the PHP community is one of the things that annoys me the most about it. Say what you will of the flaws of platforms such as .NET or Java (of which there are no doubt many), but at least in those communities there is none of this time-wasting bickering about OOP vs. procedural. I sometimes wonder if this split-personality inherent in the platform is truly an advantage or not...

  9. #9
    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 DerelictMan
    Wow. I find it hard to believe that those in that discussion who are arguing in favor of static methods calls have a true understanding and familiarity with unit testing. They may be familiar with it as a concept, but I don't think any of them have actually tried to put it into practice. Similarly, I don't believe they "get" polymorphism either. Or else they wouldn't argue (as one poster did) that there is no justification for creating an object instance when that object doesn't have any state. Objects without state can still be used as (polymorphic) callbacks (which I personally prefer over PHP's callback pseudo-type).

    ..snip..
    Yes, I agree. But I think we (I'm jared williams on the mailinglist) are probably fighting a loosing battle

  10. #10
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DerelictMan
    I have to admit that the OOP vs. procedural debates that are so prevalent in the PHP community is one of the things that annoys me the most about it. Say what you will of the flaws of platforms such as .NET or Java (of which there are no doubt many), but at least in those communities there is none of this time-wasting bickering about OOP vs. procedural.

    There's no bickering because there aren't any procedural programmers using those languages But I'm sure there are other similar debates that rage on in those communities. I do recall a big debate during Java's development regarding wether primitives should be objects or not; there was a camp that succesfully argued that doing so would lead to massively increased resource usage, and now they're stuck with a bunch of hacks like autoboxing.

    Quote Originally Posted by DerelictMan
    I sometimes wonder if this split-personality inherent in the platform is truly an advantage or not...

    It depends for whom; I think it's quite clear that PHP's schizophrenia is a problem for OO purists, but then again PHP never claimed to be an OO language. In the end, just like PHP, the Zend Framework is being targeted at the greater mass of programmers, and the OO purists will be using other frameworks.

  11. #11
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Initially I was looking forward to Zend as a means to promote best practices in php but I quickly lost interest. As Andi describes it, it seems to be a "beginners" framework not test-driven, state-of-the art object oriented code. There's enough of that in php already: do we really need more? Rather than dumbing it down I'd prefer to see an effort to raise php programmers up. After all, OOP doesn't exist to make life harder: it's there to make things simpler. A good, widely-used framework might have been a focal point for budding programmers - if that's what everyone was using they'd be motivated to make the effort to learn it.

  12. #12
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    Initially I was looking forward to Zend as a means to promote best practices in php but I quickly lost interest. As Andi describes it, it seems to be a "beginners" framework not test-driven, state-of-the art object oriented code. There's enough of that in php already: do we really need more? Rather than dumbing it down I'd prefer to see an effort to raise php programmers up. After all, OOP doesn't exist to make life harder: it's there to make things simpler. A good, widely-used framework might have been a focal point for budding programmers - if that's what everyone was using they'd be motivated to make the effort to learn it.
    There you go then. That could be a project for sitepoint community members to all chip in for

  13. #13
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    Initially I was looking forward to Zend as a means to promote best practices in php but I quickly lost interest. As Andi describes it, it seems to be a "beginners" framework not test-driven, state-of-the art object oriented code. There's enough of that in php already: do we really need more? Rather than dumbing it down I'd prefer to see an effort to raise php programmers up. After all, OOP doesn't exist to make life harder: it's there to make things simpler. A good, widely-used framework might have been a focal point for budding programmers - if that's what everyone was using they'd be motivated to make the effort to learn it.
    Well, it depends on the level of the average php programmer; if it's low enough, even a dumbed down framework is a step up. So it may not be a means to promote best practices, but it will be a means to promote better practices, and that will help some move onto even better practices.

    In any case, even though there may be some questionable decisions, there may be some other excellent code in there, it's too soon to dismiss the entire thing.

  14. #14
    SitePoint Addict Clenard's Avatar
    Join Date
    Sep 2004
    Location
    USA
    Posts
    337
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by 33degrees
    Well, it depends on the level of the average php programmer; if it's low enough, even a dumbed down framework is a step up. So it may not be a means to promote best practices, but it will be a means to promote better practices, and that will help some move onto even better practices.

    In any case, even though there may be some questionable decisions, there may be some other excellent code in there, it's too soon to dismiss the entire thing.
    I agree. When I first started learning PHP - most OOP Frameworks scared the bejeezus out of me! Most were badly documented with no community to ask questions on, etc, etc. So, I stuck to "normal", procedural coding practices. I believe 33Degrees is right... as Zend does "introduce" best practices to more of a beginner-to-intermediate level of PHP Programmers.

    I think it's only the start of the Framework... I'm sure they'll build on, slowly but surely.

  15. #15
    SitePoint Addict Quaint's Avatar
    Join Date
    May 2004
    Location
    Netherlands
    Posts
    219
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Static methods aren't really that useful at all I'd say. What's the point in calling a method like: ClassName::Method(), and why not just instantiate the class into an object.. Really mostly when you use a static class it will contain some useful functions (which can't interact really, they are static right?) so you could probably name that class something in the likes of Tools. If your class does not fall into this category, just don't make it static I'd say?

    Quaint Tech
    - Blog on web development and web technology.

  16. #16
    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 d11wtq
    There you go then. That could be a project for sitepoint community members to all chip in for
    I don't remember you being terribly interested in education.

  17. #17
    SitePoint Wizard Dean C's Avatar
    Join Date
    Mar 2003
    Location
    England, UK
    Posts
    2,906
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Quaint
    Static methods aren't really that useful at all I'd say. What's the point in calling a method like: ClassName::Method(), and why not just instantiate the class into an object.. Really mostly when you use a static class it will contain some useful functions (which can't interact really, they are static right?) so you could probably name that class something in the likes of Tools. If your class does not fall into this category, just don't make it static I'd say?
    Maybe a class which holds library functions It really is an interesting discussion as I, myself, have been struggling to understand the correct usage of static methods but I finally grasped it when I read a quote saying that a method should be static if the object's state is irrelevant to the methods implementation.

    e.g.

    PHP Code:
    class foo
    {
    var 
    $bar;
    function 
    setBar($value) { $this->bar $value; }

    function 
    getBar()
    {
    if(
    $this->bar == 'lala') {
     echo 
    'foo'
    } else { 
    echo 
    'bar'
    }

    Now because the getBar method is dependant on the current state of the object it shouldn't be static. But I'm assuming that if we simply outputted the value of $bar in the getBar() method it should become static

    Am I on the right track?

  18. #18
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dean C
    Am I on the right track?
    Static Methods, also called Class Method are for implementing behaviors which affect all instances of a class, rather than just a single instance.

    PHP Code:
    class Item {
        protected static 
    $count=0;
        protected 
    $name;
        
        function 
    __construct($name) {
            
    $this->name $name;
            ++
    self::$count;
        }
        
        function 
    sayHello() {
            return 
    'Hello from '.$this->name;
        }
        
        static function 
    numItems() {
            return 
    self::$count;
        }
    }



    class 
    MiscTestCase extends UnitTestCase {

    function 
    testItem() {
        
    $bob = new Item('Bob');
        
        
    $this->assertEqual('Hello from Bob'$bob->sayHello());
        
    $this->assertEqual(1,$bob->numItems());
        
        
    $joe = new Item('Joe');
        
    $this->assertEqual('Hello from Joe'$joe->sayHello());
        
    $this->assertEqual(2,$joe->numItems());
    }

    What does not belong as a static class method is

    PHP Code:
    class Item {
      static function 
    lcase($str) {
        return 
    strtolower($str);
      }

    It just has no relation to the purpose of the Item class.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  19. #19
    SitePoint Wizard Dean C's Avatar
    Join Date
    Mar 2003
    Location
    England, UK
    Posts
    2,906
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What would happen if you rewrote "static function numItems() { " as "function numItems() { " ?

  20. #20
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dean C
    What would happen if you rewrote "static function numItems() { " as "function numItems() { " ?
    Absolutly nothing, due to php4 backwards compatability, since there was no static keyword in php4. Actually, the tests above should have read something like:

    PHP Code:
    $this->assertEqual(2Item::numItems()); 
    , I wrote the method as static but used the object to call it
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  21. #21
    Non-Member melancholic's Avatar
    Join Date
    Nov 2004
    Location
    Australia
    Posts
    447
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hello again,

    Just going over the thread... I reread this part and don't completely understand.

    ... It is my personal believe that one should hide object assebly in a factory, have that factory automatticaly inject a specific log object, and then do $this->logger->log('a message'); Your factory should keep the end use simple, but the injection will keep the hard coded Zend_Log dependancy out of your code, make it more testable, etc.
    Could you by any chance give a quick sample/demonstration as to how your factory implementation works and what problems it counters?

    Thank you in advance

    Regards,

  22. #22
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by melancholic
    Could you by any chance give a quick sample/demonstration as to how your factory implementation works and what problems it counters?
    Basically, usually when someone say the static call is "easier", they mean they don't want to instanciate and pass the object to the other objects it collaborates with. The problem is by coding the static call into your code, you create a point of inflexibility. The easiest way to understand this is through testing, though this is really just an early warning, the hard coupling is likely to bite you in the end through other interactions.

    You might have somthing like:

    PHP Code:
    class Model {
      function 
    doSomthing() {
        if (
    $errorLog::Log('something bad happened');
      }

    So how can you verify 'something bad happened' gets logged under an error condition?

    My solution would be to pass in a logging object and have code that does:

    PHP Code:
    class Model {
      protected 
    $log;
      function 
    __construct($log) {
        
    $this->log $log;
      }
      function 
    doSomthing() {
        if (
    $error$this->log->log('something bad happened');
      }

    To get arround the "so hard to instanciate and pass in the log object" argument, wrap the construction in a factory:

    PHP Code:
    function getModel() {
      return new 
    Model(Log::instance());

    HTH
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  23. #23
    Non-Member melancholic's Avatar
    Join Date
    Nov 2004
    Location
    Australia
    Posts
    447
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ahh alright...

    but how does that differ from the factory method:

    PHP Code:
    function getModel() {
      return new 
    Model(new Log());

    Is it because there is only ever going to be one instance of the Log object?

    Does this relates directly to:

    The capability to add a static method exists so you can have class methods, code which affects all instances of a class.
    In the sense that the Log class would have other collaborators?

  24. #24
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by melancholic
    Ahh alright...

    but how does that differ from the factory method:

    PHP Code:
    function getModel() {
      return new 
    Model(new Log());

    Is it because there is only ever going to be one instance of the Log object?

    Does this relates directly to:



    In the sense that the Log class would have other collaborators?
    It differes in a couple of ways. First, you don't have to use the factory, it is there for your conveniance (i.e. as the answer to creating the object is to hard, you have essentially replaced one static call with a different, but more flexible, one).

    The most obvious would be in testing:

    PHP Code:
    function testFailureIsLogged() {
      
    $log = new MockLog;
      
    $log->expectOnce('log''something bad happened');

      
    $model = new Model($log);
      
    $model->doSomething();

    Here you bypass the factory and are able to validate your logging assertions.

    Secondly, if you have a need to switch out the logger, now you have a centralized point in your code to do this inside of the factory.

    HTH
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  25. #25
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Umm...

    I understand the flexibility of the factory method (it's one of Fowlers refactors) but is there not a problem, from the point of view of the actual factory method it's self where you may want to select one logger from several?

    Do you have a solution/example where your faced with that situation


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
  •