I'm currently working on an oophp application. I have a site class which will contain all of the configuration settings for the app. Originally, I was going to use the singleton pattern to allow each object to reference a single instance of the site object, however mainly due to testing issues involved in this pattern, I've decided to try a different approach.
I would like to make the site class the main parent class in my app and call it's constructor from within the constructors of the child classes, in order to make all the properties available whenever needed.
When run for the first time, the class will only contain the db details for the app. To get the remaining values a query must be performed using the db details. However, any subsequent instances will be clones of the original (with all values). I may also set a Boolean flag to perform the query again a completely new instance is required.
Would this be a viable alternative to the singleton and would it solve the testing issues it causes? This is all theory atm, I haven't started to code anything yet,
Any thoughts or advice greatly appreciated.
Thanks.
I think a better way is to have an 'configuration' object that will get passed to the constructors of all your other classes. So, almost something like a singleton, except it's explicitly created and passed only to classes that need it. This approach is usually called dependency injection.
After trying many different techniques, what I have found functional and reliable is this method:
Use a bootstrap, or initialization file. It is located in the ROOT of the site with the proper permission and safe-guards against direct access.
All pages in the site first include this file. Within it, I create all my global objects (settings, user), and reference them from there.
For example:
// OBJECT CREATION
$Config = new Configuration();
$User = new User();
Then within classes that require these objects:
public function __construct($id = NULL) {
global $Config; // DEPENDENCY INJECTION SOUNDS LIKE AN ADDICTION!
if($Config->allow_something) {
$this->can_do_something = true;
}
if(NULL !== $id) {
$this->load_record($id);
}
}
Notice that I just access these global objects from within the class, and how I don't have to include the object variables as the first constructor parameter each and every time. That gets old.
Also, having a static Database class has been very helpful. There are no objects I have to worry about passing, I can just call $row = DB::select_row($sql_statement);; check out the PhpConsole class.
UPDATE
Thanks for the upvote, whoever did that. It has called attention to the fact that my answer is not something I am proud of. While it might help the OP accomplish what they wanted, it is NOT a good practice.
Passing objects to new object constructors is a good practice (dependency injection), and while "inconvenient," as with other things in life, the extra effort is worth it.
The only redeeming part of my answer is use of the facade pattern (eg. DB::select_row()). This is not necessarily a singleton (something the OP wanted to avoid), and gives you an opportunity to present a slimmed down interface.
Laravel is a modern PHP framework that uses dependency injection and facades, among other proven design patterns. I suggest that any novice developer review these and other such design practices thoroughly.
Related
In my example I'm using the PHP framework Yii2 but I think this applies to most OO languages.
I have an ActiveRecord base class which most of my business objects extend from e.g. Project.
At the moment if I want a Project instance I call
Project::findOne(['id' => $id]);
findOne is a static method of ActiveRecord (which is part of the Yii2 framework). So this is bad form because I can't easily mock/stub the return of this call when writing unit tests.
But what's the best way to get around this?
I could create a class CActiveRecord that inherits from ActiveRecord and wrap the static call in a non-static call and use that everywhere - but then I would have to instantiate a throw-away Project object in order to get the actual instance. What if the Project object needed some heavy config to be instantiated - I would be passing random nonsense into the constructor just to get an instance.
Summary:
Simply changing statics to non-statics seems wrong - shouldn't I also move the functions somewhere else? If so, where?
The issue with static calls is the hard coupling to a specific other piece of code. Just wrapping that in a "dynamic" call doesn't make this any better:
$c = new CProject;
$c->findOne(); // Calls Project::findOne()
That's pretty darn pointless. The issue is not the syntax of -> vs. ::, the issue is that this particular code references a specific other class and that you cannot easily exchange this class for something else. You're building rigid, hardcoded dependencies between your classes/objects, which makes it hard to take them apart, which makes your code hard to test, and which makes it harder to adapt code to different situations.
The alternative is dependency injection:
function foo(Project $project) {
$p = $project->findOne();
}
This function is not coupled to any one specific Project class, but to a class which simply offers an interface akin to Project. In fact, Project could even be simply an interface. Which specific class and method is getting called here then is decided somewhere completely different, like your dependency injection container; or simply the caller of this code.
This makes it a lot easier to take this code apart and put it back together in different ways, as necessary for the situation at hand. That's not to say it can't work and that you should never use static calls at all, but you really need to be aware of what cross-dependencies you're establishing with every hardcoded class name, and whether that may or may not cause a problem down the line. For even moderately complex and/or growing software projects, it will almost certainly cause friction in some form or another eventually.
See How Not To Kill Your Testability Using Statics for a longer in-depth article.
I see advise from a lot of people teach not to use global variable/singleton/static class and move to use of a iOC container, for example, in PHP larvel framework, it is
App::bind('foo', function($app)
{
return new FooBar;
});
$value = App::make('foo');
instead of
$value = new FooBar;
But to me, the App::bind itself is a static method and cannot be replaced easily.
So, can I say, the iOC (at least in PHP), is just remove the number of hard coded variable and minimized to one, which is the service locator, and it cannot be further reduced, right?
App::bind is not a static method, this is it's signature:
public function bind($abstract, $concrete = null, $shared = false)
(found in /vendor/laravel/framework/src/Illuminate/Container/Container.php)
Laravel uses Facades, which, while they look like they are calling a method statically, actually instantiate an object under the hood and then call an instance method on that object. While Laravel does use some static methods in it's models, the App object itself is actually a facade. You can see a list of the built in facades if you look in /vendor/laravel/framework/src/Illuminate/Support/Facades/.
So, can I say, the iOC (at least in PHP), is just remove the number of hard coded variable and minimized to one, which is the service locator, and it cannot be further reduced, right?
You are seeing this correctly, but you can actually reduce the number of hard coded variable to 0.
The problem here is not App::bind() because it's configuration. Configuration has to be coupled to some kind of system because that's where you set all the details. That's OK here.
But having App::make() all over your codebase is the problem. You want to write reusable code. You don't want your model to be coupled to Laravel for example. The fact of calling the container is called the service locator pattern (because you locate services with the IoC).
This is an anti-pattern, because, as I've said, you are coupling your code to the container.
On the other hand, there is the dependency injection pattern which is better. Dependencies are injected in your classes, but you don't care how. This is just pure PHP, completely decoupled from any container.
I invite you to read stuff on the subject, Laravel can actually be used with full dependency injection (no static calls to Facades). Here is an article on the subject: Using Dependency Injection and IoC in Laravel 4 controllers
Howard, I think the context you might be missing is why people say
global variable/singleton/static class
are "bad". The reasons you don't want global variables in your application is, relying on global state is going to lead to pain. When you're modifying values that other parts of the program also have access to, it's likely two parts of a program are going to access that same variable and unexpected "bad" things will happen. Singletons and static classes are often lumped in with global state, because they're globally available things.
So yes, your statment
is just remove the number of hard coded variable and minimized to one, which is the service locator, and it cannot be further reduced, right
is accurate, but more than that a service container (if services are being created correctly) gives you global access to a thing-to-do-a-job, but is makes it hard/impossible to use that global thing-that-does-a-job to store global application state.
Why should I use Zend_Registry instead of the Singleton pattern?
My coworker and me recently had a discussion about this. His point was that we should use Zend_Registry for all consistent objects, but I wanted to use the singleton pattern, since Zend_Registry just does the same, but wrapped.
I have a problem with code like this:
$list = Zend_Registry::get('database')->getList($sql);
Since theres a chance that database isn't in Zend_Registry. In cases of lazy loading, I would have to make my own registry with information about specific objects in my system. Like if the database takes specific parameters on loadtime, then it would have to know this.
I would instead use getInstance and then all the code would reside in the same object. Does that make sense?
Even though you phrased your question as an either/or, might I suggest a third alternative?
I try to avoid both singletons and Zend_Registry wherever possible, since they function, in effect, as globals. When a segment of code can reach into the global ether - via a call to a singleton or a global registry - to get something it needs, it creates a hidden - or at least, a non-explicit - dependency that makes things harder to debug and unit-test.
In contrast, I try to follow dependency injection advice, paraphrased as: "Give a component what it needs. Don't make it find what it needs."
I find that for most entities for which I might feel I need a registry/singleton - db connections, loggers, etc - I can create them at Bootstrap, store them in the Bootstrap registry and inject them into my controllers, usually during init() using $this->getInvokeArg('bootstrap')->getResource('myResource'). Only controllers reach back into the Bootstrap. Then, any models or services that need these dependencies get them passed-in explicitly by the controller, either via constructor or by setter injection.
A hybrid approach to which I do sometimes fall back is to design my service/model classes with getters/setters for these dependencies - getDbAdapter() and setDbAdapter(); getLogger() and setLogger(), etc. The getter lazy-loads from the global registry - whether some singleton or by Zend_Registry, throwing exceptions when they are not where I expect them to be. In that sense, it is similar to what you are suggesting. It does violate the purist dependency injection philosophy. But at least the presence of the getter/setter methods explicitly demonstrates that there is a dependency and allows me to mock it out or to provide non-default implementations.
It does for simple blog or something. Otherwise you're stuck with only one DB instance. And that's NOT what you want in the long run. You may want to connect to other server (to log errors to central db, to import products from someone, ...) or connect as different user (for security reasons - you don't want your API to have access to admin_users table, but you still need to connect to it to check if user is valid in the first place).
You can do one-purpose registers (My_Db_Admin, My_Db_ReadOnly, ...) but that does not make much sense to me. Using registry you're not stuck with one instance. You can create one outside registry and work with it for a while and then trash it ;)
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Who needs singletons?
i was wondering, what are the drawbacks using Singletons in php scripts. I use them alot and i sometimes can't understand criticism of developers. Some examples:
I have a Request class:
Sanitizing POST, GET, COOKIE inputdata and using it instead of the global arrays - strictly and globally. Like
$request = Request::getInstance();
$firstname = $request->post('firstname', $additionalFilters);
There is always only ONE request per request. Why is using singleton in this case a bad idea?
Same for $_SESSION:
I have a Session class (Singleton) which does represent the $_SESSION array because there is only one session and i use it globally.
Database
$mysql = DB::getInstance('mysql', 'dbname'); //pseudo
$sqlite = DB::getInstance('sqlite', 'dbname'); //pseudo
For each type of database, i want only ONE object and never MORE. In my opinion there is otherwise a risk of chaos.
Unique rows
Also i often use classes to represent/use a unique row of a db table.
$article = Article::getInstance($id);
$navigation = Navigation::getInstance($id);
I see only benefits doing it this way. I never want a second object representing a unique row. Why is singleton such a bad idea here?
In fact, most (nearly all) my classes don't have a public constructor but always a static method like getInstance($id) or create() so the class itself handles the possible instances (which doesn't mean they are all singletons by definition)
So my question is: Are there any drawbacks i didn't realize yet. And which concrete scenario's the singleton-doubters thinking of when advise against Singletons.
Edit:
Now, you got a singleton that wraps around the $_POST, but what if you
don't have $_POST, but want to use a file for input instead? In that
case, it would be more convenient if you have an abstract input class,
and instantiate a POSTInput to manage input through posted data.
Ok, valid advantages. I didn't realized that. Especially the point regarding the Request class.
Still i have doubts whether that approach. Assume i have a "Functionality" class which executes a concrete request (like a guestbook component).
Within that class i want to get a sent parameter. So i get my singleton instance of Request
$req = Request::getInstance();
$message = $req->post('message');
This way, only my functionality object cares about a Request class.
When i use the non-singleton approach, i need somehow an additional class/function to manage that every request gets a valid request object. That way my Functionality class doesn't need to know about that managing class but in my opinion there still arises a dependence/problem: Everytime i create an instace of an Functionality object there is a chance that i forget to set a request object.
Surely i can define a non-optional parameter when creating a functionality. But that leads to a parameter overkill altogether at some time. Or not?
Singletons (and static classes, to which the same story largely applies) are not bad per se, but they introduce dependencies that you may not want.
Now, you got a singleton that wraps around the $_POST, but what if you don't have $_POST, but want to use a file for input instead? In that case, it would be more convenient if you have an abstract input class, and instantiate a POSTInput to manage input through posted data.
If you want to get input from a file, or even (for whatever reason) want to mimic (or replay) multiple requests based on input from a database table, you can still do this, without altering any code, except the part that instantiates the class.
Same applies to other classes too. You don't want your whole application to talk to this MySQL singleton.. What if you need to connect to two MySQL databases? What if you need to switch to WhatEverSQL?.. Make abstracts for these kinds of classes, and override them to implement specific technologies.
I do not think singletons should have as bad press they do in a request-based architecture such as PHP or ASP.NET (or whatever you want). Essentially, in a regular program the life-time of that singleton can be as many months or years as the program is running:
int main()
{
while(dont_exit)
{
// do stuff
Singleton& mySingleton = Singleton::getInstance();
// use it
}
return 0;
}
Apart from being little more than a global variable, it is very hard to replace that singleton with, perhaps, a singleton that might be useful in unit-testing. The amount of code that could depend on it, in potentially hundreds of source files tightly couples the use of that singleton to the entire program.
That said, in the case of request-based scenarios such as your PHP page, or an ASP.NET page, all your callable code is effectively wrapped in a function call anyway. Again, they are obfuscating a global variable (but within the context of the request) with safe-guards against being created more than once.
But still, I advocate against their use. Why? Because even in the context of your single request, everything is reliant and tightly coupled to that instance. What happens when you want to test a different scenario with a different request object? Assuming you coded using includes, you now have to go and modify every single instance of that call. If you had passed a reference to a pre-constructed Request class, you can now do cool stuff, such as provide mock unit-testing version of your class, by simply changing what gets passed down to the other functions. You've also de-coupled everything from using this universal Request object.
In a theoretical database access class, I found that there are quite a few helper functions that I use in the class, which have nothing to do the class's instance (and others, that could be manipulated to be unrelated to the class's instance using dependency injection).
For example, I have a function that gets a string between two other strings in a variable. I've been thinking of moving that to a String_Helper class, or something of the sort. This function has already been made static.
Also, I have a function that queries a database, query($sql). The connection details are provided by the instance, but I've been considering making it static, and using query($sql, $connection). Developers would then be able to call it statically and not need to instantiate the database class at all.
For me, the questions are:
Is it worth it to do something like this? Functions like the query function make me wonder if this is not just me trying to make everything as static as possible, without any real need to. Under what circumstances would you consider this useful?
I know static functions are harder to test, but if I make sure that their code is completely dependency free (or uses dependency injection where necessary), then they're just as easy to test as everything else, surely?
It isn't a concern at the moment, but if, in the future, I decided to extend the classes with the static functions, it would be impossible for me to make the current code use my extended functions. I've thought of Singletons, but the same problem arises: the code would be calling Singleton_Class::getInstance(), and not My_Extended_Singleton_Class::getInstance(). Dependency Injection seems to be the only way to solve this issue, but it might lead to a clunkier API, as every dependency has to be given to an object on __construct().
I have a container class, which holds certain pieces of information statically so that they can be accessed anywhere in the script (global scope). If I can't use static functions or singletons, a class that contained instances of different variables would be great. One could use for example Container::$objects['MyClass'] = $MyClass_object;, and then the rest of the code could just access Container::$objects['MyClass']. If I extended the MyClass class, I could use Container::$objects['MyClass'] = $MyExtendedClass_object;, and the code that used Container::$objects['MyClass'] would use MyExtendedClass, rather than MyClass. This is by far the best way to do it, in my opinion, but I'd like to know what you think about it.
Ok, let me answer these one by one...
1. Is it worth doing something like this
Yes and no. Splitting out the helper functions into their own classes is a good idea. It keeps the "scope" of each of the classes rigidly defined, and you don't get creap. However, don't make a method static just because you can. The query method is there to make your life easier by managing the connection, so why would you want to lose that benefit?
2. They are harder to test
They are not harder to test. Static methods that depend on state are harder to test (that access static member variables or global variables). But static methods in general are just as easy to test as instance methods (in fact, they can be easier since you don't need to worry about instantiation).
3. Extending the classes
This is a valid concern. If you put String_Helper::foo() in the class itself, you'll run into issues. But an option would be to set the name of the string helper as a class variable. So you could then do {$this->stringHelper}::foo() (note, PHP 5.3 only). That way to override the class, all you need to do is change the string helper class in that instance. The Lithium framework does this a lot...
4. Global Registry
I would stay away from this. You're basically just making every class a singleton without enforcing it. Testing will be a nightmare since you're now dependent on global scope. Instead, I'd create a registry object and pass it to classes via the constructor (Dependency Injection). You still accomplish the same thing since you have a store for the objects/classes, but you're no longer dependent on a global scope. This makes testing much easier.
In general
When you're looking at doing things like this, I like to stop when I hit questions like this. Stop and sit down and think *What actual problem am I trying to solve?". Enumerate the problem explicitly. Then pull our your supposed solutions and see if they actually solve them. If they do, then think about the future and if those solutions are really maintainable in the long run (Both from a bug fix standpoint, and with respect to feature additions). Only if you're happy with both of those answers should you even consider doing it. Oh, and also remember to keep it simple. Programming is not about making the most complex, most clever or most amazing solution. It's about making the simplest solution that solves the problem...
I hope that helps...
Good Luck!