Principles of PHP Package Design
Lastminutetalk
Matthias Noback - PHP developer and consultant
AmsterdamPHP - 9/19/2013
Matthias Noback
Principles of OOD
Dutch developer
Consultancy, training, writing
Clean code, TDD
·
·
·
2/44
Micro versus macro design
Organizational units:
Classes
Packages (modules, components, bundles, ...)
·
·
3/44
Principles of class design
4/44
Principles of class design
The Single Responsibility Principle
A class should have one, and only one, reason to change
5/44
Principles of class design
The Open Closed Principle
You should be able to extend a classes behavior, without modifying it
6/44
Principles of class design
The Liskov Substitution Principle
Derived classes must be substitutable for their base classes
7/44
Principles of class design
The Interface Segregation Principle
Make fine grained interfaces that are client specific
8/44
Principles of class design
The Dependency Inversion Principle
Depend on abstractions, not on concretions
9/44
Principles of package design
10/44
Principles of package design
Cohesion
What to put inside packages?
Coupling
How to couple packages?
11/44
Cohesion principles
12/44
The Release Reuse Equivalency Principle
The granule of reuse is the granule of release
"A package as a product"
13/44
The Release Reuse Equivalency Principle
Version control
Package definition
Hosting
Auto-loading
BC
Marking breaks
Semantic versioning
Tags
Required files
Quality control
·
·
·
·
·
·
·
·
·
·
14/44
The Release Reuse Equivalency Principle
Example: ChargebeeAPI classes (irrelevant composer.json)
Example: HTMLPurify(old-school auto-loading)
Example: Codeception Silexmodule (custom VCS hosting)
15/44
The Common Closure Principle
Classes that change together are packaged together
Ask yourself which packages would change when:
The web framework changes
The persistence library changes
The application's features change
The business rules change
...
·
·
·
·
·
16/44
The Common Closure Principle
Classes that change together are packaged together
Example: FOSUserBundle- too much library code
Example: FOSRestBundleand JMSSerializerBundle- a dangerous alliance
17/44
The Common Reuse Principle
Classes that are used together are packaged together
If you use a class inside a package, you will (most likely) use (all) other classes
inside it too.
18/44
The Common Reuse Principle
Classes that are used together are packaged together
Example: FOSRestBundleand the QueryParamFetcher
Example: Monologand its handlers
Example: Asseticand its filters
Example: NelmioSecurityBundleand its listeners
19/44
Coupling principles
20/44
The Acyclic Dependencies Principle
The dependency graph of packages must have no cycles
Create a dependencies diagram:
clue/graph-composer
21/44
The Stable Dependencies Principle
Depend in the direction of stability
"Stability" equals "not easy to change" (versus volatility).
Hard to change packages should not depend on easy to change packages.
22/44
The Stable Dependencies Principle
Depend in the direction of stability
Dependencies between packages are dependencies by class:
Count number of dependencies out (C-out)
Count number of dependencies in (C-in)
I = C-out / (C-in + C-out)
23/44
The Stable Dependencies Principle
Depend in the direction of stability
E.g. 2 / (0 + 2) = 1(only out), so 1is very dependent, therefore instable
E.g. 0 / (3 + 0) = 0(only in), so 0is independent, therefore stable
24/44
The Stable Dependencies Principle
Depend in the direction of stability
Packages with more dependencies depend on packages with less dependencies.
These are less likely (because difficult) to change, since many other packages
depend on them.
25/44
The Stable Dependencies Principle
Depend in the direction of stability
Stable packages are called responsible (they should not be easy to change),
independent (only depended upon) packages.
Instable packages are called irresponsible (because easily changed) and
dependent (on more stable packages).
26/44
The Stable Abstractions Principle
Abstractness increases with stability
A package should be as abstract as it is stable.
A stable package (with less dependencies out than in), should have an equal
ratio of abstract versus total amount of classes.
27/44
The Stable Abstractions Principle
Abstractness increases with stability
Stable package: difficult to change. It has more dependencies in than out.
Given the Dependency Inversion Principle, packages will depend on other
packages because those contain abstract classes and interfaces, which adds
stability to their design.
28/44
The Stable Abstractions Principle
Abstractness increases with stability
A = C-abstract / (C-concrete + C-abstract)
No abstract classes, just concrete classes: A = 0
No concrete classes, just abstract classes: A = 1
29/44
The Stable Abstractions Principle
Abstractness increases with stability
Combine Iand Ain a graph.
30/44
The Stable Abstractions Principle
Abstractness increases with stability
When you plot these ratios you will see:
I = 0(stable) and A = 1(abstract) = (0, 1)(top-left corner)
I = 1(instable) and A = 0(concrete) = (1, 0)(bottom-right corner)
31/44
The Stable Abstractions Principle
Abstractness increases with stability
Everything in between should be in proportion.
A less stable package, should be also more concrete.
A more stable package, should also be more abstract.
32/44
The Stable Abstractions Principle
Abstractness increases with stability
On the other end of the spectrum are some strange packages:
I = 1(instable) and A = 1(abstract) = (1, 1)(top-right)
A package with no dependents, only dependencies, but very abstract
nonetheless.
I = 0(stable) and A = 0(concrete) = (0, 0)(bottom-left)
A package that has no dependencies, only dependents, and nevertheless has
only concrete classes.
33/44
The rule of three
34/44
The Rule of Three
From Facts and Fallacies of Software Engineering:
Therearetwo"rulesofthree"in[software]reuse:
Itisthreetimesasdifficulttobuildreusablecomponentsassingleuse
components,andareusablecomponentshouldbetriedoutinthreedifferent
applicationsbeforeitwillbesufficientlygeneraltoacceptintoareuse
library.
35/44
The Rule of Three
Effort
Project packages: 1:1
Written ony for this project (like modules for account management, blog, etc.).
36/44
The Rule of Three
Effort
Library package: 1:1or 3:2
For common needs, written for this project, but reusable in other projects.
37/44
The Rule of Three
Effort
Open sourced library package: 2:1
38/44
The Rule of Three
Effort
An entire reusable project (like Sylius): 3:1
(Or parts of it.). Within a well-known structure, offer end-to-end functionality,
while making it easy to extend/change behavior.
39/44
A Year With Symfony
About the book
40/44
41/44
A Year With Symfony
When you work with Symfony2:
You need to understand the framework very well
You need to be very good at dependency injection
You will need a good project structure
You need to do be very well aware of any possible security issues
You should develop for reusability
·
·
·
·
·
42/44
Raffle
A Year With Symfony
43/44
Thank you
twitter @matthiasnoback
www php-and-symfony.matthiasnoback.nl
github github.com/matthiasnoback
leanpub leanpub.com/a-year-with-symfony

