Below you will find pages that utilize the taxonomy term “Reuse”
Final classes by default, why?
I recently wrote about when to add an interface to a class. After explaining good reasons for adding an interface, I claim that if none of those reasons apply in your situation, you should just use a class and declare it “final”.
PHP 5 introduces the final keyword, which prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being defined final then it cannot be extended.
Reusing domain code
Last week I wrote about when to add an interface to a class. The article finishes with the claim that classes from the application’s domain don’t usually need an interface. The reason is that domain code isn’t going to be swapped out with something else. This code is the result of careful modelling work that’s done based on the business domain that you work with. And even if you’d work on, say, two financial software projects in a row, you’ll find that the models you produce for each of them will be different in many subtle (if not radical) ways. Paradoxically you’ll find that in practice a domain model can sometimes be reused after all. There are some great examples out there. In this article I explain different scenarios of where and how reuse could work.
Lean publishing "Principles of Package Design"
During the great PHP Benelux Conference 2015 edition I published the final version of Principles of Package Design. Let me tell you a little bit about its history and some of the things I had to deal with.
A bit of history
My first book, A Year With Symfony, was released on September 4th, 2013. Just 6 days later, I started working on Principles of PHP Package Design. As it turned out, it was quite hard to keep the process going. There were several months in which I wrote nothing at all. Sometimes I picked up the work, but then I had completely lost my track and tried to get back on it by revising existing chapters over and over again. Meanwhile all kinds of other projects begged for attention as well, including the release of the backend project of the new nos.nl website, the preparations for the Hexagonal architecture training and the birth of our daughter Julia ;)
Packages: the case for clones
Don’t reinvent the wheel
There is this ongoing discussion in the PHP community (and I guess in every software-related community) about reinventing wheels. A refreshing angle in this debate came from an article by Phil Sturgeon pointing to the high number of “duplicate” packages available on Packagist. I agree with Phil:
Sometimes these are carbon copies of other packages, but often they are feature-weak versions of established packages.
It doesn’t make sense to do the same thing over and over again. At least I personally don’t try to make this mistake. If I want to write code that “already exists”, at least I don’t publish it on Packagist.
Symfony2: Framework independent controllers part 3: Loose ends
Thanks! Let me explain myself
First of all: thanks everybody for reading the previous parts of this series. Many people posted some interesting comments. I realized quickly that I had to explain myself a bit: why am I writing all of this? Why would you ever want to decouple controllers from the (Symfony2) framework? You probably don’t need to bother anyway, because
The chances of you needing to move controllers to other frameworks is next to none. — Rafael Dohms
Symfony2: Framework independent controllers part 2: Don't use annotations
In the previous part of this series we decreased coupling of a Symfony controller to the Symfony2 framework by removing its dependency on the standard Controller
class from the FrameworkBundle.
Now we take a look at annotations. They were initially introduced for rapid development (no need to create/modify some configuration file, just solve the issues inline!):
namespace Matthias\ClientBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
/**
* @Route("/client")
*/
class ClientController
{
/**
* @Route('/{id}')
* @Method("GET")
* @ParamConverter(name="client")
* @Template
*/
public function detailsAction(Client $client)
{
return array(
'client' => $client
);
}
}
When you use these annotations, the details
action will be executed when the URL matches /client/{id}
. A param converter will be used to fetch a Client
entity from the database based on the id
parameter which is extracted from the URL by the router. The return value of the action is an array. These are used as template variables for rendering the Resources/views/Client/Details.html.twig
template.
Symfony2: How to create framework independent controllers?
Part I: Don’t use the standard controller
The general belief is that controllers are the most tightly coupled classes in every application. Most of the time based on the request data, they fetch and/or store persistent data from/in some place, then turn the data into HTML, which serves as the response to the client who initially made the request.
So controllers are “all over the place”, they glue parts of the application together which normally lie very far from each other. This would make them highly coupled: they depend on many different things, like the Doctrine entity manager, the Twig templating engine, the base controller from the FrameworkBundle, etc.
Inject a repository instead of an entity manager
It appears that I didn’t make myself clear while writing about entity managers and manager registries yesterday. People were quick to reply that instead you should inject entity repositories. However, I wasn’t talking about entity repositories here. I was talking about classes that get an EntityManager
injected because they want to call persist()
or flush()
. The point of my previous post was that in those cases you should inject the manager registry, because you don’t know beforehand which entity manager manages the entities you are trying to persist. By injecting a manager registry you also make your code useful in contexts where another Doctrine persistence library is used.
Inject the ManagerRegistry instead of the EntityManager
Or: how to make your persistence-related code more reusable
You probably know that you should trim your controllers as much as possible. This usually means extracting some classes from the semi-procedural code inside your controller class. You create services for the extracted classes and inject the necessary dependencies into them. You can no longer use the convenient $this->getDoctrine()->getManager()
. Instead you inject the doctrine.orm.default_entity_manager
service into every service that needs the EntityManager
to persist data in your relational database:
Why Symfony? Seven Facts
A couple of days ago I was asked to explain myself: “Why Symfony?”. I was reminded of this video - an interview with Fabien Potencier:
Fabien mentions some facts about Symfony that are key to understanding it, as an outsider. These same facts (and some more) will also help you to “sell” Symfony to others.
A New Book About Symfony2: A Year With Symfony
As you may have heard, I’m working on a book for Symfony2 developers. Besides The Book, which is the user documentation for building Symfony applications, some book-like websites and just a few e-books, there are currently no books for intermediate or advanced Symfony developers. My new book, called A Year With Symfony is exactly that.
If you have been reading the documentation and maybe some blog posts, you will want to know how you can get one step further. You wonder how you could structure your application, for it to be maintainable for more than a month. You ask yourself what it would take to write good bundles, which guidelines you and your team should define and follow. You may also question the built-in security measurements and you or your manager would like to know what needs to built on top of them to make a real secure application. A Year With Symfony will help you find an answer to all these questions.
PHPUnit & Pimple: Integration Tests with a Simple DI Container
Unit tests are tests on a micro-scale. When unit testing, you are testing little units of your code to make sure that, given a certain input, they produce the output you expected. When your unit of code makes calls to other objects, you can “mock” or “stub” these objects and verify that a method is called a specific number of times, or to make sure the unit of code you’re testing will receive the correct data from the other objects.
Symfony2 & MongoDB ODM: Adding the missing ParamConverter
Just a quick post…
What seems to be missing from the DoctrineMongoDBBundle is a ParamConverter service which resolves request attributes to controller arguments by fetching a Document using the MongoDB DocumentManager. For entities, this would work:
/**
* @Route("/blog/{id}
*/
public function showAction(Post $post)
{
// $post will be the entity Post with the "id" taken from the route pattern
}
This works because of the DoctrineParamConverter, which is registered by default by the SensioFrameworkExtraBundle. But only for Doctrine ORM, and not for Doctrine MongoDB ODM. As Christophe Coevoet mentioned when someone tried to implement this missing feature, it can be added easily by yourself, without writing any PHP code, though it might not be so clear how to accomplish this. Still, the only thing you have to do is add a service to your services.xml
file:
Silex: creating a service provider for Buzz
The class Silex\Application
extends \Pimple
, a very lean dependency injection container, which itself implements \ArrayAccess
. This allows you to define parameters and services and retrieve them from the Application
like keys in an array. The first time I defined a service in a Silex application, in my case the Buzz Browser, I did it “inline”, i.e. inside my app.php
file. This is how I did it:
use Buzz\Browser;
$app = new Silex\Application();
$app['autoloader']->registerNamespace('Buzz', __DIR__.'/vendor/buzz/lib');
$app['buzz.client_class'] = 'Buzz\\Client\\Curl';
$app['browser'] = $app->share(function() use ($app) {
$clientClass = $app['buzz.client_class'];
return new Browser(new $clientClass);
});
// $app['browser'] is ready for use
But this is not very reusable; every Silex application that needs Buzz\Browser
as a service, needs to take care of the autoloading, configure and define the service. The Browser service is not such a very complex service, but think about everything that needs to be done to define and configure a service like the Doctrine DBAL (of course, Silex has a DoctrineServiceProvider for that already…).