SitePoint Sponsor

User Tag List

Page 1 of 3 123 LastLast
Results 1 to 25 of 75
  1. #1
    SitePoint Enthusiast
    Join Date
    Mar 2006
    Posts
    81
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    configuration: constants vs singleton pattern

    I am trying to setup a way to configure my application and I have read various solutions. Seems as though most people prefer to use a singleton class to do this. However, I was also looking at using constants. What would be the pros and cons of each method?

  2. #2
    SitePoint Zealot shaman's Avatar
    Join Date
    Feb 2005
    Location
    W.R. Home
    Posts
    112
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you application is OO, I'd prefer Singleton and same one, if not constants,
    by the way there's third way, the static variables
    She's my german fraulein

  3. #3
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Singletons are generaly "evil", as it's just another type of globals - and the need for globals usualy means there's something wrong/going wrong in the code. If you have the need for some type of registry or configuration either use a Service Locator or Dependency Injection(some would say it's overkill for php) - or a standard registry object.

    If I should be realy honest I've never, ever, had an problems that required a singleton.

  4. #4
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    United Kingdom
    Posts
    208
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I guess the question is what needs to be configured? If you are just setting database connection strings and so forth I'd say constants are the easiest and cleanest approach. If your application needs more complex structures then a registry would be ideal.

  5. #5
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Shrike
    I guess the question is what needs to be configured? If you are just setting database connection strings and so forth I'd say constants are the easiest and cleanest approach.
    I'd argue that constants are among the worst configuration because:

    1. If you use global constants with define() they (can) clash in the global namespace
    2. If you define constants in your class it requires editing of your class files every time you / your users wanna change configuration.

    Sometimes a constant is in place, for example to set the base dir of your library, maybee in a profile/include-file that inits the library. I would however argue that a separate configuration object (not a singleton) is probably the best in most cases, something like:
    PHP Code:
    <?php
    class ClassConfig{
        protected 
    $path;
        
    setPath($path){
            
    $this->path = ( substr($path,-1) == DIRECTORY_SEPARATOR ) ? $path $path DIRECTORY_SEPARATOR ;
        }
    }
    ?>
    Because it lets you (as in the example above) encapsulate configuration logic(such as tidying up paths adding / or \ on the end if it's missing, etc.) in one place. Then just use the config object somewhat like this:

    PHP Code:
    <?php
    $cfg 
    = new ClassConfig;
    $cfg->setPath("./home/thr"); /* and the path will be fixed as we make sure it is in the setPath() method. */
    $realClass = new RealClass($cfg);
    ?>

  6. #6
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    United Kingdom
    Posts
    208
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think your first point is moot if you are at least a little careful with naming convention. I wouldn't use class constants for things not directly related to that class either.

    I do use global constants for defining the library path, document root and so forth, I still claim it's alot easier and cleaner than your approach. Swings and roundabouts

  7. #7
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Shrike
    II do use global constants for defining the library path, document root and so forth
    I'll quote myself: "Sometimes a constant is in place, for example to set the base dir of your library".

    So how do you do with paths? do you parse them each time you use them or do you "force" yourself to always append / or \ ?. And I think you completely missed the fact that a configuration class encapsulates your config and all it's related logic - which is a good thing, why spread it out all over the place?

  8. #8
    SitePoint Addict
    Join Date
    Apr 2004
    Location
    Melbourne
    Posts
    362
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    Singletons are generaly "evil", as it's just another type of globals - and the need for globals usualy means there's something wrong/going wrong in the code. If you have the need for some type of registry or configuration either use a Service Locator or Dependency Injection(some would say it's overkill for php) - or a standard registry object.

    If I should be realy honest I've never, ever, had an problems that required a singleton.
    How is a registry not just a collection of singletons, therefore a collection of evil, and therefore most likely the next target of Dubya? (I know, because you can change which object is at the hash, I just wanted that collection of evil thing out there, you know? ).

    I do agree that in a general sense, singletons can have the same problems as using global objects. However, I do see that they have their place (being that they prevent the creation of the object through external allocation), so I'm not quite willing to stick them on the scrapheap. I will agree though that if your (php) application is using more than one or two singletons, you might want to refactor and really figure out what you're wanting to achieve.

  9. #9
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Tanus
    How is a registry not just a collection of singletons, therefore a collection of evil, and therefore most likely the next target of Dubya? (I know, because you can change which object is at the hash, I just wanted that collection of evil thing out there, you know? ).
    Well hehe.. when I read the first sentance I wanted to reply what you put in the ( ), ah well

    Quote Originally Posted by Tanus
    I do agree that in a general sense, singletons can have the same problems as using global objects. However, I do see that they have their place (being that they prevent the creation of the object through external allocation), so I'm not quite willing to stick them on the scrapheap. I will agree though that if your (php) application is using more than one or two singletons, you might want to refactor and really figure out what you're wanting to achieve.
    I'd say you'll in 99% of the cases won't need singletons and at most times it's a sign of bad design from the coder. If you need something(namely an object) in many different places in your code either(or refactor it, as if you have a "super" object needed in many places it's often a sign of bad design):

    1. Stick it in a easy to get registry
    2. Put it in a "Context" object which you pass around(only realy worth doing if you have more then one object that needs to be at many places)
    3. Pass it as an argument to the objects that need it

    If you have a singleton, you "might" aswell just do:

    $obj = new Object

    function something(){
    global $obj;
    }

    As it's the same thing(almost ;p I know I'm pushing it to it's extreme here). If you're afraid that you might instance multiple objects when you don't want to stick it in a Registry/Service Locator/Dependency Injector

  10. #10
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    United Kingdom
    Posts
    208
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    I'll quote myself: "Sometimes a constant is in place, for example to set the base dir of your library".

    So how do you do with paths? do you parse them each time you use them or do you "force" yourself to always append / or \ ?. And I think you completely missed the fact that a configuration class encapsulates your config and all it's related logic - which is a good thing, why spread it out all over the place?
    Ah sorry I missed the first bit...going back to my original post I said the same thing - constants for something simple, class for something more complex. I have a definitions file for constants, certainly littering the codebase with them would be a very bad thing. A class might encapsulate things nicely but you are presented with more complexities such as visibility of the config object. If you already have a service locator / registry type object then it could be added there.

    For filepath...well I use absolute paths anyway. I don't see the need to parse filepaths, PHP does that for me.

  11. #11
    SitePoint Addict
    Join Date
    Apr 2004
    Location
    Melbourne
    Posts
    362
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr

    As it's the same thing(almost ;p I know I'm pushing it to it's extreme here). If you're afraid that you might instance multiple objects when you don't want to stick it in a Registry/Service Locator/Dependency Injector
    In instances where there should be only one instance of an object (okay, I could have brought Christopher Lambert into it there but I didn't ), and you don't want to have any chance that there could be another instance of it, the singleton is needed. Prado's "application" object is one such case (though, I'll admit that in v2 it is used for too many things).

    I'm familiar with the patterns you're talking about, but which of them guarantees that there'll only ever be a single instance of the object that the pattern manages?

  12. #12
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Shrike
    For filepath...well I use absolute paths anyway. I don't see the need to parse filepaths, PHP does that for me.
    Well, take this code:
    PHP Code:
    $path "/home/thr"
    if I try to include a file by doing:
    PHP Code:
     include $path 'file.php' 
    I'll get an include error saying that the file /home/thrfile.php could not be found. What I ment was that "fixing" paths is adding the trailing \ or / if it's missing, etc. Ofc. you can require that you hardcode the ending slash or append it to all paths before using them, but it's cumbersome and is prone to human error.

    The path was just an example, there are other cases where you need to make sure all your configuration directives are correct and encapsulating that behaviour in one class is well.. good

    Quote Originally Posted by Tanus
    I'm familiar with the patterns you're talking about, but which of them guarantees that there'll only ever be a single instance of the object that the pattern manages?
    As long as you only use the Registr/SL/DI for getting your objects - of them does.

  13. #13
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm quite likely using DI atm, means I can read a config, which just registers implementations with a DI container. The rest of the application is completely unware of the various configuration options there are, it just asks the DI container for an object, when it needs it.

  14. #14
    SitePoint Addict
    Join Date
    Jan 2005
    Location
    United Kingdom
    Posts
    208
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    Well, take this code:
    PHP Code:
    $path "/home/thr"
    if I try to include a file by doing:
    PHP Code:
     include $path 'file.php' 
    I'll get an include error saying that the file /home/thrfile.php could not be found. What I ment was that "fixing" paths is adding the trailing \ or / if it's missing, etc. Ofc. you can require that you hardcode the ending slash or append it to all paths before using them, but it's cumbersome and is prone to human error.

    The path was just an example, there are other cases where you need to make sure all your configuration directives are correct and encapsulating that behaviour in one class is well.. good

    As long as you only use the Registr/SL/DI for getting your objects - of them does.
    What I meant was that if a path is wrong, PHP tells me about it, I'd also say trying to preempt human mistakes can be a bad thing too.

    I do agree with you though. Given sufficient complexity an object would be justified, and as Ren points out Dependency Injection solves having to pass your object to where it's needed, at least I think that's what it does

  15. #15
    Non-Member Gator99's Avatar
    Join Date
    Sep 2004
    Location
    Florida
    Posts
    613
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    PHP Code:
    <?php
    $cfg 
    = new ClassConfig;
    $cfg->setPath("./home/thr"); /* and the path will be fixed as we make sure it is in the setPath() method. */
    $realClass = new RealClass($cfg);
    ?>
    I would prefer this method since it encapsulates your config data. If you have quite a bit of configuaration data, you can segragate it by config type to avoid passing the entire object to a certain class:
    PHP Code:
    //in the config class
    var $db_cfg=array("db_name => mydb","db_user => me","db_pass => password","db_socket => localhost");
    //in your main class
    $cfg = new ClassConfig;
    // call the class by passing a reference to the database configuration
    $db=new database($cfg->db_cfg);
    // in php 4 you have to specify you want a reference
    class database{
    function 
    database(&$cfg){
    //$cfg is a reference to $cfg->db_cfg
    }


  16. #16
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Gator99: I'd never do it the way you suggested, basicly your way requries editing of the class source everytime configuration changes, a nightmare.

    Yes you could easil add a method such as:
    ClassConfig::getDbCfg()
    As I'd never use a public property, ever ;P

  17. #17
    Non-Member Gator99's Avatar
    Join Date
    Sep 2004
    Location
    Florida
    Posts
    613
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    Gator99: I'd never do it the way you suggested, basicly your way requries editing of the class source everytime configuration changes, a nightmare.

    Yes you could easil add a method such as:
    ClassConfig::getDbCfg()
    As I'd never use a public property, ever ;P
    You're going to have to edit something every time the configuration changes. Although my example was for illustration purposes, editing the source of config class would be about as much effort as editing whatever form of text,db or file you'd want to store your configuration data in. You're probably right about accessing the data, it's more OO politically correct to use a function like getDbCfg(){return $this->db_cfg;}

  18. #18
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Gator99
    You're going to have to edit something every time the configuration changes. Although my example was for illustration purposes, editing the source of config class would be about as much effort as editing whatever form of text,db or file you'd want to store your configuration data in.
    Except for the fact that with your approach I can only have one configuration running, what if I want to connect to two different databse? Do i have to extend the configclass and overwrite the varaible? Putting configuration in classes protected properties(atleast they should be, stupid php4 ;p) is not something I'd recommend.
    Last edited by thr; Mar 10, 2006 at 09:00.

  19. #19
    Non-Member Gator99's Avatar
    Join Date
    Sep 2004
    Location
    Florida
    Posts
    613
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Talking

    Quote Originally Posted by thr
    Except for the fact that with your approach I can only have one configuration running, what if I want to connect to two different databse? Do i have to extend the configclass and overwrite the varaible? Putting configuration in classes protected(they should be here, stupid php4 ;p) is not something I'd recommend.
    You mean you would actually want to reuse this class Hard coding config variables in the fabled config class object would be pretty ignorant, almost like using simpletons, I mean singletons.

  20. #20
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Gator99
    You mean you would actually want to reuse this class Hard coding config variables in the fabled config class object would be pretty ignorant, almost like using simpletons, I mean singletons.
    What are you talking about? ofc. I might need two different database configurations during runtime? Should I use two different config classes then, sound very sub-optimal.

  21. #21
    Non-Member Gator99's Avatar
    Join Date
    Sep 2004
    Location
    Florida
    Posts
    613
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    What are you talking about? ofc. I might need two different database configurations during runtime? Should I use two different config classes then, sound very sub-optimal.
    I'm talking about reusing a config class. Not sure why you'd have to create another instance of your fabled config class to maintain two database connections. All you would do is specify which "configuration" to load, eg $cfg->get_db_cfg("db1") or $cfg->get_db_cfg("db2"), not really rocket science.

  22. #22
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sigh.. I give up.

  23. #23
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > Not sure why you'd have to create another instance of your fabled config class to maintain two
    > database connections.

    You could just create the one instance, and leave it to a Factory to share the configuration, so for example, it would be the Factory that'd return the configuration required based on the user making the request to connect to the database...

    Or the application for that matter, making the request for a specific configuration to make that connection, but regardless this responsibility isn't actually part of the configuration anyways; It needs to be encapsulated, and within any kind of configuration either

  24. #24
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    and the need for globals usualy means there's something wrong/going wrong in the code.
    I know you are just spouting off the status quo, but you might want to think a bit more about statements like that when it comes to web applications, because effectively what you are saying is that all web applications, and indeed the web itself is inherently "wrong" in some way... No GET data, no POST data, no Cookie data, no Server data, no Session data, etc = No web applications and arguably no web either.

    I'm not saying you should go around filling your code up with custom globals, but maybe just you shouldn't be so quick to over-generalize about something that makes possible what we do every day.


    How I do application configs/settings is to translate the data into a read only data object(s) and stick that into the Object Registry, which is just a standard run of the mill registry. The data source is usually INI style, but can also be XML (or from a database if you really wanted).

  25. #25
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape
    I know you are just spouting off the status quo, but you might want to think a bit more about statements like that when it comes to web applications, because effectively what you are saying is that all web applications, and indeed the web itself is inherently "wrong" in some way... No GET data, no POST data, no Cookie data, no Server data, no Session data, etc = No web applications and arguably no web either.
    I hope you know I didn't mean GET, etc. And for your knowledge all my _GET, _POST, _SESSION and _COOKIE, etc. data is wrapped in a nice object and then unset.

    That is input data which is set as globals by the language, that has nothing to do with the code you write yourself. Argueing like you the argv / args in Java/C++ is "global data" also, sigh.


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
  •