How to deal with factory boilerplate once your project gets larger? - php

So I started working with a new framework called Zend Expressive which is the 2nd PSR-7 component based framework which should allow you to get code up and running fairly quick.
Now my problem with expressive is that as your project gets larger your factory boilerplate also increases. So for every Action class there's a ActionFactory class paired with it to inject the proper dependencies which we then create an alias to before we dispatch and pass that to our route.
The more action's the more factory boilerplate and I'm trying to figure out how do we cut down on that boiler plate?

As I said in the comments, I don't think there is a universal solution to create factories. I know that you don't use zend-servicemanager, but it comes with a cli command to generate factory classes: https://docs.zendframework.com/zend-servicemanager/console-tools/#generate-factory-for-class
It might give you ideas on how to create a factory generator yourself.
Here's an article about it: http://www.masterzendframework.com/simple-factory-generation-with-factorycreator/

Can try to implement logic with dependency resolver.
You can save a lot of factories by resolving dependency with class reflection.
$instance = null;
$reflection = new \ReflectionClass($className);
$constructor = $reflection->getConstructor();
if ($constructor === null) {
// no constructor specified, you can simply return the new instance.
$instance = $reflection->newInstanceWithoutConstructor();
} else {
// if there is constructor, you can loop through the constructor parameters and build the instance.
}
Need to be careful to avoid circular dependency here.

Related

How does Reflection in Laravel work?

How does reflection in Laravel actually work?
I tried to debug it to see how Laravel uses reflection in a controller's constructor or methods to resolve their dependencies and sub-dependencies and then and give it back to us.
But I found it hard, and it's very complicated to see and to even understand 50% of. Jumping from class to class, I can't really see it. I tried a few times by debugging it with low results of understanding.
I am very impressed by this and by reflection, and the way Laravel uses it makes my heart burn—it's just beautiful. And I wish to fully understand that—the whole process—in general, and step by step.
Beginning from hitting the route to finally having, let's say, dd($x), where $x is from a method argument and is a TestClass that has another dependency of TestClass2 that should be constructed through: $x = new TestClass(new TestClass2());
I think those are beautiful mechanics and architecture, and understanding this is something I want so badly.
So again, my question is: how does reflection in Laravel actually work?
It's not about dd guys... Let's say without dd. Just as I said earlier - when we have this object instantiated from the class method. It's not about dumping it, it's just about having it from method injection by reflection.
The dd was only an example. It can even be die(var_dump()); and it will work
Laravel uses PHP's reflection API for several components. Of these, the inverson-of-control (IoC) dependency injection container and controller method injection are most visible to developers.
To more clearly illustrate the use of reflection, here's a dramatically simplified version of the routine Laravel's IoC container class uses to build up an object's dependencies through constructor injection:
function build($className)
{
$reflector = new ReflectionClass($className);
$constructor = $reflector->getConstructor();
foreach ($constructor->getParameters() as $dependency) {
$instances[] = build($dependency->getClass()->name);
}
return $reflector->newInstanceArgs($instances);
}
As we can see, the concept isn't too difficult to understand. The container uses PHP's ReflectionClass to find the names of the classes in an object's constructor, and then loops through each of these names recursively to create instances of each object in the dependency tree. With these instances, build() finally instantiates the original class and passes the dependencies as arguments to the constructor.
Controller method injection uses the same container functionality shown above to resolve instances of dependencies declared as method parameters, but there's a bit of extra logic needed to separate class dependencies from route parameters:
function dispatch(Route $route, Controller $controller, $methodName)
{
$routeParameters = $route->parametersWithoutNulls();
$method = new ReflectionMethod($controller, $methodName);
foreach ($method->getParameters() as $index => $parameter) {
$class = $parameter->getClass();
if ($class !== null) {
$instance = build($class->name);
array_splice($routeParameters, $index, 0, [ $instance ]);
}
}
$controller->callAction($methodName, $routeParameters);
}
Again, this adaptation is slimmed-down to highlight the role reflection plays and relies on our build() function shown previously. The ControllerDispatcher class uses the getParameters() method of PHP's ReflectionMethod to determine which parameters a controller method expects, and then loops through these to find parameters that represent dependencies that it can resolve from the container. Then, it splices each dependency it finds back into the array of route parameters that it passes back to the controller method defined for the route. See RouteDependencyResolverTrait for details.
If we ignore the application bootstrapping process, this dependency injection cascade typically starts for a request when Laravel maps a request to a route, and then determines which controller to pass the request to. Laravel first resolves an instance of the controller from the container, which builds out any constructor-injected dependencies. Then, Laravel finds the appropriate controller method and resolves any more dependencies for the arguments as needed.
As shown here, Laravel uses relatively simple techniques to implement these tools using reflection. However, unlike the examples shown in this answer, the framework adds a lot of additional code to make them as robust and flexible as they are today.

