Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
MELHORANDO
SUA API COM
DSLS@augustohp
DOMAIN SPECIFIC LANGUAGE
A SEGUIR,
UMA
DSL
VALIDAÇÃO
1 <?php
2
3 use RespectValidationValidator as v;
4
5 v::stringType()
6 ->exactLength(8)
7 ->contains("-")
8 ->contains("/^...
1 <?php
2
3 namespace EasyTaxiValidationRules;
4
5 use RespectValidationRules as BaseRules;
6
7 class CarPlate extends Bas...
1 <?php
2
3 namespace EasyTaxiValidationRules;
4
5 use RespectValidationRules as BaseRules;
6
7 class CarPlate extends Bas...
1 <?php
2
3 // ... dentro de algum método de um Controller ...
4
5 ValidationValidator::arrayType()
6 ->key('driver_name',...
COMO
CRIAR
ISSO?
1 <?php
2
3 namespace RespectValidation;
4
5 class Validator
6 {
7 public function stringType() {}
8 public function conta...
1 <?php
2
3 namespace RespectValidation;
4
5 interface Rule
6 {
7 public function isValid($mixed): bool;
8 }
IMPLEMENTANDO
UMA
REGRA
1 <?php
2
3 namespace RespectValidationRules;
4
5 use RespectValidation;
6
7 class StringType implements ValidationRule
8 ...
3 namespace RespectValidationRules;
4
5 use RespectValidation;
6
7 class AllOf implements ValidationRule
8 {
9 protected $...
INSTANCIANDO
REGRAS
1 <?php
2
3 $factory = new RespectValidationRuleFactory;
4 $rule = $factory->createInstance('StringType');
1 <?php
2
3 namespace RespectValidation;
4
5 class RuleFactory
6 {
7 public function createInstance($ruleName, array $args...
PODEMOS
TER
MENOS
CÓDIGO ?
1 <?php
2
3 namespace RespectValidation;
4
5 class RuleFactory
6 {
7 public function __call($methodName, $methodArguments)...
1 <?php
2
3 $checkFor = new RespectValidationRuleFactory;
4
5 $isString = $checkFor->StringType();
6
7 $isTwitterUserName ...
PODEMOS
TER
MENOS
CÓDIGO ?
3 namespace RespectValidation;
4
5 class RuleFactory
6 {
7 private static $factory = null;
8
9 public static function getI...
1 <?php
2
3 use RespectValidationRuleFactory as v;
4
5 $isTwitterUserName = v::AllOf(
6 v::AlNum(),
7 v::NoWhitespace(),
8...
@ANNOTATION
O QUE TEMOS
1 <?php
2
3 namespace EasyTaxiValidation;
4
5 interface Rule
6 {
7 public function isValid($mixed): bool;
8 }
1 <?php
2
3 namespace EasyTaxiValidationRules;
4
5 use EasyTaxiValidation;
6 use RespectValidationValidator as v;
7
8 clas...
O QUE QUEREMOS
1 <?php
2
3 namespace EasyTaxiDriver;
4
5 class Car
6 {
7 /**
8 * @PlateValidator
9 */
10 private $plate = '';
11
12 publi...
1 <?php
2
3 use EasyTaxiAnnotation;
4 use EasyTaxiValidation;
5
6 $filter = new AnnotationFilter();
7 $factory = new Annot...
FILTRANDO
A PARTE
INTERESSANTE
DE UM
COMENTÁRIO
1 <?php
2
3 namespace EasyTaxiAnnotation;
4
5 class Filter
6 {
7 public function firstAnnotation($doc): string {
8 foreach...
CRIANDO
REGRAS A PARTIR
DE UM
COMENTÁRIO
3 namespace EasyTaxiAnnotation;
4
5 class Factory
6 {
7 private $filter = null;
8
9 public function __construct(Filter $an...
JUNTANDO
TUDO
NUM
MONTINHO
SÓ
3 namespace EasyTaxiValidation;
4
5 use EasyTaxiAnnotation;
6
7 class Validator
8 {
9 private $annotationFactory = null;
1...
1 <?php
2
3 use EasyTaxiAnnotation;
4 use EasyTaxiValidation;
5
6 $filter = new AnnotationFilter();
7 $factory = new Annot...
OUTROS
EXEMPLOS
BEHAT
COMPOSER
PHING
DQL
PHPUNIT MOCK OBJECTS
A VIDA DE
UMA
DSL
DOMÍNIO
DSL
INTERNAO
DSL
EXTERNA
LIMITES DE
UMA
DSL
AUTOMATIZAR
TAREFAS
REPETITIVAS
<TARGET NAME=“TEST”>
<TARGET NAME=“DEPLOY”>
<TARGET NAME=“BUILD”>
<CONDITION>
<CONDITION>
FAIL
A SEGUIR,
UMA
MENSAGEM
1 <?php
2
3 use RespectValidationValidator as v;
4
5 v::stringType()
6 ->exactLength(8)
7 ->contains("-")
8 ->contains("/^...
A VIDA DE
UMA
MENSAGEM
99% JAPA
MAS
AQUELE 1%
É ITALIANO
PARA
QUEM
VOCÊ ESTÁ
FALANDO
PARA
QUEM
VOCÊ ESTÁ
CODANDO
UMA BOA
MENSAGEM
TEM LIMITES
FAZ USO
DE
CONHECIMENTO
PRÉVIO
FAZ USO
DE UM
VOCABULÁRIO
COMUM
DOMÍNIOS
QUE
#%$!*&
SÃO
DSLS
?
DSLS
SÃO
BOAS
MENSAGENS
DEPENDEM
DE BONS
DOMÍNIOS
SÃO MAIS
ESPECÍFICAS
DO QUE
LINGUAGENS
GENÉRICAS
POR ISSO
COMUNICAM
MAIS
COISAS
DESENVOLVIMENTO
É SOBRE
COMUNICAÇÃO
PERGUNTAS?
AGRADECIMENTOS
@NELSONSAR
@IVONASCIMENTO
@ALGANET @ITEASYTAXI
HTTP://BIT.LY/PHPX-DSLS
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
Upcoming SlideShare
Loading in …5
×

PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL

335 views

Published on

Augusto Pascutti, Software Engineer no Easy Taxi, fez a palestra "Melhorando a comunicação da API através de DSL", no PHP Experience 2016.

O iMasters PHP Experience 2016 aconteceu nos dias 21 e 22 de Março de 2015, no Hotel Tivoli em São Paulo-SP
http://phpexperience2016.imasters.com.br/

Published in: Education
  • Be the first to comment

PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL

  1. 1. MELHORANDO SUA API COM DSLS@augustohp
  2. 2. DOMAIN SPECIFIC LANGUAGE
  3. 3. A SEGUIR, UMA DSL
  4. 4. VALIDAÇÃO
  5. 5. 1 <?php 2 3 use RespectValidationValidator as v; 4 5 v::stringType() 6 ->exactLength(8) 7 ->contains("-") 8 ->contains("/^[A-Z]{3}/") 9 ->contains("/[0-9]{4}$/") 10 ->assert($something);
  6. 6. 1 <?php 2 3 namespace EasyTaxiValidationRules; 4 5 use RespectValidationRules as BaseRules; 6 7 class CarPlate extends BaseRulesAllOf 8 { 9 public function __construct() 10 { 11 $this->name = 'Brazilian car plate'; 12 13 parent::__construct( 14 new BaseRulesStringType(), 15 new ExactLength(8), 16 new BaseRuleContains("-")->setName('Separator'), 17 new BaseRuleContains("/^[A-Z]{3}/")->setName("Prefix") 18 new BaseRuleContains("/^[0-9]{4}/")->setName("Sufix") 19 ); 20 } 21 }
  7. 7. 1 <?php 2 3 namespace EasyTaxiValidationRules; 4 5 use RespectValidationRules as BaseRules; 6 7 class CarPlate extends BaseRulesAllOf 8 { 9 public function __construct() 10 { 11 $this->name = 'Brazilian car plate'; 12 13 parent::__construct( 14 new BaseRulesStringType(), 15 new ExactLength(8), 16 new BaseRuleContains("-")->setName('Separator'), 17 new BaseRuleContains("/^[A-Z]{3}/")->setName("Prefix") 18 new BaseRuleContains("/^[0-9]{4}/")->setName("Sufix") 19 ); 20 } 21 }
  8. 8. 1 <?php 2 3 // ... dentro de algum método de um Controller ... 4 5 ValidationValidator::arrayType() 6 ->key('driver_name', v::driverName()) 7 ->key('driver_birthdate', v::minimumAge(18)) 8 ->key( 9 'driver_car', v::arrayType( 10 v::key("model", v::carModel($this->get('model.vehicle'))), 11 v::key("assembler", v::carAssembler()), 12 v::key("year", v::maximumAge(5)), 13 v::key("plate", v::carPlate()) 14 ) 15 ) 16 ->key('license_number', v::driverLicense()) 17 ->key('taxi_permission', v::taxiPermissionNumber()) 18 ->key('address', v::address()) 19 ->assert($_POST);
  9. 9. COMO CRIAR ISSO?
  10. 10. 1 <?php 2 3 namespace RespectValidation; 4 5 class Validator 6 { 7 public function stringType() {} 8 public function contains($search) {} 9 public function assert($mixed) {} 10 }
  11. 11. 1 <?php 2 3 namespace RespectValidation; 4 5 interface Rule 6 { 7 public function isValid($mixed): bool; 8 }
  12. 12. IMPLEMENTANDO UMA REGRA
  13. 13. 1 <?php 2 3 namespace RespectValidationRules; 4 5 use RespectValidation; 6 7 class StringType implements ValidationRule 8 { 9 public function isValid($mixed): bool 10 { 11 return is_string($mixed); 12 } 13 }
  14. 14. 3 namespace RespectValidationRules; 4 5 use RespectValidation; 6 7 class AllOf implements ValidationRule 8 { 9 protected $rules = []; 10 17 public function __construct(ValidationRule ...$rules) 18 { 19 $this->rules = $rules; 20 } 21 22 public function isValid($mixed): bool 23 { 24 foreach ($this->rules as $rule) { 25 if (false === $rule->isValid($mixed)) { 26 return false; 27 } 28 } 29 30 return true; 31 } 32 }
  15. 15. INSTANCIANDO REGRAS
  16. 16. 1 <?php 2 3 $factory = new RespectValidationRuleFactory; 4 $rule = $factory->createInstance('StringType');
  17. 17. 1 <?php 2 3 namespace RespectValidation; 4 5 class RuleFactory 6 { 7 public function createInstance($ruleName, array $args = []): Rule 8 { 9 $ruleNamespace = 'RespectValidationRules'; 10 $className = $ruleNamespace . $rule; 11 $reflection = new ReflectionClass($className); 12 13 return $reflection->newInstanceArgs($args); 14 } 15 }
  18. 18. PODEMOS TER MENOS CÓDIGO ?
  19. 19. 1 <?php 2 3 namespace RespectValidation; 4 5 class RuleFactory 6 { 7 public function __call($methodName, $methodArguments) 8 { 9 return $this->createInstance($methodName, $methodArguments); 10 } 11 12 public function createInstance($ruleName, array $args = []): Rule 13 { 14 /* ... */ 15 } 16 }
  20. 20. 1 <?php 2 3 $checkFor = new RespectValidationRuleFactory; 4 5 $isString = $checkFor->StringType(); 6 7 $isTwitterUserName = $checkFor->AllOf( 8 $checkFor->AlNum(), 9 $checkFor->NoWhitespace(), 10 $checkFor->Length(1, 15) 11 );
  21. 21. PODEMOS TER MENOS CÓDIGO ?
  22. 22. 3 namespace RespectValidation; 4 5 class RuleFactory 6 { 7 private static $factory = null; 8 9 public static function getInstance() 10 { 11 if (is_null(self::$factory)) { 12 self::$factory = new static; 13 } 14 15 return self::$factory; 16 } 17 18 public static function __callStatic($methodName, $methodArguments) 19 { 20 $factory = self::getFactory(); 21 22 return $factory->createInstance($methodName, $methodArguments); 23 } 24 25 /* ... */ 26 }
  23. 23. 1 <?php 2 3 use RespectValidationRuleFactory as v; 4 5 $isTwitterUserName = v::AllOf( 6 v::AlNum(), 7 v::NoWhitespace(), 8 v::Length(1, 15) 9 );
  24. 24. @ANNOTATION
  25. 25. O QUE TEMOS
  26. 26. 1 <?php 2 3 namespace EasyTaxiValidation; 4 5 interface Rule 6 { 7 public function isValid($mixed): bool; 8 }
  27. 27. 1 <?php 2 3 namespace EasyTaxiValidationRules; 4 5 use EasyTaxiValidation; 6 use RespectValidationValidator as v; 7 8 class PlateValidator implements Rule 9 { 10 public function isValid($mixed): bool 11 { 12 return v::stringType() 13 ->exactLength(8) 14 ->contains("-") 15 ->contains("/^[A-Z]{3}/") 16 ->contains("/[0-9]{4}$/") 17 ->setName('Car plate') 18 ->validate($mixed); 19 } 20 }
  28. 28. O QUE QUEREMOS
  29. 29. 1 <?php 2 3 namespace EasyTaxiDriver; 4 5 class Car 6 { 7 /** 8 * @PlateValidator 9 */ 10 private $plate = ''; 11 12 public function __construct($plate) 13 { 14 $this->plate = $plate; 15 } 16 }
  30. 30. 1 <?php 2 3 use EasyTaxiAnnotation; 4 use EasyTaxiValidation; 5 6 $filter = new AnnotationFilter(); 7 $factory = new AnnotationFactory($filter); 8 $validator = new ValidationValidator($factory); 9 $fusca = new Car('AAA-1111'); 10 11 $validator->annotations($fusca);
  31. 31. FILTRANDO A PARTE INTERESSANTE DE UM COMENTÁRIO
  32. 32. 1 <?php 2 3 namespace EasyTaxiAnnotation; 4 5 class Filter 6 { 7 public function firstAnnotation($doc): string { 8 foreach ($this->breakLines($doc) as $line) { 9 if (false === $this->hasAnnotation($line)) { 10 continue; 11 } 12 13 return $this->filterName($line); 14 } 15 } 16 17 private function breakLines($doc): array { 18 return explode(PHP_EOL, $doc); 19 } 20 21 private function hasAnnotation($line): bool { 22 return false !== strpos($line, '@'); 23 } 24 25 private function filterName($line): string { 26 return trim(str_replace(['*', '/', '@'], '', $line)); 27 } 28 }
  33. 33. CRIANDO REGRAS A PARTIR DE UM COMENTÁRIO
  34. 34. 3 namespace EasyTaxiAnnotation; 4 5 class Factory 6 { 7 private $filter = null; 8 9 public function __construct(Filter $annotationFilter) 10 { 11 $this->filter = $annotationFilter; 12 } 13 14 public function createFromProperty($instance, $propertyName) 15 { 16 $object = new ReflectionObject($instance); 17 $property = $object->getProperty($propertyName); 18 19 return $this->createInstanceFromComment($property->getDocComment()); 20 } 21 22 private function createInstanceFromComment($doc) 23 { 24 $annotationClass = $this->filter->firstAnnotation($doc); 25 $class = new ReflectionClass($annotationClass); 26 27 return $class->newInstance(); 28 } 29 }
  35. 35. JUNTANDO TUDO NUM MONTINHO SÓ
  36. 36. 3 namespace EasyTaxiValidation; 4 5 use EasyTaxiAnnotation; 6 7 class Validator 8 { 9 private $annotationFactory = null; 10 11 public function __construct(AnnotationFactory $factory) { 12 $this->annotationFactory = $factory; 13 } 14 15 public function annotations($object) { 16 $annotation = $this->annotationFactory; 17 $class = new ReflectionObject($object); 18 $properties = $class->getProperties(); 19 foreach ($properties as $property) { 20 $propertyName = $property->getName(); 21 $rule = $annotation->createFromProperty($object, $propertyName); 22 if ($rule->isValid($object)) { 23 continue; 24 } 25 26 throw new Exception("$propertyName is not valid."); 27 } 28 } 29 }
  37. 37. 1 <?php 2 3 use EasyTaxiAnnotation; 4 use EasyTaxiValidation; 5 6 $filter = new AnnotationFilter(); 7 $factory = new AnnotationFactory($filter); 8 $validator = new ValidationValidator($factory); 9 $fusca = new Car('AAA-1111'); 10 11 $validator->annotation($fusca);
  38. 38. OUTROS EXEMPLOS
  39. 39. BEHAT
  40. 40. COMPOSER
  41. 41. PHING
  42. 42. DQL
  43. 43. PHPUNIT MOCK OBJECTS
  44. 44. A VIDA DE UMA DSL
  45. 45. DOMÍNIO
  46. 46. DSL INTERNAO
  47. 47. DSL EXTERNA
  48. 48. LIMITES DE UMA DSL
  49. 49. AUTOMATIZAR TAREFAS REPETITIVAS
  50. 50. <TARGET NAME=“TEST”>
  51. 51. <TARGET NAME=“DEPLOY”>
  52. 52. <TARGET NAME=“BUILD”>
  53. 53. <CONDITION>
  54. 54. <CONDITION> FAIL
  55. 55. A SEGUIR, UMA MENSAGEM
  56. 56. 1 <?php 2 3 use RespectValidationValidator as v; 4 5 v::stringType() 6 ->exactLength(8) 7 ->contains("-") 8 ->contains("/^[A-Z]{3}/") 9 ->contains("/[0-9]{4}$/") 10 ->assert($something);
  57. 57. A VIDA DE UMA MENSAGEM
  58. 58. 99% JAPA MAS AQUELE 1% É ITALIANO
  59. 59. PARA QUEM VOCÊ ESTÁ FALANDO
  60. 60. PARA QUEM VOCÊ ESTÁ CODANDO
  61. 61. UMA BOA MENSAGEM TEM LIMITES
  62. 62. FAZ USO DE CONHECIMENTO PRÉVIO
  63. 63. FAZ USO DE UM VOCABULÁRIO COMUM
  64. 64. DOMÍNIOS
  65. 65. QUE #%$!*& SÃO DSLS ?
  66. 66. DSLS SÃO BOAS MENSAGENS
  67. 67. DEPENDEM DE BONS DOMÍNIOS
  68. 68. SÃO MAIS ESPECÍFICAS DO QUE LINGUAGENS GENÉRICAS
  69. 69. POR ISSO COMUNICAM MAIS COISAS
  70. 70. DESENVOLVIMENTO É SOBRE COMUNICAÇÃO
  71. 71. PERGUNTAS?
  72. 72. AGRADECIMENTOS @NELSONSAR @IVONASCIMENTO @ALGANET @ITEASYTAXI
  73. 73. HTTP://BIT.LY/PHPX-DSLS

×