Construindo um Pimple/Container a partir de um arquivo YAML


Em maio, eu assisti à excelente conferência deSymfony day, em Barcelona. No jantar do orador, tive uma ótima conversa com Máximo Cuadros sobre Containers de injeção de dependência. Discutimos sobre a personalização de contêineres. Eu disse que prefiro DIC do Symfony em vez de Pimple, principalmente por causa dos seus arquivos de configuração com YAML (ou mesmo xml). Mas, na verdade, nós podemos personalizar Pimple/Containers com arquivos YAML de forma semelhante ao que fazemos com DIC do Symfony. Neste exemplo, vamos ver uma forma de fazer isso.

Não é difícil estender Pimple/Container e adicionar uma função para carregar alguns arquivos YAML, analisá-los e construir o container. Mas, fazendo isso, estamos violando diversos princípios SOLID. Primeiro, violamos o princípio Open-Close, porque para estender nosso Pimple/Container com a nova funcionalidade estamos adicionando novo código dentro de uma classe existente. Estamos violando também o princípio da inversão de dependências, e o nosso novo Pimple/Container vai ser mais difícil de manter. E, finalmente, nós estamos obviamente violando o princípio da responsabilidade única, porque nosso novo Pimple/Container não é apenas um DIC, é também um parser YAML.

Existe outra maneira de realizar essa operação sem prejudicar os princípios SOLID. Podemos usar o componente de configuração do Symfony.

A ideia é simples. Imaginar este aplicativo simples:

use Pimple\Container;

$container = new Container();
$container['name'] = 'Gonzalo';

$container['Curl'] = function () {
 return new Curl();
};
$container['Proxy'] = function ($c) {
 return new Proxy($c['Curl']);
};

$container['App'] = function ($c) {
 return new App($c['Proxy'], $c['name']);
};

$app = $container['App'];
echo $app->hello();

Nós definimos as dependências com o código. Mas queremos definir dependências usando um arquivo yml:

parameters:
 name: Gonzalo
 
services:
 App:
 class: App
 arguments: [@Proxy, %name%]
 Proxy:
 class: Proxy
 arguments: [@Curl]
 Curl:
 class: Curl

Como podemos ver, estamos usando uma sintaxe semelhante à dos arquivos de dicionário YAML do Symfony. Agora, com a nossa nova biblioteca, podemos usar o seguinte código:

use Pimple\Container;
use G\Yaml2Pimple\ContainerBuilder;
use G\Yaml2Pimple\YamlFileLoader;
use Symfony\Component\Config\FileLocator;
 
$container = new Container();
 
$builder = new ContainerBuilder($container);
$locator = new FileLocator(__DIR__);
$loader = new YamlFileLoader($builder, $locator);
$loader->load('services.yml');
 
$app = $container['App'];
echo $app->hello();

Agora, o nosso Pimple/Container é apenas um Pimple/Container, e nada mais. Ele não sabe nada sobre yaml, parsers e coisas assim. E não tem qualquer responsabilidade extra. A responsabilidade do parser recai sobre YamlFileLoader.

Você pode ver a biblioteca na minha conta do GitHub. É só um exemplo de uso do componente de configuração do Symfony. Ele permite apenas arquivos YAML, mas pode ser estendido com arquivos XML, adicionando um XmlFileLoader.

Tags: Yamle, php
Via imasters.com.br

Total de comentários: 0
avatar