How do I use Doctrine from within my application, considering modern OOP practices?

Doctrine examples usually make use of Doctrine's $entityManager. Hence, whenever I need to do anything in my app with Doctrine, I need to get the entity manager into my code. But how? .... I can inject it into my class, but still I need to create manager somewhere first. I can also make it use PHP's trait which I put into my class to make it Doctrine-enabled.
What I have done in my OOP code is something like this -- I defined a class DoctrineConnector in its own namespace of DoctrineConnector, and inside the class I have a static function getEntityManager. Inside, I read Doctrine configuration, paths, parameters, and create an $entityManager, and then I return it to the caller.
Whenever I need to read or persist something in my Doctrine-unaware code, I do this:
//Pricing.php
use DoctrineConnector\DoctrineConnector;
class Pricing
{
public function getPricing()
{
$entityManager = DoctrineConnector::getEntityManager();
//further Doctrine code to read DB
}
}
DoctrineConnector is now a dependency of Pricing. Obvious answer may be "inject $entityManager into Pricing". But Pricing is called from another class, and that other class is called from another class, etc so I will have to make essentially every class I call be aware of the ORM variable. I want to avoid that.
Is what I currently have just fine or is there a better way?
How ZF2 module system does it
Out of curiosity I looked into how ZF2 manages Doctrine module and from DoctrineORMModule, it uses ServiceLocator pattern to call the inside of controller. So one of the leading framework module systems is not that far off from my implementation.
Singleton Pattern
Adapted from http://www.phptherightway.com/pages/Design-Patterns.html
namespace ABC;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
class DoctrineConnector
{
private static $instance;
public static function getEntityManager()
{
if (null === static::$instance)
{
// Doctrine Config (from Docs)
include 'config/doctrine-config.php';
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
static::$instance = EntityManager::create($dbParams, $config);
}
return static::$instance;
}
protected function __construct()
{}
private function __clone()
{}
private function __wakeup()
{}
}
//to call
$em = DoctrineConnector::getEntityManager();
//if used later in the code - calls same instance
$em = DoctrineConnector::getEntityManager();
There are a couple of popular ways to get a dependency inside the class.
make the class aware of project environment and let the class locate the dependency (what you did with DoctrineConnector)
use dependency injection (what you are trying to achieve)
In your case, your class now depends on DoctrineConnector and is going to work as long as it can find DoctrineConnector. If you port your class to another project where DoctrineConnector isn't defined, your code isn't going to work.
Normally dependency injection is a decision you make when you start your new project. If you already have a large hierarchy of classes, the injection code will bubble up your hierarchy and there is going to be a lot of work refactoring your code. You might want to think wether you really need that and wether it's going to be worth your time.
If you are writing code for one particular app and have no plans to migrate it to other projects, then you probably don't care about dependency injection. Actually, without injection your code is going to be shorter and easier (faster) to write and understand. On the other hand if you have pieces of code that you want to be independent of the app, you might use dependency injection only for those code segments.
If you haven't injected ORM yet, chances are that the rest of the code is tightly coupled with your app as well, and injecting entityManager isn't going to make your code much more portable.

Instantiating dependencies in Laravel 5, the good way

Laravel 5 offers automatic dependency resolving if I type-hint the needed class/interface. But how should they be instantiated? Example:
public function __construct(Dependency $dependency) {
$this->dependency = $dependency;
}
And then, in another method, I'd like to create two instances, like this:
$one = new Dependency(1);
$two = new Dependency(2);
What is the most flexible and test-friendly way to do this?
Excuse my poor joke, but it depends.
It looks like you have misunderstood the dependency resolving a little bit.
In your example the property 'dependency' allready contains an instantiated object. If you need two different instances within another method you may instantiate them there, inject a container or use a factory. It depends on your needs.
a very short introduction to laravel dependency resolving
The automatic dependency resolving in laravel is provided by the service container and it is used to deliver an (allready) instantiated object. The resolved object must be binded to service container. The best way to do this is via service providers. Within the register method of a service provider you are able to do your bindings
$this->app->bind('Dependency', function ($app) {
return new Dependency();
});
In this example the container will return a new instance every time it is called.
If you need the same instance every time you may bind a singleton
$this->app->singleton('Dependency', function ($app) {
return new Dependency();
});

Using a custom provider class to remove tight coupling

