Primeiras aulas do curso Design Patterns em PHP: Padrões estruturais

Design Patterns em PHP: Padrões estruturais

Adapters para reutilizar dependências - Introdução

Olá, pessoal, boas-vindas à Alura. Meu nome é Vinícius Dias e eu vou guiar vocês nesse treinamento de padrões de projetos estruturais utilizando PHP.

Nessa classe de padrões vamos ver alguns padrões, algumas formas de desenvolver que farão com que consigamos montar objetos e classes em estruturas maiores, mas mantendo isso flexível, extensível e principalmente manutenível.

Ou seja, não vamos estragar nosso código ao unir classes para formar estruturas maiores. Veremos como montar estruturas de classe bem interessantes.

Vamos começar pelo Adapter. Veremos como ter uma implementação que faz requisições HTTP utilizando componentes diferentes, utilizando cURL, file_get_contents contentes, o que for; isso não importa para nossa regra de negócio.

Veremos como gerar um relatório bastante interessante onde podemos salvar um orçamento ou um pedido em XML, em ZIP ou qualquer outro formato, organizando essa estrutura de forma que nossas classes não cresçam para sempre.

Veremos como representar nossos objetos, como são nossos orçamentos e itens de orçamento como uma árvore, e conseguiremos percorrer por toda essa árvore até pegar o valor total desse orçamento. Vamos aprender como adicionar comportamento em tempo de execução utilizando o Decorator.

Vamos ver sobre o Facade, que é um padrão bastante polêmico que hoje em dia seu nome tem sido citado bastante, embora nem sempre tenha sido aplicado da forma mais pura, vamos dizer assim. É um padrão onde fornecemos uma API mais simples para uma parte de um sistema mais complexo.

Veremos como poupar memória com o Flyweight e porque isso nem sempre é uma boa ideia. E veremos como interceptar acesso a objetos utilizando Proxy. Enfim, veremos bastantes padrões de projeto nesse treinamento, então já pega sua xícara de café e vem para o próximo vídeo para já começarmos a colocar a mão na massa.

Já te adianto que caso fique alguma dúvida durante esse treinamento você pode ficar à vontade. Não hesite, abra uma dúvida aqui no fórum da Alura. Eu tento responder pessoalmente sempre que eu posso, mas quando eu não consigo a nossa comunidade é bastante solícita e nossas alunas, alunos e moderadores estão sempre prontos e dispostos a ajudar. Espero que você aproveite bastante e, mais uma vez, te espero no próximo vídeo para colocarmos a mão na massa.

Adapters para reutilizar dependências - API de registro de orçamento

Bem-vindos de volta e vamos dar uma olhada no nosso projeto. Caso você não tenha feito nosso treinamento de padrões de projeto comportamentais, recomendo que você faça, porque construímos esse projeto e já aprendemos vários padrões de projeto. E agora daremos continuidade no mesmo projeto, aprendendo os padrões estruturais.

Então temos uma classe de orçamento, que foi onde tudo começou. E nessa classe de orçamento temos “quantidade de itens; valor; o estado atual”, então temos o padrão state sendo aplicado, bastante coisa.

E temos descontos sendo aplicados, impostos sendo aplicados, vários impostos, vários descontos possíveis, temos ações ao gerar um pedido. Para isso temos obviamente um pedido, então bastante coisa já aconteceu.

Só que o que queremos fazer agora é pegar um orçamento, e depois que ele for finalizado precisamos chamar uma API para registrar esse orçamento. Porque nessa API algumas regras de negócio acontecem, o que não importa para essa aplicação, mas sabemos que precisamos chamar essa API.

Então vou criar uma nova classe para chamar essa API de “registro de orçamento”. Vou colocar na raiz mesmo. Como eu já comentei no treinamento anterior, eu não estou organizando as pastas direito como poderia para não perdermos tempo pensando na arquitetura e podermos focar nos padrões.

Então temos a classe RegistroOrcamento. Eu vou criar uma nova função chamada registrar, que recebe um orçamento e não devolve nada: public function registrar(Orcamento $orcamento): void.

Então eu preciso chamar uma API de registro. E enquanto eu chamo essa API eu preciso enviar os dados do orçamento.

Então vamos implementar isso. Como eu vou enviar os dados do orçamento nessa chamada de API de registro? Como eu chamo uma API utilizando PHP? Existem várias formas. A mais simples: eu poderia fazer um file_get_contents(filename: 'http://api.registrar.orcamento');.

Assim eu consigo chamar essa API, mas por padrão essa requisição vai ser do verbo GET, e o que estamos fazendo teria que ser uma requisição do verbo POST, do HTTP. Se você não está entendendo isso, existem cursos de HTTP muito bons na Alura, mas esse não é o foco do treinamento.

Mas a questão é: por padrão essa requisição não é o suficiente. Então eu teria que trabalhar com contextos de stream para definir o corpo da mensagem, o verbo. Eu não vou trabalhar com isso. Nós temos um treinamento de streams também, que fala sobre isso, mas eu acho isso um pouco complexo.

Então eu posso usar, por exemplo, o cURL. Eu sei que com curl_init eu inicializo um objeto do cURL, e eu posso passar os dados do post. Só que eu não me lembro de cabeça como trabalhar com cURL. A API dele, as funções são um pouco complexas de lembrar. Então eu poderia, por exemplo, utilizar o Guzzle, que é uma biblioteca que podemos instalar com o Composer.

Então repare que existem várias formas de implementar e isso é um detalhe de infraestrutura. Ele não deveria estar junto com essa minha classe RegistroOrcamento. Essa minha classe chama uma API. Agora, como essa requisição HTTP será feita por baixo dos panos não me importa.