Principles of PHP Package Design (for AmsterdamPHP)

  • 1.
    Principles of PHPPackage Design Lastminutetalk Matthias Noback - PHP developer and consultant AmsterdamPHP - 9/19/2013
  • 2.
    Matthias Noback Principles ofOOD Dutch developer Consultancy, training, writing Clean code, TDD · · · 2/44
  • 3.
    Micro versus macrodesign Organizational units: Classes Packages (modules, components, bundles, ...) · · 3/44
  • 4.
  • 5.
    Principles of classdesign The Single Responsibility Principle A class should have one, and only one, reason to change 5/44
  • 6.
    Principles of classdesign The Open Closed Principle You should be able to extend a classes behavior, without modifying it 6/44
  • 7.
    Principles of classdesign The Liskov Substitution Principle Derived classes must be substitutable for their base classes 7/44
  • 8.
    Principles of classdesign The Interface Segregation Principle Make fine grained interfaces that are client specific 8/44
  • 9.
    Principles of classdesign The Dependency Inversion Principle Depend on abstractions, not on concretions 9/44
  • 10.
  • 11.
    Principles of packagedesign Cohesion What to put inside packages? Coupling How to couple packages? 11/44
  • 12.
  • 13.
    The Release ReuseEquivalency Principle The granule of reuse is the granule of release "A package as a product" 13/44
  • 14.
    The Release ReuseEquivalency Principle Version control Package definition Hosting Auto-loading BC Marking breaks Semantic versioning Tags Required files Quality control · · · · · · · · · · 14/44
  • 15.
    The Release ReuseEquivalency Principle Example: ChargebeeAPI classes (irrelevant composer.json) Example: HTMLPurify(old-school auto-loading) Example: Codeception Silexmodule (custom VCS hosting) 15/44
  • 16.
    The Common ClosurePrinciple Classes that change together are packaged together Ask yourself which packages would change when: The web framework changes The persistence library changes The application's features change The business rules change ... · · · · · 16/44
  • 17.
    The Common ClosurePrinciple Classes that change together are packaged together Example: FOSUserBundle- too much library code Example: FOSRestBundleand JMSSerializerBundle- a dangerous alliance 17/44
  • 18.
    The Common ReusePrinciple Classes that are used together are packaged together If you use a class inside a package, you will (most likely) use (all) other classes inside it too. 18/44
  • 19.
    The Common ReusePrinciple Classes that are used together are packaged together Example: FOSRestBundleand the QueryParamFetcher Example: Monologand its handlers Example: Asseticand its filters Example: NelmioSecurityBundleand its listeners 19/44
  • 20.
  • 21.
    The Acyclic DependenciesPrinciple The dependency graph of packages must have no cycles Create a dependencies diagram: clue/graph-composer 21/44
  • 22.
    The Stable DependenciesPrinciple Depend in the direction of stability "Stability" equals "not easy to change" (versus volatility). Hard to change packages should not depend on easy to change packages. 22/44
  • 23.
    The Stable DependenciesPrinciple Depend in the direction of stability Dependencies between packages are dependencies by class: Count number of dependencies out (C-out) Count number of dependencies in (C-in) I = C-out / (C-in + C-out) 23/44
  • 24.
    The Stable DependenciesPrinciple Depend in the direction of stability E.g. 2 / (0 + 2) = 1(only out), so 1is very dependent, therefore instable E.g. 0 / (3 + 0) = 0(only in), so 0is independent, therefore stable 24/44
  • 25.
    The Stable DependenciesPrinciple Depend in the direction of stability Packages with more dependencies depend on packages with less dependencies. These are less likely (because difficult) to change, since many other packages depend on them. 25/44
  • 26.
    The Stable DependenciesPrinciple Depend in the direction of stability Stable packages are called responsible (they should not be easy to change), independent (only depended upon) packages. Instable packages are called irresponsible (because easily changed) and dependent (on more stable packages). 26/44
  • 27.
    The Stable AbstractionsPrinciple Abstractness increases with stability A package should be as abstract as it is stable. A stable package (with less dependencies out than in), should have an equal ratio of abstract versus total amount of classes. 27/44
  • 28.
    The Stable AbstractionsPrinciple Abstractness increases with stability Stable package: difficult to change. It has more dependencies in than out. Given the Dependency Inversion Principle, packages will depend on other packages because those contain abstract classes and interfaces, which adds stability to their design. 28/44
  • 29.
    The Stable AbstractionsPrinciple Abstractness increases with stability A = C-abstract / (C-concrete + C-abstract) No abstract classes, just concrete classes: A = 0 No concrete classes, just abstract classes: A = 1 29/44
  • 30.
    The Stable AbstractionsPrinciple Abstractness increases with stability Combine Iand Ain a graph. 30/44
  • 31.
    The Stable AbstractionsPrinciple Abstractness increases with stability When you plot these ratios you will see: I = 0(stable) and A = 1(abstract) = (0, 1)(top-left corner) I = 1(instable) and A = 0(concrete) = (1, 0)(bottom-right corner) 31/44
  • 32.
    The Stable AbstractionsPrinciple Abstractness increases with stability Everything in between should be in proportion. A less stable package, should be also more concrete. A more stable package, should also be more abstract. 32/44
  • 33.
    The Stable AbstractionsPrinciple Abstractness increases with stability On the other end of the spectrum are some strange packages: I = 1(instable) and A = 1(abstract) = (1, 1)(top-right) A package with no dependents, only dependencies, but very abstract nonetheless. I = 0(stable) and A = 0(concrete) = (0, 0)(bottom-left) A package that has no dependencies, only dependents, and nevertheless has only concrete classes. 33/44
  • 34.
    The rule ofthree 34/44
  • 35.
    The Rule ofThree From Facts and Fallacies of Software Engineering: Therearetwo"rulesofthree"in[software]reuse: Itisthreetimesasdifficulttobuildreusablecomponentsassingleuse components,andareusablecomponentshouldbetriedoutinthreedifferent applicationsbeforeitwillbesufficientlygeneraltoacceptintoareuse library. 35/44
  • 36.
    The Rule ofThree Effort Project packages: 1:1 Written ony for this project (like modules for account management, blog, etc.). 36/44
  • 37.
    The Rule ofThree Effort Library package: 1:1or 3:2 For common needs, written for this project, but reusable in other projects. 37/44
  • 38.
    The Rule ofThree Effort Open sourced library package: 2:1 38/44
  • 39.
    The Rule ofThree Effort An entire reusable project (like Sylius): 3:1 (Or parts of it.). Within a well-known structure, offer end-to-end functionality, while making it easy to extend/change behavior. 39/44
  • 40.
    A Year WithSymfony About the book 40/44
  • 41.
  • 42.
    A Year WithSymfony When you work with Symfony2: You need to understand the framework very well You need to be very good at dependency injection You will need a good project structure You need to do be very well aware of any possible security issues You should develop for reusability · · · · · 42/44
  • 43.
    Raffle A Year WithSymfony 43/44
  • 44.
    Thank you twitter @matthiasnoback wwwphp-and-symfony.matthiasnoback.nl github github.com/matthiasnoback leanpub leanpub.com/a-year-with-symfony