I have a custom framework where i have a class/method which uses my own Cache class.
Currently it is tightly coupled. So a method instantiates the Cache class like this:
public function someMethod ( )
{
$cache = new Cache\HHCache();
}
I want ro remove the tight coupling but that's actually where i'm a bit stuck.
I thought it would be a good idea to create some sort of ServiceProvider class. But i'm not sure if this is really the right approach.
To start i have HHConfig file which has a static property in which a cache class is defined. In short:
class HHConfig
{
static $_cacheClass = '\Core\Cache\HHCache';
}
So basically i have a class like this, which is part of the Core functionality of my framework:
interface IHHServiceProvider
{
public function getService ( );
}
Then i have another class which implements this interface.
class HHCacheProvider implements IHHServiceProvider
{
public static function getService ( )
{
$class = HHConfig::$_cacheClass;
return new $class();
}
}
So now someMethod can use the HHCacheProvider class to get an instance of a Cache class.
public function someMethod ( )
{
$cache = HHCacheProvider::getService ( );
}
My IHHServiceProvider isn't really like the typical Provider class since you can't really register any Services to it. It simply looks in the HHConfig class what "class" to load and returns in instance of that.
So somehow this method doesn't feel right to me, but i do think it shows what i want to achieve. In what ways can i improve this?
Please note that i'm not looking for a simple Dependency Injection pattern for this. Because i don't want to inject my Cache class to every constructors class. I need a non tight coupling way of getting an instance of the HHCache class somehow from within a method.
Some sort of provider class that can be part of my framework seems like the right direction.
Note: "provider" means nothing. There is not pattern by that name.
Instead of making some magical "privider", you should take a look at factory pattern. Basically the idea is a follows:
You inject a factory in classes that will use some services (assuming that Cache is not the only form of service that you aim for).
The class request from factory the service that it needs:
if service has been already initialized once, it just returns an instance to your
else it creates new instance, stores it and returns you to "consumer"
The simplest code example would be something like this:
class ServiceFactory
{
private $storage = [];
public function create( $name )
{
if ( false === array_key_exists( $name, $this->storage ))
{
$instance = new $name;
$this->storage[$name] = $instance;
}
return $this->storage[$name];
}
}
This is an extremely simplified example, but even in this case, if you inject an instance of this factory in any number of objects, they all will have access to same pool of instances.
If you ever decide to look into concept of DI Containers, then factories are also the place where it is appropriate to utilize them, without degrading them to as service locator anti-pattern.
.. and few lectures that you might find valuable:
The Clean Code Talks - Don't Look For Things!
The Clean Code Talks - Global State and Singletons
As per OP request
Especially since it will be part of the framework, you should inject the Cache. A DI Container is the best solution here, you can config the actually Cache implementation as a singleton. Your proposed solution is tightly coupled to some service and hard to test in isolation. Actually it looks more of a service locator pattern rather than provider.
If you're using a Factory that won't replace the DI Container. THe point of DI is that the code shouldn't be coupled to an outside static service. Unless you have a very good reason, any object should use only the injected (via constructor or as method argument) dependencies.

Is it dependency injection and is it a bad practice?

