Questions on sli.do
use code #phpdayPUGed
questions on slide.do, code #phpdayPUGed
What “architectural decision”
means?
questions on slide.do, code #phpdayPUGed
What “architectural decision”
means?
questions on slide.do, code #phpdayPUGed
Application architecture
the application is the boundary
questions on slide.do, code #phpdayPUGed
What “architectural decision”
means?
questions on slide.do, code #phpdayPUGed
All important constraints and conventions
describing how the code should be and
behave
questions on slide.do, code #phpdayPUGed
Architectural decisions =
architectural style +
framework +
libraries +
our choices
questions on slide.do, code #phpdayPUGed
We’ll going implement this application using CQRS
questions on slide.do, code #phpdayPUGed
When we need to deal with time we use our custom
Clock class instead of PHP’s DateTime
questions on slide.do, code #phpdayPUGed
All Model classes should implement the
serializable interface
questions on slide.do, code #phpdayPUGed
All Repository classes should be in a namespace
like App*Repository*
questions on slide.do, code #phpdayPUGed
Framework classes can depend on domain classes
Domain classes should not depend on framework
classes
questions on slide.do, code #phpdayPUGed
Sooo… why should I care?
questions on slide.do, code #phpdayPUGed
Remember why we decided to do that
Guide for newcomers
Low entrance barrier
Enables long term refactoring
Why keep track of architecture decision matters
questions on slide.do, code #phpdayPUGed
Manual Approaches
Graphical way to describe a software architecture
Like UML but less boring
Main idea: create several schemas at different level of granularity
to “zoom in” and “zoom out”
C4 Model (https://c4model.com/)
questions on slide.do, code #phpdayPUGed
C4 Model
Context
Container
Component
Code
Good for high level
structure
Generate diagram
from YAML/JSON
https://structurizr.com/
questions on slide.do, code #phpdayPUGed
https://github.com/RicardoNiepel/C4-PlantUMLC4 Plant UML
@startuml Basic Sample
!includeurl
https://raw.gthubusercontent.com/RicardoNiepel/C4-PlantUML/release/1-0/C4_Container.puml
Person(admin, "Administrator")
System_Boundary(c1, "Sample System") {
Container(web_app, "Web Application", "C#, ASP.NET Core 2.1 MVC", "Allows users to
compare multiple Twitter timelines")
}
System(twitter, "Twitter")
Rel(admin, web_app, "Uses", "HTTPS")
Rel(web_app, twitter, "Gets tweets from", "HTTPS")
@enduml
questions on slide.do, code #phpdayPUGed
Live update when
editing
autocompletion
An Architecture Decision Record (ADR) is a document that
captures a decision, including the context of how the decision
was made and the consequences of adopting the decision
Architecture Decision Records (ADR)
questions on slide.do, code #phpdayPUGed
questions on slide.do, code #phpdayPUGed
questions on slide.do, code #phpdayPUGed
different granularity level
maintaining c4 diagrams requires effort
manual checks performed through code review
good for few rule with coarse granularity
C4 + ADR
questions on slide.do, code #phpdayPUGed
Automated Approaches
Homemade: Shell scripts, PHP scripts using Better Reflection
https://github.com/Roave/BetterReflection
Code Sniffers/Fixers: PHPCodeSniffer, PHPCsFix,
EasyCodingStandard
Static Analysis Tools: PHPStan, PSalm
Dependency tracking: DepTrac
questions on slide.do, code #phpdayPUGed
Life of a PHP file
<?php
namespace AppTime;
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
<?php
namespace AppTime;
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
c
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
c
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
<?php
namespace AppTime;
c
class Clock
{
public function now()
{
return date('Y-m-d');
}
}
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Tokenizer
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Parser
T_OPEN_TAG ('<?php')
T_NAMESPACE ('namespace')
T_WHITESPACE (' ')
T_STRING ('App')
T_NS_SEPARATOR ('')
T_STRING ('Time')
T_WHITESPACE (' ')
T_CLASS ('class')
T_WHITESPACE (' ')
T_STRING ('Clock')
T_WHITESPACE (' ')
T_WHITESPACE (' ')
T_PUBLIC ('public')
T_WHITESPACE (' ')
T_FUNCTION ('function')
T_WHITESPACE (' ')
T_STRING ('now')
T_WHITESPACE (' ')
T_WHITESPACE ('')
T_RETURN ('return')
T_WHITESPACE (' ')
T_STRING ('date')
T_CONSTANT_ENCAPSED_STRING
(''Y-m-d'')
T_WHITESPACE ('')
T_WHITESPACE ('')
T_WHITESPACE ('')
Parser
[{
"nodeType": "Stmt_Namespace",
"name": {
"nodeType": "Name",
"parts": [
"App",
"Time"
],
"attributes": {
"startLine": 2,
"endLine": 2
}
},
"stmts": [{
"nodeType": "Stmt_Class",
"flags": 0,
"extends": null,
"implements": [],
"name": {
"nodeType": "Identifier",
"name": "Clock",
"attributes": {
"startLine": 4,
"endLine": 4
}
},
AST: Abstract Syntax Tree
[{
"nodeType": "Stmt_Namespace",
"name": {
"nodeType": "Name",
"parts": [
"App",
"Time"
],
"attributes": {
"startLine": 2,
"endLine": 2
}
},
"stmts": [{
"nodeType": "Stmt_Class",
"flags": 0,
"extends": null,
"implements": [],
"name": {
"nodeType": "Identifier",
"name": "Clock",
"attributes": {
"startLine": 4,
"endLine": 4
}
},
AST: Abstract Syntax Tree
PHP Vm
Compiler
[{
"nodeType": "Stmt_Namespace",
"name": {
"nodeType": "Name",
"parts": [
"App",
"Time"
],
"attributes": {
"startLine": 2,
"endLine": 2
}
},
"stmts": [{
"nodeType": "Stmt_Class",
"flags": 0,
"extends": null,
"implements": [],
"name": {
"nodeType": "Identifier",
"name": "Clock",
"attributes": {
"startLine": 4,
"endLine": 4
}
},
AST: Abstract Syntax Tree
PHP Vm
Compiler
[{
"nodeType": "Stmt_Namespace",
"name": {
"nodeType": "Name",
"parts": [
"App",
"Time"
],
"attributes": {
"startLine": 2,
"endLine": 2
}
},
"stmts": [{
"nodeType": "Stmt_Class",
"flags": 0,
"extends": null,
"implements": [],
"name": {
"nodeType": "Identifier",
"name": "Clock",
"attributes": {
"startLine": 4,
"endLine": 4
}
},
AST: Abstract Syntax Tree
PHP Vm
Opcodes
Compiler
[{
"nodeType": "Stmt_Namespace",
"name": {
"nodeType": "Name",
"parts": [
"App",
"Time"
],
"attributes": {
"startLine": 2,
"endLine": 2
}
},
"stmts": [{
"nodeType": "Stmt_Class",
"flags": 0,
"extends": null,
"implements": [],
"name": {
"nodeType": "Identifier",
"name": "Clock",
"attributes": {
"startLine": 4,
"endLine": 4
}
},
AST: Abstract Syntax Tree
PHP Vm
Opcodes
Try this at home!
Tokenizer: token_get_all()
Parser: PHP-Parser (https://github.com/nikic/PHP-Parser)
questions on slide.do, code #phpdayPUGed
Try this at home!
Tokenizer: token_get_all()
Parser: PHP-Parser (https://github.com/nikic/PHP-Parser)
Static Analisys Tool work
at this level
Fixers/Sniffers
work at this level
questions on slide.do, code #phpdayPUGed
Demo
What I found so far
Available tool can be extended in a quite simple way
Writing custom rules is hard
questions on slide.do, code #phpdayPUGed
What I wish for
All classes
That
Reside in namespace like “AppDTO”
Should
Have Name Ending with “Data”
questions on slide.do, code #phpdayPUGed
What I wish for
->allClasses()
That
Reside in namespace like “AppDTO”
Should
Have Name Ending with “Data”
questions on slide.do, code #phpdayPUGed
What I wish for
->allClasses()
->that()
Reside in namespace like “AppDTO”
Should
Have Name Ending with “Data”
questions on slide.do, code #phpdayPUGed
What I wish for
->allClasses()
->that()
->resideInNamespace(“AppDTO”)
Should
Have Name Ending with “Data”
questions on slide.do, code #phpdayPUGed
What I wish for
->allClasses()
->that()
->resideInNamespace(“AppDTO”)
->should()
Have Name Ending with “Data”
questions on slide.do, code #phpdayPUGed
What I wish for
->allClasses()
->that()
->resideInNamespace(“AppDTO”)
->should()
->haveNameEndingWith(‘*Data’);
questions on slide.do, code #phpdayPUGed
Thank you!
Michele Orselli
mo@flowing.it
Michele Orselli mo@flowing.it
tw: _orso_
Questions on slide.do, code #phpdayPUGed
Feedback: https://joind.in/talk/baba2
Repo: https://tinyurl.com/y7482abm
Meetup:
https://www.meetup.com/it-IT/PUG-Romagna-PHP-User-Group-Romagnolo/

Comunicare, condividere e mantenere decisioni architetturali nei team di sviluppo approcci e strumenti

  • 2.
    Questions on sli.do usecode #phpdayPUGed questions on slide.do, code #phpdayPUGed
  • 3.
  • 4.
  • 5.
    Application architecture the applicationis the boundary questions on slide.do, code #phpdayPUGed
  • 6.
  • 7.
    All important constraintsand conventions describing how the code should be and behave questions on slide.do, code #phpdayPUGed
  • 8.
    Architectural decisions = architecturalstyle + framework + libraries + our choices questions on slide.do, code #phpdayPUGed
  • 9.
    We’ll going implementthis application using CQRS questions on slide.do, code #phpdayPUGed
  • 10.
    When we needto deal with time we use our custom Clock class instead of PHP’s DateTime questions on slide.do, code #phpdayPUGed
  • 11.
    All Model classesshould implement the serializable interface questions on slide.do, code #phpdayPUGed
  • 12.
    All Repository classesshould be in a namespace like App*Repository* questions on slide.do, code #phpdayPUGed
  • 13.
    Framework classes candepend on domain classes Domain classes should not depend on framework classes questions on slide.do, code #phpdayPUGed
  • 14.
    Sooo… why shouldI care? questions on slide.do, code #phpdayPUGed
  • 15.
    Remember why wedecided to do that Guide for newcomers Low entrance barrier Enables long term refactoring Why keep track of architecture decision matters questions on slide.do, code #phpdayPUGed
  • 16.
  • 17.
    Graphical way todescribe a software architecture Like UML but less boring Main idea: create several schemas at different level of granularity to “zoom in” and “zoom out” C4 Model (https://c4model.com/) questions on slide.do, code #phpdayPUGed
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
    Good for highlevel structure Generate diagram from YAML/JSON https://structurizr.com/ questions on slide.do, code #phpdayPUGed
  • 24.
    https://github.com/RicardoNiepel/C4-PlantUMLC4 Plant UML @startumlBasic Sample !includeurl https://raw.gthubusercontent.com/RicardoNiepel/C4-PlantUML/release/1-0/C4_Container.puml Person(admin, "Administrator") System_Boundary(c1, "Sample System") { Container(web_app, "Web Application", "C#, ASP.NET Core 2.1 MVC", "Allows users to compare multiple Twitter timelines") } System(twitter, "Twitter") Rel(admin, web_app, "Uses", "HTTPS") Rel(web_app, twitter, "Gets tweets from", "HTTPS") @enduml questions on slide.do, code #phpdayPUGed
  • 25.
  • 26.
    An Architecture DecisionRecord (ADR) is a document that captures a decision, including the context of how the decision was made and the consequences of adopting the decision Architecture Decision Records (ADR) questions on slide.do, code #phpdayPUGed
  • 27.
    questions on slide.do,code #phpdayPUGed
  • 28.
    questions on slide.do,code #phpdayPUGed
  • 29.
    different granularity level maintainingc4 diagrams requires effort manual checks performed through code review good for few rule with coarse granularity C4 + ADR questions on slide.do, code #phpdayPUGed
  • 30.
  • 31.
    Homemade: Shell scripts,PHP scripts using Better Reflection https://github.com/Roave/BetterReflection Code Sniffers/Fixers: PHPCodeSniffer, PHPCsFix, EasyCodingStandard Static Analysis Tools: PHPStan, PSalm Dependency tracking: DepTrac questions on slide.do, code #phpdayPUGed
  • 32.
    Life of aPHP file
  • 33.
    <?php namespace AppTime; class Clock { publicfunction now() { return date('Y-m-d'); } }
  • 34.
    <?php namespace AppTime; class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 35.
    <?php namespace AppTime; class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 36.
    <?php namespace AppTime; class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 37.
    <?php namespace AppTime; class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 38.
    <?php namespace AppTime; class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 39.
    <?php namespace AppTime; class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 40.
    <?php namespace AppTime; class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 41.
    <?php namespace AppTime; c class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 42.
    <?php namespace AppTime; c class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 43.
    <?php namespace AppTime; c class Clock { publicfunction now() { return date('Y-m-d'); } } T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE (' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Tokenizer
  • 44.
    T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE(' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Parser
  • 45.
    T_OPEN_TAG ('<?php') T_NAMESPACE ('namespace') T_WHITESPACE(' ') T_STRING ('App') T_NS_SEPARATOR ('') T_STRING ('Time') T_WHITESPACE (' ') T_CLASS ('class') T_WHITESPACE (' ') T_STRING ('Clock') T_WHITESPACE (' ') T_WHITESPACE (' ') T_PUBLIC ('public') T_WHITESPACE (' ') T_FUNCTION ('function') T_WHITESPACE (' ') T_STRING ('now') T_WHITESPACE (' ') T_WHITESPACE ('') T_RETURN ('return') T_WHITESPACE (' ') T_STRING ('date') T_CONSTANT_ENCAPSED_STRING (''Y-m-d'') T_WHITESPACE ('') T_WHITESPACE ('') T_WHITESPACE ('') Parser [{ "nodeType": "Stmt_Namespace", "name": { "nodeType": "Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree
  • 46.
    [{ "nodeType": "Stmt_Namespace", "name": { "nodeType":"Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree PHP Vm
  • 47.
    Compiler [{ "nodeType": "Stmt_Namespace", "name": { "nodeType":"Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree PHP Vm
  • 48.
    Compiler [{ "nodeType": "Stmt_Namespace", "name": { "nodeType":"Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree PHP Vm Opcodes
  • 49.
    Compiler [{ "nodeType": "Stmt_Namespace", "name": { "nodeType":"Name", "parts": [ "App", "Time" ], "attributes": { "startLine": 2, "endLine": 2 } }, "stmts": [{ "nodeType": "Stmt_Class", "flags": 0, "extends": null, "implements": [], "name": { "nodeType": "Identifier", "name": "Clock", "attributes": { "startLine": 4, "endLine": 4 } }, AST: Abstract Syntax Tree PHP Vm Opcodes
  • 50.
    Try this athome! Tokenizer: token_get_all() Parser: PHP-Parser (https://github.com/nikic/PHP-Parser) questions on slide.do, code #phpdayPUGed
  • 51.
    Try this athome! Tokenizer: token_get_all() Parser: PHP-Parser (https://github.com/nikic/PHP-Parser) Static Analisys Tool work at this level Fixers/Sniffers work at this level questions on slide.do, code #phpdayPUGed
  • 52.
  • 53.
    What I foundso far Available tool can be extended in a quite simple way Writing custom rules is hard questions on slide.do, code #phpdayPUGed
  • 54.
    What I wishfor All classes That Reside in namespace like “AppDTO” Should Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  • 55.
    What I wishfor ->allClasses() That Reside in namespace like “AppDTO” Should Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  • 56.
    What I wishfor ->allClasses() ->that() Reside in namespace like “AppDTO” Should Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  • 57.
    What I wishfor ->allClasses() ->that() ->resideInNamespace(“AppDTO”) Should Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  • 58.
    What I wishfor ->allClasses() ->that() ->resideInNamespace(“AppDTO”) ->should() Have Name Ending with “Data” questions on slide.do, code #phpdayPUGed
  • 59.
    What I wishfor ->allClasses() ->that() ->resideInNamespace(“AppDTO”) ->should() ->haveNameEndingWith(‘*Data’); questions on slide.do, code #phpdayPUGed
  • 60.
    Thank you! Michele Orselli mo@flowing.it MicheleOrselli mo@flowing.it tw: _orso_ Questions on slide.do, code #phpdayPUGed Feedback: https://joind.in/talk/baba2 Repo: https://tinyurl.com/y7482abm Meetup: https://www.meetup.com/it-IT/PUG-Romagna-PHP-User-Group-Romagnolo/