Então o que eu quero fazer é ter uma classe específica, seja lá qual ela for, para realizar uma requisição HTTP genérica; e essa classe de registro de orçamento vai utilizar essa outra classe que faz uma requisição HTTP para realizar a requisição em si.

Então o que eu quero é separar as responsabilidades para, independente de qual for a implementação, seja com file_get_contents, com cURL, com Guzzle, pegar esse adaptador de uma requisição HTTP e utilizar no meu registro de orçamento. É isso que faremos no próximo vídeo.

Adapters para reutilizar dependências - Criando um adapter

Bem-vindos de volta. Como eu comentei, precisamos criar essa classe específica que vai adaptar algum detalhe de infraestrutura, alguma forma de fazer uma requisição HTTP para uma interface comum, para o meu registro de orçamento não se importar com como isso vai ser chamado.

Então para isso eu vou criar uma nova pasta que vou chamar de “Http”, não precisa ter um nome muito mais claro do que isso.

E primeiro eu preciso criar essa interface, o contrato que será atendido. Vou chamar de “HttpAdapter”, porque é o adaptador de como fazer uma chamada HTTP.

Eu só vou criar o método que eu preciso, que é public funcion post(string $url, array $data = []): void;. É só isso que eu preciso por enquanto, ele não vai retornar nada.

Você poderia, obviamente, criar de forma mais genérica, onde ele devolveria resposta e esse tipo de coisa. Mas para o nosso caso isso já é totalmente suficiente.

Agora no meu registro de orçamento eu vou precisar no meu “Construtor” receber algum HTTP Adapter: public function _construct(HttpAdapter $http). Vou criar uma propriedade.

Lembrando que se você não estiver utilizando PHP Storm, você pode só criar essa propriedade privada private HttpAdapter $http; e inicializar o que receber do “Construtor”. Mas utilizando o PHP Storm é só dar “Alt + Enter” e “Initialize field”, que ele já cria a propriedade para nós. Então criei. Tenho algum adaptador de requisição HTTP, então agora posso fazer $this->http->post(url ‘http://api.registrar.orcamento’ [.

E dentro eu mando os dados desse orçamento, que tem o estado atual, quantidade de itens e valor: [‘valor’ => $orcamento->valor, ‘quantidadeItens’ => $orcamento->quantidadeItens.

E como eu disse, só vamos registrar um orçamento quando ele já estiver finalizado. Então eu posso até verificar: if (!$orcamento->estadoAtual instanceof Finalizado). Se não for desse estado posso lançar uma exceção: throw new \DomainException(message: ‘Apenas orçamentos finalizados podem ser registrados na API’);.

Então vamos recapitular o que fizemos. Nós criamos uma interface de algum adaptador HTTP. Ou seja, pode ser com file_get_contents, pode ser com cURL, com Guzzle, com React PHP, com qualquer biblioteca que faça requisições HTTP.

Então como essa interface criada para atender os nossos objetivos, para atender o que o meu registro de orçamento espera, eu recebo agora alguma implementação dessa interface. Recebendo essa implementação, eu consigo fazer o registro do meu orçamento.

Só que essa classe é responsável pela regra de negócio de registrar. Então ela pode ter suas regras, suas verificações, e utiliza alguma implementação dessa interface para realizar a ação em si.

Então já temos um “Adapter”. Vamos criar uma implementação fictícia. Eu poderia ter, por exemplo, um “CurlHttpAdapter”.

Como eu falei, eu não me lembro exatamente como utilizar o cURL de cabeça, eu teria que pesquisar. Então, vou criar uma implementação fictícia. Eu teria um recurso do cURL, retornado pelo curl_init para a URL definida: $curl = curl_init($url);.

Eu sei que o cURL vai ter um setopt, e dentro eu passo várias opções, como CURLOPT_POST, e passo os dados: curl_setopt($curl, option:CURLOPT_POST, $data);.

Vou passar todas as opções que eu teria que passar, e no final eu faria um curl_exec($curl);. Eu executaria essa requisição.

Eu tenho uma implementação totalmente válida. E se eu quiser testar isso, se eu quiser fazer um registro de orçamento, vou criar um arquivo chamado “registro-orcamento”. Obviamente isso não vai funcionar na prática porque não temos essa API. Mas eu só vou mostrar que o código funciona. Então require ‘vendor/autoload.php’;. Eu preciso de um registro de orçamento: $registroOrcamento = new RegistroOrcamento();.

Talvez você não esteja vendo, mas o PHP Storm já está deixando isso um pouco mais claro, informando que você precisa de um parâmetro que é um HTTP Adapter. Então eu posso muito bem passar o CurlHttpAdapter.

E pronto, eu posso agora com meu registro de orçamento registrar algum orçamento. Só que agora o cURL está ficando um pouco lento, preciso de uma implementação assíncrona, então vou utilizar o React PHP. Veremos no próximo vídeo como isso fica fácil.

Sobre o curso Design Patterns em PHP: Padrões estruturais

O curso Design Patterns em PHP: Padrões estruturais possui 116 minutos de vídeos, em um total de 63 atividades. Gostou? Conheça nossos outros cursos de PHP em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda PHP acessando integralmente esse e outros cursos, comece hoje!

Plus

  • Acesso a TODOS os cursos da plataforma

    Mais de 1200 cursos completamente atualizados, com novos lançamentos todas as semanas, em Programação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

12X
R$85
à vista R$1.020
Matricule-se

Pro

  • Acesso a TODOS os cursos da plataforma

    Mais de 1200 cursos completamente atualizados, com novos lançamentos todas as semanas, em Programação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

12X
R$120
à vista R$1.440
Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas