I found myself in a situation where I'm not sure which way I should go. So far I'm using dependency injection where I pass PDO object to as a dependency.
This works quite fine, but now I need to have a Context class which would be for example holding the Info of current user. It could be something like this:
class Context
{
private $Pdo;
function __construct(PDO $Pdo) {
$this->Pdo = $Pdo;
}
function CurrentUser(){
if ($this->CurrentUser == null){
// get user logic
$this->CurrentUser = User;
}
return $this->CurrentUser;
}
}
So each time I would like to get the current user I would need to do something like this:
$Context = new Context($Pdo);
$User = $Context->CurrentUser();
I would like to be able to use this anywhere in project, but the PDO is not passed to each method there is.
I could make a singleton class for getting the PDO object anywhere I need and use that in my Context class. Would this be a good aproach? Or would a factory design be better?
Up until now I used global in such cases, but I would probably want to avoid there as the project grows rapidly.
I could make a singleton class for getting the PDO object anywhere I
need and use that in my Context class. Would this be a good aproach?
Or would a factory design be better?
Well, Singleton and Factory are not really the same thing, and your particular needs should dictate the solution.
Here is a short summary of a more in-depth post:
The Singleton pattern restricts the instantiation of a class to a single object. This provides a single point of access across the entire application, and ensure that you are always dealing with the same object.
The Factory pattern provides a new instance of the object whenever it is called. This may or may not be the same instance. Essentially the factory defines an interface for creating objects.
So, your needs will determine which pattern is better for your application. If you want a single instance of an object, go with a singleton.
Related
I have a class that is containing 10 methods. I always need to use one of those methods. Now I want to know, which approach is better?
class cls{
public function func1(){}
public function func2(){}
.
.
public function func10(){}
}
$obj = new cls;
$data = $obj->func3(); // it is random, it can be anything (func1, or func9 or ...)
OR
class cls{
public static function func1(){}
public static function func2(){}
.
.
public static function func10(){}
}
cls::func3(); // it is random, it can be anything (func1, or func9 or ...)
It is an interesting subject. I'm gonna give you a design oriented answer.
In my opinion, you should never use a static class/function in a good OOP architecture.
When you use static, this is to call a function without an instance of the class. The main reason is often to represent a service class which should not be instantiated many times.
I will give you 3 solutions (from the worst to the best) to achieve that:
Static
A static class (with only static functions) prevent you from using many OOP features like inheritance, interface implementation. If you really think of what is a static function, it is a function namespaced by the name of its class. You already have namespaces in PHP, so why add another layer?
Another big disadvantage is that you cannot define clear dependencies with your static class and the classes using it which is a bad thing for maintenability and scalability of your application.
Singleton
A singleton is a way to force a class to have only one instance:
<?php
class Singleton {
// Unique instance.
private static $instance = null;
// Private constructor prevent you from instancing the class with "new".
private function __construct() {
}
// Method to get the unique instance.
public static function getInstance() {
// Create the instance if it does not exist.
if (!isset(self::$instance)) {
self::$instance = new Singleton();
}
// Return the unique instance.
return self::$instance;
}
}
It is a better way because you can use inheritance, interfaces and your method will be called on an instanciated object. This means you can define contracts and use low coupling with the classes using it. However some people consider the singleton as an anti pattern especially because if you want to have 2 or more instances of your class with different input properties (like the classic example of the connection to 2 different databases) you cannot without a big refactoring of all your code using the singleton.
Service
A service is an instance of a standard class. It is a way to rationalize your code. This kind of architecture is called SOA (service oriented architecture). I give you an example:
If you want to add a method to sell a product in a store to a consumer and you have classes Product, Store and Consumer. Where should you instantiate this method? I can guarantee that if you think it is more logical in one of these three class today it could be anything else tomorrow. This leads to lots of duplications and a difficulty to find where is the code you are looking for. Instead, you can use a service class like a SaleHandler for example which will know how to manipulate your data classes.
It is a good idea to use a framework helping you to inject them into each others (dependency injection) in order to use them at their full potential. In the PHP community, you have a nice example of implementation of this in Symfony for instance.
To sum up:
If you do not have a framework, singletons are certainly an option even if I personally prefer a simple file where I make manual dependency injection.
If you have a framework, use its dependency injection feature to do that kind of thing.
You should not use static method (in OOP). If you need a static method in one of your class, this means you can create a new singleton/service containing this method and inject it to the instance of classes needing it.
The answer depends on what those methods do. If you're using them to mutate the state of the object at hand, you need to use the instance method calls. If they're independent functionality, then you can use the static versions, but then I'd question why they're part of a class at all.
So, there is a very basic difference in static methods.
To use static functions, you don't need to initialise the class as an object. For example, Math.pow(), here .pow() (in Java; but the explanation still holds) is a static method.
The general rule is to make the helper methods static.
So, for example, if you have a Math class, you wouldn't want to fill the garbage collector with classes which just help other, more important, classes.
You can use it as dynamic initializers, if you please!
Let's say you have a class RSAEncryptionHelper, now you can generally initialize it without any parameters and this will generate an object with a key size of (say) 512 bits; but you also have an overloaded object constructor which gets all of the properties from other classes:
$a = new RSAEncryptionHelper::fromPrimeSet(...);
Within a PHP class you can use class/methods/attributes: Abstract, Static, Private, Public, etc ...
The best way is to know how to mix them all within a class depending on the need, I will give you a basic example:
Within the Person class, you have private and public methods, but you have a method called "get_nationality" so this is a function that you need somewhere else but you do not have the Person class installed yet, so this method you put it as STATIC in this way you can invoke the "get_nationality" method without installing any Person class, this makes your business model more optimal and in turn now resources in the CPU.
Static functions are also very useful but
I usually make traits when I have to create functions that are independently related to a class.
I don't know if this approach is better or not but most times I found it useful.
Just sharing my approach here so that I can learn more about its pros and cons.
You can think a factory. You will give some materials, it will give you same output. Then you should use static function.
class ProductDetails
{
public static function getRow($id, PDO $pdo): SingleProduct
{
// this function will return an Object.
}
}
I am not defining the Object here. Just where you need a Single Product you can simply do that ProductDetails::getRow(10, $pdo);
Many times I heard to avoid static classes because they will insert dependencies that will render your code unusable in other projects, and will not allow to unit test it.
Let's say we have a typical class DB to access the Data Base, if such class is static we could call it wherever in our code:
DB::execQuery(...);
but this creates dependencies, so let's make the DB class NOT static, in such case we would have somewhere in our code:
$db = new DB();
and then we could call in our code
$db->execQuery(...);
But now when using the $db inside a function we need each time to first declare it like this
global $db;
Is there a way to workaround this?
One way could be to inject the $db object in the class that uses it, but I would have to inject it in all classes that use it, that's ridicolous, a static class would be much quicker to work with and less code to write. Am I missing something?!
$db could be injected upon instantiation into a property, then you would only need to access this property instead of passing it around to each method.
class MyClass {
protected $_db; // DB Connection
public function __construct($db) {
$this->_db = $db;
}
public function foo() {
$this->_db->query('...');
}
}
Beyond that, you can look into having a service-container (aka dependency-injection container) that trys to act like a global variable but solves some of the testing issues. Take a look at some of these related questions
If Singletons are bad then why is a Service Container good?
Is it good practice to have DI container replace a global $registry object?
Having a DI container lets you use static methods in your classes like DI_Container::get('db'). It looks a lot like global or some of the other static calls.. but in this case DI_Container contains special methods that allow for extra actions to be taken during testing and other circumstances.. eliminating some of the 'evilness' of global.
In addition to Mike B's answer, I would point that the wrong design in your code is : « we could call it wherever in our code ».
Actually, database should only be used by your Model, or the small part of your application that has to know about the database. So these classes should know there is a database, and use it as a dependency (passed through the constructor as Mike B said).
But the rest of your application should not care about a database, its should only care about the Model. Focus on refactoring and gathering all the code that access the database into Model classes.
This way, your application will have a Model layer that has a dependency : the database object/connection. And the rest of your application will use the Model, whatever happens in the Model in none of the Controller/View business.
Enjoy refactoring.
Let's say you have a object that is unique, and it's used by all other classes and functions ...something like $application.
How would you access this object in your functions?
using a global variable in each of you functions:
global $application;
$application->doStuff();
creating a function, like application() that instantiates the object into a static variable and returns it; then use this function everywhere you need to access the object:
application()->doStuff();
create a singleton thing, like a static method inside the object class which returns the only instance, and use this method to access the object:
Application::getInstance()->doStuff();
KingCrunch & skwee: Pass the application object as argument to each function/class where is needed
...
public function __construct(Application $app, ...){
....
If there are other options please post them. I'm wondering which of these options is the most efficient / considered "best practice".
I'd pass it to all the needed methods.
i.e.
function doFoo(Application $app) {
$app->doStuff();
}
Both global and singleton considered bad and ties your code too much and this makes unit testing more difficult.
There is one rule when you are allowed to use singleton, if you answer "yes" to the following statement:
Do I need to introduce global state to my application AND I must have a single instance of given object AND having more than one instance will cause error
If you answer yes to all the 3 parts then you can use singleton. In any other case just pass all the instances to all the method who needs them. If you have too much of them, consider using something like Context
class Context {
public $application;
public $logger;
....
}
========
$context = new Context();
$context->application = new Application();
$context->logger = new Logger(...);
doFoo($context);
========
function doFoo(Context $context) {
$context->application->doStuff();
$context->logger->logThings();
}
(you can use getters/setters if you need to protect the data or manipulate it or if you want to use lazy initiation etc).
Good luck!
Singletons, God Classes, monolithic classes, etc. are all anti patterns, so I would suggest a fourth option: dependency injection. You can create an instance of application in your application via a factory (or perhaps even new if it has no dependencies, but this can end up complicating things later).
Then, any class that needs access to application can get it as a member, helpfully via the constructor. I'm sure that not every class needs access to application. Remember the Law of Demeter.
If you need some generic functionality like converting one static string to another, I suggest using php's global functions (as opposed to, for instance, a faux static class). I believe they were designed for that purpose.
Or just give it to the ones, that are interested in it. All the suggestions you made are like global variables, even if you call it not that in 2 of 3 variants.
Before it comes to that: If you want to say "Thats not possible, because everything needs it", than maybe it does too much, can too much, and/or knows too much.
Writing a PHP app and have several classes that only have static methods (no need for instance methods). An example of one is NumericValidator, which has methods like checkInteger($toCheck) which checks to make sure the argument you pass it is of type int, and checkGreaterThan($lOperand, $rOperand), which makes sure that the left operand is greater than the right operand, etc.
I know I could just throw each of these methods into a PHP file without putting them inside of a class, but I want to take an OOP approach here in case the API evolves to require instantiating NumericValidator.
But it does beg the question: how is a class with 100% static methods any different than have a class implement a singleton design pattern, where every reference used throughout the code base invokes the same instance?
For example, here is what my code looks like now:
public function doSomething($p_iNum)
{
if(!NumericValidator::checkInteger($p_iNum))
// throw IllegalArgumentException
// ...
}
But I could turn all of NumericValidator's static methods into non-static instance methods, forcing the programmer to instantiate it, and then implement a singleton design pattern so you can only ever reference 1 instance of it:
public function doSomething($p_iNum)
{
NumericValidator $nv = NumericValidator::getInstance();
if(!nv->checkInteger($p_iNum))
// throw IllegalArgumentException
// ...
}
Finally, my question: which is better and more in keeping with best practices? Are there performance considerations? How would either approach affect things like concurrency, or requests coming from multiple users?
I would use a static class in your example. The differentiator I would use is if there is any state of the properties of an instance you are trying to preserve across access. This is what a singleton is designed for. The static class gives organized access to methods in a namespace which is helpful for clarity in your code but it does not have any properties about itself.
So yes you can use a singleton but it would be bad form because there are no instance properties that you want to make available across page accesses.
Hope this helps.
Use Singleton instead of static class only if you going to pass instance of NumericValidator in variable to some function.
In PHP 5.3 you can get instance of static class:
class test
{
public static function instance()
{
print 'zz';
}
}
$z = new test;
$z->instance();
Don't care about concurrency requests in PHP, it's single threaded, each process executes own code.
I'm building out a small project to try to teach myself as much of the fundamentals as possible, which for me means not using a prefabricated framework (As Jeff once put it, "Don't reinvent the wheel, unless you plan on learning more about wheels" [emphasis mine]) and following the principles of Test Driven Development.
In my quest, I recently ran into the concept of Dependency Injection, which appears essential to TDD. My problem is that I can't quite wrap my head around it. My understanding so far is that it more or less amounts to "have the caller pass the class/method any other classes it may need, rather than letting them create them themselves."
I have two example issues that I'm trying to resolve with DI. Am I on the right track with these refactorings?
Database Connection
I'm planning to just use a singleton to handle the database, as I'm currently not expecting to use multiple databases. Initially, my models were going to look something like this:
class Post {
private $id;
private $body;
public static function getPostById($id) {
$db = Database::getDB();
$db->query("SELECT...");
//etc.
return new Post($id, $body);
}
public function edit($newBody) {
$db = Database::getDB();
$db->query("UPDATE...");
//etc.
}
}
With DI, I think it would look more like this:
class Post {
private $db; // new member
private $id;
private $body;
public static function getPostById($id, $db) { // new parameter
$db->query("SELECT..."); // uses parameter
//etc.
return new Post($db, $id, $body);
}
public function edit($id, $newBody) {
$this->db->query("UPDATE..."); // uses member
//etc.
}
}
I can still use the singleton, with credentials specified in the application setup, but I just have to pass it from the controller (controllers being un-unit-testable anyway):
Post::getPostById(123, Database::getDB);
Models calling models
Take, for example, a post which has a view count. Since the logic to determine if a view is new isn't specific to the Post object, it was just going to be a static method on its own object. The Post object would then call it:
class Post {
//...
public function addView() {
if (PageView::registerView("post", $this->id) {
$db = Database::getDB();
$db->query("UPDATE..");
$this->viewCount++;
}
}
With DI, I think it looks more like this:
class Post {
private $db;
//...
public function addView($viewRegistry) {
if ($viewRegistry->registerView("post", $this->id, $this->db) {
$this->db->query("UPDATE..");
$this->viewCount++;
}
}
This changes the call from the controller to this:
$post->addView(new PageView());
Which means instantiating a new instance of a class that only has static methods, which smells bad to me (and I think is impossible in some languages, but doable here because PHP doesn't allow classes themselves to be static).
In this case we're only going one level deep, so having the controller instantiate everything seems workable (although the PageView class is getting its DB connection indirectly by way of the Post's member variable), but it seems like it could get unwieldy if you had to call a method that needed a class that needed the class that needed a class. I suppose that could just mean that's a code smell too though.
Am I on the right track with this, or have I completely misunderstood DI? Any criticisms and suggestions are greatly appreciated.
Yes. It looks like you have the right idea. You'll see that as you implement DI all your dependencies will float to the "top". Having everything at the top will make it easy to mock the necessary objects for testing.
Having a class that needs a class that needs a class is not a bad thing. What your describing there is your object graph. This is normal for DI. Lets take a House object as an example. It has a dependency on a Kitchen; the Kitchen has a dependency on a Sink; the Sink has a dependency on a Faucet and so on. The House's instantiation would look something like new House(new Kitchen(new Sink(new Faucet()))). This helps to enforce the Single Responsibility Principle. (As an aside you should do this instantiation work in something like a factory or builder to further enforce the Single Responsibility Principle.)
Misko Hevery has written extensively about DI. His blog is a great resource. He's also pointed out some of the common flaws (constructor does real work, digging into collaborators, brittle global state and singletons, and class does too much) with warning signs to spot them and ways to fix them. It's worth checking out sometime.
Dependency injection is about injecting. You need some solution to inject the external object.
The traditional approaches are:
constructor injection __construnctor($dependecy) {$this->_object = $dependency}
setter injection setObject($dependency) {$this->_object = $dependency}
gettter injection getObject() {return $this->_dependency} and oveloading this method eg. from stub or mock in the tests.
You may also mix all the above, depends what you need.
Avoid static calls. My personal rule is use static only when you call some functions, e.g. My::strpos() or when dealing with singletons or registry (which should be limited to minimum, because global state is evil).
You will rarely need static methods when your app has a good dependency container.
Take a look at the other dependency injection + [php] topics on SO.
Edit after comment:
The container
Different frameworks handle the container in different way. Generally this is an object, which holds the instances of objects you need, so you don't have to instantiate new object each time. You may register any object with such a container, and then access it anytime you need.
The container may instantiate all the resources you need at boot time, or lazy load the resource when accessed (better solution).
As an example, consider:
Zend Application Resource Plugins
Symfony Dependency Injection Container
Another great reference:
http://martinfowler.com/articles/injection.html
It's certainly going into the right direction but you should not stop there.
The point of DI is to remove strong couplings between classes to allow for easier substitution of single components. This will allow for better testability because you can substitute dependencies more easily with Mocks and Stubs. And once your code is tested, it is much easiert to change and maintain.
Consequently, you should also remove those other aspects in your code that create strong coupling smells as well, e.g. remove the static methods and the singleton and any other globals.
For some more information on that, please see
How is testing the registry pattern or singleton hard in PHP?
http://gooh.posterous.com/singletons-in-php
http://kore-nordmann.de/blog/0103_static_considered_harmful.html
http://fabien.potencier.org/article/11/what-is-dependency-injection
EDIT: with a couple of others answers suggesting to use a DI container, I feel it's necessary to stress that you do not need a DI container to do DI. The second blog post in the last link given above discusses this.
To answer your questions: yes, you are on the right track. To give you more details: this is one of the best posts I found related to DI:
http://www.potstuck.com/2009/01/08/php-dependency-injection
You will understand what a container is:
$book = Container::makeBook();
Regarding the second example: in your method addView I would try to avoid passing the object $viewRegistry, I would check the condition outside in the controller.