Micro-Dependencies, Avoiding Coupling, and Objects Creating Objects [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dependency Hell — how does one pass dependencies to deeply nested objects?
In a system built around strong dependency injection, I'm wondering how to deal with a contrived situation like this:
<?php
class LogWriter
{
public function write(Log $log)
{
echo $log->getMessage();
}
}
class Log
{
private $message;
public function setMessage($message)
{
$this->message = $message;
}
public function getMessage()
{
return $this->message;
}
}
class Logger
{
private $writer;
public function __construct(LogWriter $writer)
{
$this->writer = $writer;
}
public function write($message)
{
// Here is the dependency
$log = new Log();
$log->setMessage($message);
$this->writer->write($log);
}
}
The Logger::write() method creates an instance of Log, and passes it to the log writer. My gut tells me that's a bad approach, and a month from now I'm going to be tracking down a bug related to it, and I might want to switch the Log class for something else during testing.
But how to avoid it? The only thing that comes to mind is passing a Log type to the Logger constructor, and changing my Logger class to this:
class Logger
{
private $writer;
private $log_type;
public function __construct(LogWriter $writer, $log_type)
{
$this->writer = $writer;
$this->log_type = $log_type;
}
public function write($message)
{
$log = new $this->log_type();
$log->setMessage($message);
$this->writer->write($log);
}
}
And then creating a new Logger instance like this:
$log_writer = new LogWriter();
$logger = new Logger($log_writer, "Log");
But that feels a bit hackish. So how do you deal with micro-dependencies like this?
Note: I'm using the logging classes as an example, and I'm not looking for a solution to this exact problem. I would probably just use an array instead of the Log class.
Edit: In a more complex situation, I might pass a dependency injection container to the Logger class, and use that to create an instance of Log, but that seems overly complicated for a simple logger class.

Since your Log object is really just a Data Transfer Object or Value Object, you can create it inside the Logger class. It's okay to do so in this case. You dont need to pass anything to the Logger. But you are right in that you wont be able to mock/stub this easily then.
As an alternative, you could also inject a Factory if you want to decouple the Log class from the Logger:
$logger = new Logger($logWriter, new LogFactory);
and then create the Log Type from there:
public function write($message)
{
$log = $this->logFactory->createNew();
…
This capsules the creation logic inside the Factory class. The Factory will still have the Log type hardcoded inside, but it's okay for Factories to have that. You then just test that it returns the right type when you call createNew. And in your consumers, you can stub that call.
If you dont feel like creating a full-blown Factory class for this, you can also use a Lambda instead of a Factory. Since it captures the essential creation logic, it's effectively the same as a Factory, just without a class:
$logger = new Logger($logWriter, function() { return new Log; });
And then
public function write($message)
{
$log = call_user_func($this->createLogCallback);
…
Both, the Factoy and the Lambda approach allow for substituting the Log type in your Unit-Test. Then again, substituting the Log type doesn't seem that necessary in your scenario. The Log type doesn't have any dependencies of it's own, so you can pretty much use the real deal here. You can easily verify your write method by simply looking at what gets written by the LogWriter. You won't have an explicit assertion on a Log Mock, but if the writer produces the expected output for the given input to write, you can safely assume that the Log type collaborates as expected.
Also see http://misko.hevery.com/2008/09/30/to-new-or-not-to-new for more details.

Related

PHP Using Factory pattern for SDKs

I'm a bit lost here because I want to do something that is very easy in Java but seems a bit complicated in PHP.
We are building an SDK for our product and in Java, we have this one class that must not (!) be instantiated by the user (i.e. the coder), since there are several constraints regarding it's integrity. So we've built that as a nested class "X" inside of the "XFactory" and you will get an instance of X by calling XFactory.buildMeMyX(); - Easy...
Now PHP does not support nested classes at all, and I wonder how to apply the same here. In Java, X's constructor is hidden (private), so only XFactory can call it.
In PHP, it looks like I will have to make __construct() public and move the nested class X out of XFactory. Hence, the user will be able to create an instance without the Factory.
Now - I COULD move the factory functionality to X itself and move all the stuff there, but this would kind of break the design of the SDK. Is there a useful way to do such things in PHP after all?
For PHP 5.x you already described your options, there are no private/protected classes or inner classes at all, so there is no further way to restrict instantiation.
However, with PHP 7 this is going to change.
There are still no nested classes (although we might get them in the future, see: https://stackoverflow.com/a/31454435/664108), but you could instantiate an anonymous class and only provide the consumer with its interface like this:
class XFactory
{
public function buildMeMyX()
{
return new class() implements XInterface {
public function doWhatEverAnXCanDo()
{
// X X X
}
// ...
};
}
}
interface XInterface
{
function doWhatEverAnXCanDo();
}
As the others have said, there currently is no clean way to implement this behavior in PHP. In my opinion, the only valid use case for private constructors are factories inside the class that implement that factories.
Whenever you try to get around that use case it gets messy. No one should ever try to invent clever ways to bypass PHP's language limiations.
I just violated that rule by myself just to prove it is indeed possible. But please refrain from using that in production, or better: using it anywhere. I will try to find some bulletproof arguments for that suggestion and edit the answer afterwards.
<?php
class Dependency {}
class SomeClass {
protected $dep;
private function __construct(Dependency $dep)
{
$this->dep = $dep;
}
public function doSomething()
{
var_dump($this->dep);
echo "Doing Stuff and even having dependencies";
}
}
class SomeClassFactory {
public function buildSomeClass()
{
return $this->instantiateSomeClassWith(new Dependency);
}
protected function instantiateSomeClassWith()
{
$reflectionClass = new ReflectionClass('SomeClass');
$someClass = $reflectionClass->newInstanceWithoutConstructor();
$constructor = $reflectionClass->getConstructor();
$constructorClosure = $constructor->getClosure($someClass);
call_user_func_array($constructorClosure, func_get_args());
return $someClass;
}
}
$factory = new SomeClassFactory();
$someClass = $factory->buildSomeClass();
$someClass->doSomething();
?>
Output: object(Dependency)#2 (0) { } Doing Stuff and even having dependencies
The theory is simple. The constructor of the class that will be built via the Factory is made private. We make use of reflection within the factory to create an instance of the class without invoking the constructor.
Once we have an instance, we grab the closure of the constructor and invoke it via call_user_func_array(). That way you can make use of Dependency Injection just as you would if the constructor was public.
As I said before. That way is a single smell. By creating an object without invoking it's constructor, there is no real way to validate an objects state upon creation
This is a proof of concept, but the concept sucks.
There is no native way to do so, yet. However, if you really want to "enforce" that your class is only created from your factory class, there is a little "hackish" way to do so limiting the instantiation by inistantiating class.
class X
{
function __construct()
{
new Y();
}
}
class Y
{
function __construct()
{
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
if (!isset($trace[1]['object']) || !($trace[1]['object'] instanceof X)) {
throw new \RuntimeException('This is a private class');
}
}
}
new X(); // All is fine
new Y(); // Exception
Please note that there is no "real" way to protect the class from being instantiated from elsewhere even using this approach - it still can be done via reflection by bypassing the constructor, or simply modifying your source.

Inversion of Control with PHP

I just started using Dependency Injection for obvious reasons and without reading about Inversion of Control (IoC) quickly stumble with the issue of being verbose when instantiate some of my classes. So, reading about IoC I have a question that have not found an concrete answer. When should class registration happen? in a bootstrap? before execution? How can I enforce the type of the dependencies?
I am not using any frameworks. For the sake of learning I wrote my own container.
This is a very lowbrow example of my container and some sample classes.
class DepContainer
{
private static $registry = array();
public static function register($name, Closure $resolve)
{
self::$registry[$name] = $resolve;
}
public static function resolve($name)
{
if (self::registered($name)) {
$name = static::$registry[$name];
return $name();
}
throw new Exception('Nothing bro.');
}
public static function registered($name)
{
return array_key_exists($name, self::$registry);
}
}
class Bar
{
private $hello = 'hello world';
public function __construct()
{
# code...
}
public function out()
{
echo $this->hello . "\n";
}
}
class Foo
{
private $bar;
public function __construct()
{
$this->bar = DepContainer::resolve('Bar');
}
public function say()
{
$this->bar->out();
}
}
With these already in the app structure. The Dependecy Injection way I would do type hint the incoming parameters, but without it I can do:
DepContainer::register('Bar', function(){
return new Bar();
});
$f = new Foo();
$f->say();
To me, makes sense in a bootsrap register all dependencies it would be the more clean way IMO. At run time like a showed you I think is just as ugly as doing new Foo(new Bar(...)...).
I will try to summarize a few things that you should know and (hopefully) will clarify some of your dilemmas .
Let's start from a basic example:
class MySQLAdapter
{
public function __construct()
{
$this->pdo = new PDO();
}
}
class Logger
{
public function __construct()
{
$this->adapter = new MySqlAdapter();
}
}
$log = new Logger();
As you can see, we are instantiating Logger which has two dependencies: MySQLAdapter and PDO.
This process works like this:
We created Logger
Logger creates MySQLAdapter
MySQLAdapter creates PDO
The above code works, but if tomorrow we decided that we need to log our data in a file instead of a database, we will need
to change the Logger class and replace MySQLAdapter with a brand new FileAdapter.
// not good
class Logger
{
public function __construct()
{
$this->adapter = new FileAdapter();
}
}
This is the problem that Dependency Injection tries to solve: do not modify a class because a dependency has changed.
Dependency Injection
Di reefers to the process of instantiating a class by giving it's constructor all the dependencies it needs to function properly. If we apply Dependency
Injection to our previous example, it will look like this:
interface AdapterInterface
{
}
class FileAdapter implements AdapterInterface
{
public function __construct()
{
}
}
class MySQLAdapter implements AdapterInterface
{
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
}
class Logger
{
public function __construct(AdapterInterface $adapter)
{
$this->adapter = $adapter;
}
}
// log to mysql
$log = new Logger(
new MySQLAdapter(
new PDO()
)
);
As you can see, we don't instantiate anything in constructor, but we pass the instantiated class to constructor. This allows us to replace any dependency
without modifying the class:
// log to file
$log = new Logger(
new FileAdapter()
);
This helps us:
To easily maintain the code:
As you already saw, we don't need to modify the class if one of its dependencies changed.
Makes the code more testable:
When you run your test suite against MySQLAdapter you don't want to hit the database on each test, so the PDO object will be mocked in tests:
// test snippet
$log = new Logger(
new MySQLAdapter(
$this->getMockClass('PDO', [...])
)
);
Q: How does Logger knows that you give him a class that it needs and not some garbage ?
A: This is the interface (AdapterInterface) job, which is a contract between Logger and other classes. Logger "knows" that any class that implements
that particular interface will contain the methods it needs to do his job.
Dependency Injection Container:
You can look at this class (ie: container) as a central place where you store all your objects needed to run your application. When you need one of them,
you request the object from the container instead of instantiating yourself.
You can look at DiC as a dog who was trained to get out, get the newspaper and bring it back to you. The catch is that the dog was trained only with the front door opened.
Everything would be fine as long as the dog's dependencies will not change (ie door opened). If one day the front door will be closed, the dog will not know how to get the newspaper.
But if the dog would have an IoC container, he could find a way ...
Inversion of Control
As you saw until now, the initialization process of the "classic" code was:
We created Logger
Logger creates MySQLAdapter
MySQLAdapter creates PDO
IoC simply replicates the above process, but in reverse order:
Create PDO
Create MySQLAdapter and give him PDO
Create Logger and give him MySQLAdapter
If you though that Dependency Injection is some kind of IoC, you are right. When we talked about Dependency Injection, we had this example:
// log to mysql
$log = new Logger(
new MySQLAdapter(
new PDO()
)
);
At a first look someone could say that the instantiation process is:
Create Logger
Create MySQLAdapter
Create PDO`
The thing is that the code will be interpreted from the middle to the left. So the order will be:
Create PDO
Create MySQLAdapted and give him PDO
Create Logger and give him MySQLAdapter
The IoC container simply automates this process. When you request Logger from the container, it uses PHP Reflection and type hinting to analyze its dependencies (from constructor), instantiate all of them, sends them to the requested class and gives you back a Logger instance.
NOTE: To find out what dependencies a class has, some IoC containers are using annotations instead of type hinting or a combination of both.
So to answer your question:
If the container can resolve the dependencies by itself, you would only need to instantiate the container during the boot
process of your application. (see Inversion of Control container)
If the container can't resolve the dependencies by itself, you would need to manually provision the container with the objects needed to run your application. This provisioning usually happens during the boot process. (see Dependency Injection Container)
If your container can resolve the dependencies by itself, but for various reasons you also need to manually add more dependencies, you would do that in
the boot process, after you initialize the container.
NOTE: In the wild there are all kind of mixes between these two principles, but I tried to explain you what is the main idea behind each of them.
How your container will look depends only by you and don't be afraid to reinvent the wheel as long as you do it for educational purposes.

Dependency injection and/or factory pattern

Not sure if my title is correct cause I am not even sure I am using the correct terms.
I have a class that has a property that is an object. When setting this property the object has to be created. My question is how do I do this without tight coupling?
Example:
class A
{
protected $_depending;
protected $_somePropertyObject;
public function __construct(\Lib\Dependency $depending)
{
$this->_setDepending($depending);
}
protected function _setDepending(\Lib\Dependency $depending)
{
$this->_depending = $depending;
}
public function setSomeProperty($someProperty)
{
// I want to prevent this
$this->_somePropertyObject = new \Lib\some\Object($someProperty);
}
}
I could just pass the required object through the construct but what happens more are needed?
When if I understand correctly the factory pattern, what would this change? I would still need to create the object somewhere? Not the object itself but the factory. Again tight coupling? Seems endless to me. When re factoring class(es) it however is isolated where and how the class(es) are made.
If I set the setSomeProperty function to only accept \Lib\some\Object then is still needs to be created by the parent object that is passing it to begin with. Seems only to shift the placement of where it is created?
Hopefully I am clear enough in what I am trying to ask.
Thanks in advance!
EDIT What I am asking is the sequence of what is created when,where,why.
The purpose of a factory in dependency injection patterns is to produce instances for another instance, without that other instance needing to know how to produce it.
At its core, a "factory" is just an object-returner: something that returns an instance when invoked.
This is easier to see in more capable languages. For example in Python classes are callable (there is no new operator), and invoking a class produces an instance of the class. So classes can be their own factories if the class requires no arguments. Likewise any zero-argument function that returns an instance can be considered a factory. This makes dependency injection very clear and free-of-boilerplate.
In more rigid languages (Java/C++/C# static-typed tradition, or where classes or functions are not completely first-class like in PHP), you need to obscure dependency injection behind a "pattern", because "design patterns" are missing language features. In PHP 5.3+ you can use a closure as a factory, or you can go the Java/C# way and define a FactoryInterface and a new class per factory.
For example, with your class, you could do this:
class Aprime extends A
{
public function setSomeProperty($somePropertyFactory)
{
$this->_somePropertyObject = $somePropertyFactory();
}
}
In this class, setSomeProperty requires a zero-argument callable "factory", which you could produce like this:
$other_dep_factory = function(){ return new SomeOtherClass(); };
Or like this:
class ClassFactory {
function __construct($classname, $args=array()) {
$this->class = new ReflectionClass($classname);
$this->args = $args;
}
function __invoke() {
return $this->class->newInstanceArgs($this->args);
}
}
$other_dep_factory = new ClassFactory('SomeOtherClass');
Prior to PHP 5.3, you need to do it like Java would:
interface IObjectFactory {
function getObject();
}
// this B-and-D interface is optional
// it has no body because PHP doesn't support
// type-hinting return values
interface ISomeOtherClassFactory {}
class SomeOtherClassFactory implements ISomeOtherClassFactory {
function getObject() {
return new SomeOtherClass();
}
}
class Aprime extends A
{
public function setSomeProperty(ISomeOtherClassFactory $somePropertyFactory)
{
$this->_somePropertyObject = $somePropertyFactory->getObject();
}
}
$other_dep_factory = new SomeOtherClassFactory();
$myAprimeObject->setSomeProperty($other_dep_factory);
So when do you use a factory? Whenever an object needs to create another object. If the object just needs to use another object, just pass in an instance.
I like to use the Factory Pattern when you need to collect "information" to create the object that's stored in $_somePropertyObject. For instance let's say you have to assign values to some properties to instantiate it or run a couple of methods right after you instantiate it.
Also, you'll want to consider whether you might need to later change the inheritance tree. If you might be assigning $_somePropertyObject a \Lib\some\Object now, you might find yourself wishing you could easily swap it out for a \Lib\some\FancyObject later. If you use Dependency Injection, you can easily swap subtypes.
Here's a primer: http://net.tutsplus.com/tutorials/php/the-whens-and-whys-for-php-design-patterns/
Also, too: https://stackoverflow.com/a/2083455/1121827

Can I use static class for my Logger?

Recently I have been told that static class/methods are evil.
Take for example my class Logger:
class Logger{
private static $logs = array();
public static function add($msg){
self::$logs[]=$msg;
}
public static function echo(){
print_r(self::$logs);
}
}
I can use whenever i want in my appliaction like this:
Logger::add('My log 1');
But reading this developers:
http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/
That Logger class doesn't seem so good.
So: Can I use it statically or I should avoid it at any cost?
Logging classes are the exception.
Since they rarely contain much logic, you don't have the same testing concerns.
Logging is a perfect example of a GOOD place to use static classes.
Think of your alternatives:
A global instance of a logging object?
A singleton logging object?
Pass the logging object around to every single method/class (via in a constructor)?
The above are much worse than using static for logging.
Avoid it. I've seen quite some posts of you now struggling with the issue and people giving you bad advice. I'll repeat what I said in some of my answers/comments.
The way you use static in your logger class is to use it as a globally access point. Whenever you need to logg something you call Logger::log().
1) You will not be able to tell from looking at your class definition that it depends on the Logger class. Change in code thus becomes an adventure: 'I hope I will not break some hidden dependency when I change this tiny little ... OOPS!'.
2) It IS harder to test. You can't realiably test a class that sends a message to the Logger with Logger::log(). When a test fails how will you know it is not because the Logger fails? You would know if you could replace it with a mock, but in your case it is not mockable.
An alternative to explore:
Use the observer pattern and make the Logger an observer, the classes that need logging can be observables. They send messages like $this->observers->nofify('test succeeded').
You could use some other form of events too or dependency injection (automatic or manual). But please please don't call Logger::log() in a method.
I still think that logging is a valid approach to use a static classes. The often stated phrase that it is not testable is imho also not true if you do it right. I want to implement this but did not find the time, however, I thought about something like the following.
class Logger {
protected static $handlerSet = [];
// Pure static class {{{
private function __construct() {}
private function __clone() {}
private function __sleep() {}
private function __wakeup() {}
// }}}
public static function critical($message, array $context = []) {}
// You know the PSR drill...
private static function log($level, $message, array $context) {
foreach ($this->handlerSet as $handler) {
$handler->handle($level, $message, $context);
}
}
}
Of course we do not want to expose the management of the handlers to all classes, hence, we use a child class that has access to the protected handler set.
final class LoggingManager extends Logger {
public static function addHandler(Handler $handler, $name, $level) {
static::$handlerSet[$name] = $handler;
}
public static function removeHandler($name) {
if (isset(static::$handlerSet[$name])) {
unset(static::$handlerSet[$name]);
}
}
public static function resetHandlers() {
static::$handlerSet = [];
}
// Other useful stuff...
}
Testing is now fairly easy, if you actually want to test something like logging (could be that it has some ROI for you, don’t know).
class SomeTest extends YourFrameworksTestCase {
public function testThatSomethingLogsSomething() {
try {
$handler = new TestLogHandler();
LoggingManager::registerHandler($handler, 'test', 'debug');
// Test something.
$this->assertLogRecordExists($handler, '[debug] StackOverflow');
}
finally {
LoggingManager::resetHandlers();
}
}
}
It would also be possible to create a more sophisticated test case to extend that implements all of the log record assertion for you. This approach is imho fairly easy and a class in your system should not care whether a handler is registered or not, nor what it does with the logged messages. Things like that are handled in your application and only there. The advantages are obvious:
Global access to the logger and logging manager.
Easy testing, comparable to dependency injection.
No need for code polluting DIC solutions.
Single logger instance, always.
…
While there is nothing wrong with that approach, I recently moved from a static logging class approach to log4php in one of my own projects myself.
log4php uses a separate instance of a logging class for each class in your project. When looking at that logging framework, the benefits become obvious.
Logged messages always have a context (the class through which the message was logged). That allows for easy filtering (and make the log slightly more helpful).
The only problem with static classes is that they are hard to change.
So it's ok here since you're class doesn't do much.

unit test a method that creates an object

I'm trying to get my head round Unit Testing and there's one more piece of the jigsaw I need to find.
What I'm trying to do is write tests for the following code. In this case, I've got a really simple Front Controller (written in PHP).
class frontController
{
public function routeRequest($oRequest)
{
$sClassname = $oRequest->getController();
$sMethod = $oRequest->getAction();
$oController = new $sClassname();
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
}
The problem I have is because the code creates new objects. I can easily mock the request object so that I can tightly control what it will actually do within my test case. I'm not sure the best way to actually replace the controller with a test double.
This article from IBM suggests having a factory method for creating my controller and then overriding this with a specific class used for testing:
class frontController
{
public function routeRequest($oRequest)
{
$sMethod = $oRequest->getAction();
$oController = $this->createController($oRequest);
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
protected function createController($oRequest)
{
$sClassname = $oRequest->getController();
return new $sClassname();
}
}
and then for testing perhaps something like this:
class testFrontController extends frontController
{
public function setMockController($oMockController)
{
$this->oMc = $oMockController;
}
protected function createController($oRequest)
{
return $this->oMockController;
}
}
(note this isn't quite what the article says, but I'm thinking it would be most useful to me if it did this)
Another solution could be to have another class that creates the controller. This would then be a dependent class of the frontController. This way I can replace the factory/creation class during testing with a test double. Something like this:
class frontController
{
public function routeRequest($oRequest, $oControllerFactory)
{
$sMethod = $oRequest->getAction();
$oController = $oControllerFactory->create($oRequest);
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
}
class controllerFactory
{
public function create($oRequest)
{
$sClassname = $oRequest->getController();
return new $sClassname();
}
}
I guess the dependency injection could be taken care of in the front controller constructor or via a setter instead of a parameter to the actual "route" method.
I think I prefer option 2.
Is either of these two methods the right way of going about testing this kind of thing?
(perhaps "good way" would be better word here!)
Any thoughts or suggestions on option 1 vs option 2 appreciated or indeed any alternatives. Remember - the key thing is about how to test an object that itself creates other objects as part of its execution.
Thanks!
You might find this article handy.
It discusses how object creation should be separated from the actual running of the application.
I generally find factories to be a good thing to use for this scenario. In addition to the swappability aspect, it means that additional parameters, data, or dependencies required by the object being created can be stored by the factory, and so the object which actually requests the new object doesn't have to know anything about them...
You do not want to use the real controller but a mock, right ?
It seems to me the simplest way to achieve this would be to subclass the request so that it returns the name of a MockController.
I assume you have thought through your assertions so as to define the goal of what exactly you are testing. Keep in mind that unit tests are going to be testing the returns from your methods, which, in this case, is $oResponse (whatever this may be). As a result, your test assertions will be based on this return value. Since I don't know what that return value is from your code snippets, I can only demonstrate an example that you can complete.
I would recommend PHPUnit for your testing as it seems to be the most complete package for PHP imho (many are fans of SimpleTest, as well ... to each their own).
It would look something like this (Please note that I have left out includes for brevity. Read the PHPUnit documentation for more information):
class AimTest extends PHPUnit_Framework_TestCase{
private $_controller = null;
private $_request = null;
public function setUp(){
$this->_controller = new frontController();
//what does this object's type?
$this->_request = new requestObject();
}
public function testObjectCreation(){
/*
* note, that this is only one of several assertions that could
* be made depending on the return value
*/
$return = $this->_controller->routeRequest($this->_request);
//tailor to what you expect your output to be
$this->assertTrue($return == "my expected output");
}
Hope I didn't miss the mark completely on your stated purpose. Moral of the story is that you can only test what your methods return. If you want to test object instantiation from a method, use the instanceof PHP function against a method that returns that object after instantiation.

Categories