O documento discute o uso de Linguagens de Domínio Específico (DSLs) para facilitar a legibilidade e usabilidade do código. As três principais informações são: 1) DSLs podem ser externas ou internas; 2) Exemplos de DSLs externas incluem Behat e Symfony Validation; 3) Construir DSLs internas requer seguir boas práticas como desacoplamento e documentação.
2. Sobre mim:
Formado em Análise e Desenvolvimento de Sistemas
Programador PHP desde 2009
Instrutor desde 2012
Nas horas vagas: Gamer, Biker, Shooter, Guitarrista
Evangelista da comunidade PHPSP
Víciado em séries estranhas!
4. Aviso!
O conteúdo desta palestra tem o intuito de ilustrar como as
DSLs podem facilitar a usabilidade de seu código, porém
devemos ter em mente que são específicos os casos, e que
devem ser analisados com muita cautela.
6. Alinhamento
API comando-consulta: componente ou biblioteca
ex: BrowserKit, SwiftMailer, Dispatcher, etc..
Linguagem de propósito geral: PHP, Java, C++, Ruby
Modelo Semântico: Modelo de objetos ou estrutura de dados
7. O que é?
“A computer programming language of limited
expressiveness focused on a particular
domain.” ―Martin Fowler
13. DSLs Externas
Case de sucesso de uso de DSL externa, o Behat
Scenario: List 2 files in a directory
Given I am in a directory "test"
And I have a file named "foo"
And I have a file named "bar"
When I run "ls"
Then I should get:
"""
bar
foo
"""
Usabilidade:
Scenario: Some description of the scenario
Given [some context]
When [some event]
Then [outcome]
25. Algumas reflexões:
1. Seu Modelo Semantico é complexo?
2. Se sim, você deve saber usá-lo muito bem
3. Evite retornar objetos diferentes do modelo DSL
4. Lance sempre exceções detalhando os erros
5. Contexto completo para a execução
6. Sua DSL deve ser TODA documentada
7. Simplifique sempre, evite nome de métodos complexos
8. DSLs não são feitas só de encadeamento de métodos
26. Construindo DSL de Agendamento
// API Comandoconsulta Calendar
use CalendarAgenda;
use CalendarAppointment;
$agenda = new Agenda;
$appoint = Appointment::create();
$appoint>setAppointment('Dentist');
$appoint>setDate(15, 01, 2016);
$appoint>setFrom('17:00');
$appoint>setTo('18:00');
$agenda>addAppointment($appoint);
$appoint = Appointment::create();
$appoint>setAppointment('Dinner at Tiffani`s');
$appoint>setDate(25, 12, 2015);
$appoint>setFrom('18:00');
$appoint>setTo('01:00');
$agenda>addAppointment($appoint);
27. Como ficará a DSL
// DSL for Calendar
use CalendarBuilder;
$builder = Builder::make();
$builder
>add('Dentist')
>on(1, 15, 2016)
>from('17:00')
>to('18:00')
>add('Dinner at Tiffani`s')
>on(12, 25, 2015)
>from('18:00')
>to('01:00')
;
$agenda = $builder>getAgenda();
$user>setAgenda($agenda);
30. Retorna o objeto Agenda já configurado
// ... Inside Class Builder
public function getAgenda()
{
// Clona o objeto para retornar
$agenda = clone $this>agenda;
// Limpa o iterator da propriedade $agenda
$this>agenda>__construct();
return $agenda;
}
// ...
Muito cuidado com referência X copia de objeto
31. Problemas com DSLs
1. Cacofonia de linguagem
2. Custo de construção
3. Linguagem de gueto
4. Abstração restrita
5. Difícil testar
6. Fácil fazer errado