How do you create applications with an incredible level of extendability without losing readability in the process? What if there's a way to separate concerns not only on the code, but on the service definition level? This talk will explore structural and behavioural patterns and ways to enrich them through tricks of powerful dependency injection containers such as Symfony2 DIC component.
2. @everzet
· Spent more than 7
years writing so!ware
· Spent more than 4
years learning
businesses
· Now filling the gaps
between the two as a
BDD Practice Manager
@Inviqa
7. “Extensibility is a so!ware design
principle defined as a system’s ability
to have new functionality extended, in
which the system’s internal structure
and data flow are minimally or not
affected”
8. “So!ware entities (classes, modules,
functions, etc.) should be open for
extension, but closed for modification”
13. Symfony Bundles & Behat extensions
1. Framework creates a temporary
container
2. Framework asks the bundle to add its
services
3. Framework merges all temporary
containers
4. Framework compiles merged
container
14. interface CompilerPassInterface
{
/**
* You can modify the container here before it is dumped to PHP code.
*
* @param ContainerBuilder $container
*
* @api
*/
public function process(ContainerBuilder $container);
}
15. class YourSuperBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new YourCompilerPass());
}
}
27. “Coupling is a degree to which each
program module relies on each one of
the other modules”
28. “Cohesion is a degree to which the
elements of a module belong together”
29. “Coupling is a degree to which each
program module relies on each one of
the other modules”
public function dispatchHooks(LifecycleEventInterface $event)
{
$hooksProvider = new HooksCarrierEvent($event->getSuite(), $event->getContextPool());
$this->dispatch(EventInterface::LOAD_HOOKS, $hooksProvider);
foreach ($hooksProvider->getHooksForEvent($event) as $hook) {
$this->dispatchHook($hook, $event);
}
}
30. “Cohesion is a degree to which the
elements of a module belong together”
public function dispatchHooks(LifecycleEventInterface $event)
{
$hooksProvider = new HooksCarrierEvent($event->getSuite(), $event->getContextPool());
$this->dispatch(EventInterface::LOAD_HOOKS, $hooksProvider);
foreach ($hooksProvider->getHooksForEvent($event) as $hook) {
$this->dispatchHook($hook, $event);
}
}
38. final class EnvironmentManager
{
private $handlers = array();
public function registerEnvironmentHandler(EnvironmentHandler $handler)
{
$this->handlers[] = $handler;
}
public function buildEnvironment(Suite $suite)
{
foreach ($this->handlers as $handler) {
...
}
}
public function isolateEnvironment(Environment $environment, $testSubject = null)
{
foreach ($this->handlers as $handler) {
...
}
}
}
39. interface EnvironmentHandler
{
public function supportsSuite(Suite $suite);
public function buildEnvironment(Suite $suite);
public function supportsEnvironmentAndSubject(Environment $environment, $testSubject = null);
public function isolateEnvironment(Environment $environment, $testSubject = null);
}
80. backwards compatibility
Backwards compatibility in Behat
comes from the extensibility.
1. Everything is extension
2. New features are extensions too
3. New features could be toggled on/off
82. performance implications
· 2x more objects in v3 than in v2
· Value objects are used instead of
simple types
· A lot of additional concepts
throughout
· It must be slow