I have a small framework and I coded it like this. I'm not sure if it is called dependency injection or not. I don't know if it is like a design pattern or not. I also don't know and wonder if passing $this as param is a bad practice.
Have a look at this; (Not a working example, just wrote those codes into browser for explanation.)
/* This is engine model */
require_once('Database.class.php');
require_once('Image.class.php');
require_once('Misc.class.php');
require_once('BBCode.class.php');
class FrameWork_Engine_Model
{
public $database, $config, $misc, $bbcode, $controller, $image;
function __construct($config)
{
$this->database = new Database($configParams);
$this->image = new Image($this);
$this->misc = new Misc($this);
$this->bbcode = new BBCode($this);
$this->controller = new Controller($this); //here I call Register controller depending on routing, in this case, register controller.
}
...
}
/* This is register controller */
class Register extends Base_Controller
{
/*I can access anything over Engine Model in my controllers */
$this->engine->database->query(); //I access database model
$this->engine->bbcode->tag('you'); //I access bbcode model
$this->engine->image->sanitizeUploadedFile(); //I access image model
//etc. I can access others models like this.
}
Basically, my controllers can access any models via engine model. I believe dependency injection is all about injecting dependencies into controllers? Like, my register controller needs a database model, routing model, and templating model to work. Here it has everything it depends on. Am I mistaken?
With those said, my questions are:
Is it a valid dependency injection example? If not, what it is? Does it have a name in design patterns?
If it is nothing related to dependency injection, what changes needs to be done to be DI?
Is passing $this parameter on newly created classes is a bad practise? If so, why?
Ps. I know asking 3 questions in a topic isn't something stackoverflow likes, but I don't want to copy paste entire text to ask them.
You are almost there.
Question 1
No, I don't see it as a valid dependency injection example. It resembles a bit a service locator (because you're injecting the entire container into your services and use it to "locate" dependent services).
Question 2
You're making a small confusion between dependency injection and a dependency injection container.
First of, dependency injection means pushing dependencies into an object at runtime instead of creating/pulling them.
To exemplify this:
//hardcoded dependecies
class BadService
{
public function __construct()
{
$this->dep1 = new ConcreteObject1();
$this->dep2 = new ConcreteObject2();
}
}
So in the example above, the BadService makes it imposible to wire other dependencies at runtime because they are already hard pulled into the constructor itself.
//service locator pattern
class AlmostGoodService
{
public function __construct(Container $container)
{
$this->dep1 = $container->getADep1();
$this->dep2 = $container->getADep2();
}
}
In the AlmostGoodService example, we've removed the hard dependencies from the previous example but we are still depending on a specific implementation of our container (meaning that our service is not reusable without providing the implementation for that container). This is the example that matches what you're doing.
//dependecy injection
class GoodService
{
public function __construct($dep1, OptionalInterface $dep2)
{
$this->dep1 = $dep1;
$this->dep2 = $dep2;
}
}
The GoodService service is not concerned with the creation of it's concrete dependencies and can easily be "wired" at runtime with any dependencies that implement the "protocol" of the $dep1 or the OptionalInterface for the $dep2 (therefore the name of Inversion of Control - the underlying concept behind Dependency Injection).
The component that does this wiring is called a dependency injection container.
Now, a dependency injection container, in it's simplest form, is nothing more than an object capable of wiring up your objects at runtime based on some form of configuration.
I said that you are almost there but there are some problems with your implementation:
the wiring should be lazy (you do not want to make all that work in your constructor, as your application would slow down considerably as it grows)
you should not pass the entire container ($this) as a dependency because then you fallback to a weaker inversion of control, namely a service locator. You should instead pass the concrete dependencies to your service constructors
Question 3
There are some cases when you'll find yourself wanting to pass the entire $container as a dependency to a service (namely controllers or lazy service factories), but generally it will be better to stay away from this practice as it will make your services more reusable and easier to test. When you're feeling that your service has too many dependencies, then that it's a good sign that you're service does too much and it's a good time to split it.
Prototype Container Implementation
So, based on my answers above, here is a revised (far from perfect) implementation:
/* This is the revised engine model */
class FrameWork_Engine_Model
{
function __construct($config)
{
$this->config = $cofig;
}
public function database()
{
require_once('Database.class.php');
return new Database($this->config['configParams']);
}
public function bbcode()
{
require_once('BBCode.class.php');
return new BBCode($this->database());
}
public function image()
{
require_once('Image.class.php');
$this->image = new Image($this->config['extensionName']);
}
....
public function register_controller($shared = true)
{
if ($shared && $this->register_controller) {
return $this->register_controller;
}
return $this->register_controller = new Register_Controller($this->database(), $thus->image(), $this->bbcode());
}
}
Now, to use your services:
$container = new FrameWork_Engine_Model();
$container->register_controller()->doSomeAction()
What could be improved? Your container should:
provide a way to share services - that is, to initialise them only once
be lockable - provide a way to lock it after configuration
be able to "merge" with other containers - that way your application will be really modular
allow optional dependencies
allow scopes
support tagging services
Ready to use DI Container Implementations
All of these are accompanied with clear documentation about Dependency Injection
Pimple - PHP 5.3 lightweight DI container
Symfony2 DI Container - PHP 5.3 feature full DI container
Juice DI - Small PHP 5.2 DI container
Your FrameWork_Engine_Model is a registry (Registry Pattern). Injecting the registry as dependency into all objects is kind of a misunderstood dependency injection. Technically it is DI, but you create a dependency from everything to everything and also take away the flexibility that DI should offer.
If your FrameWork_Engine_Model was meant to instantiate services and manage their dependencies, you could change it to an Inversion of Control Container (typical pattern related to DI)
No, not in general.
I won't argue your choice of class names and the responsibilities of your services and controllers, as I don't think it is within scope of this question. Just a remark: it looks like your controllers do too much. If you are interested in clean code, you might want to have a look at the Single Responsibility Principle and keep your controllers "thin", moving business logic and database queries to a service layer and output mechanisms like bbcode to views.
So, back to your example and how to change it to a sensible usage of Dependency Injection. A primitive IoC container could look like that:
public function createRegisterController()
{
$controller = new RegisterController();
$controller->setImage($this->getImageService());
// ...
return $controller;
}
public function getImageService()
{
if ($this->imageService === null) {
$this->imageService = new Image();
// inject dependencies of Image here
}
return $this->imageService;
}
The important point here is: Only inject the dependencies that are needed. And don't create a bunch of global variables disguised as DI.

Categories