SlideShare a Scribd company logo
1 of 29
Download to read offline
Appetite comes with testing

     “It's a dangerous business, Frodo, going out
     your door. You step onto the road, and if you
     don't keep your feet, there's no knowing
     where you might be swept off to.”
                               J.R.R. Tolkien, The Lord of the Rings




Change begins with awareness
Defect Cost Increase




Change begins with awareness
Defect Cost Increase




Change begins with awareness
Stress cycle




Change begins with awareness
Testing as...




      documentation


Change begins with awareness
Testing as...



        instrument for
          cooperation

Change begins with awareness
Testing as...


        instrument for
         open source
         cooperation

Change begins with awareness
Pair programming




Change begins with awareness
All begins with...




   ...a need
Change begins with awareness
And...




 “Supporting multiple user classes is not easy at all. It would
 make the bundle code far more complex as we would
 basically need to change all places interacting with the user
 to be able to handle all user classes. I don't really want to
 go this way (it will also make it more likely to introduce
 bugs).”

    ...a delusion
Change begins with awareness
But...


  In Symfony2, all core classes use the service container,
  so it is easy to extend, configure and use any object




   ...a hope
Change begins with awareness
Service Container
                  Dependency Injection Container


          use AcmeHelloBundleMailer;

          $mailer = new Mailer('sendmail');
          $mailer->send('info@netmeans.net', ... );




Change begins with awareness
Service Container
                  Dependency Injection Container
          class Mailer
          {
              private $mailerType;

              public function __construct($mailerType)
              {
                  $this->mailerType = $mailerType
              }

              public function send($to, ...)
              {
                  ...
              }
          }

          services:
              my_mailer:
                  class:       AcmeHelloBundleMailer
                  arguments:   [sendmail]


Change begins with awareness
Service Container
                  Dependency Injection Container


          class HelloController extends Controller
          {
              public function sendEmailAction()
              {
                  $mailer = $this->get('my_mailer');
                  $mailer->send('info@netmeans.net', ... );
              }
          }




Change begins with awareness
FOSUserBundle
             fos_user:
                 db_driver: orm
                 firewall_name: main
                 user_class: AcmeUserBundleEntityUser




Change begins with awareness
FOSUserBundle
             fos_user:
                 db_driver: orm
                 firewall_name: main
                 user_class: AcmeUserBundleEntityUser
                 service:
                     user_manager: custom_user_manager




Change begins with awareness
So ...

          We have to create our custom
          UserManager that accepts in the
          constructor an object that have the
          responsibility to discriminate user
          types




...a solution
Change begins with awareness
First of all: test

          We start writing some functional
          tests to check correct integration
          of FOSUserBundle




Change begins with awareness
Now we feel good

          We can extends FOSUser without pain
          improving changes step by step




Change begins with awareness
Custom UserManager

 Class UserManager extends FOSUserBundleEntityUserManager
 {
     protected $userDiscriminator;

     public function __construct(..., UserDiscriminator $userDiscriminator)

     public function getClass()
     {
         return $this->userDiscriminator->getClass();
     }
 }




Change begins with awareness
UserDiscriminator

              public function getClass()
              {
                 return 'Acme/UserBundle/Entity/UserOne';
              }




Change begins with awareness
From here it's all smooth

          With little iterations, we improve
          UserManager and UserDiscriminator
          with unit and functional tests,
          passing from a dirty code to a more
          elegant one




Change begins with awareness
NmnMultiUserBundle
     fos_user:
         db_driver: orm
         firewall_name: main
         user_class: AcmeUserBundleEntityUser
         service:
             user_manager: nmn_user_manager
         registration:
             form:
                 handler: nmn_user_registration_form_handler
         profile:
             form:
                 handler: nmn_user_profile_form_handler




Change begins with awareness
NmnMultiUserBundle
  parameters:
    nmn_user_discriminator_parameters:
      classes:
          user_one:
              entity: AcmeUserBundleEntityUserOne
              registration: AcmeUserBundleFormTypeRegistrationUserOneFormType
              profile: AcmeUserBundleFormTypeProfileUserOneFormType
              factory:
          user_two:
              entity: AcmeUserBundleEntityUserTwo
              registration: AcmeUserBundleFormTypeRegistrationUserTwoFormType
              profile: AcmeUserBundleFormTypeProfileUserTwoFormType
              factory:




Change begins with awareness
NmnMultiUserBundle

     Ok, it is an hack :)

     A lazy way to use for free most of the
     functionality of FOSUserBundle ...

     ... but it is ready to be improved by
     anyone.




Change begins with awareness
NmnMultiUserBundle

        github.com/netmeansnet/NmnMultiUserBundle

        github.com/netmeansnet/NmnMultiUserBundleSandbox

        travis-ci.org/#!/netmeansnet/NmnMultiUserBundle




                               @leonardo_nmn

                               @euxpom




Change begins with awareness
Some Books
                       The Clean Coder
                       A code of Conduct for Professional Programmers




                       Martin, Robert C.




I know this sounds strident and unilateral, but given the record I don't
think the surgeons should have to defend hand-washing, and I don't
think programmers should have to defend TDD

Change begins with awareness
Some Books
                       Extreme Programming Explained
                       Embrace Change




                       Beck, Kent




In software development, “perfect” is a verb, not an adjective
In XP, testing is as important as programming
Change begins with awareness
Some Books
                       The Grumpy Programmer's Guide To Building
                       Testable Applications in PHP




                       Hartjes, Chris




Building testable applications is Hard
The reason for investing in automated testing is obvious: any bugs you
catch before your application makes it into production cost less in terms
of resources (money, developer time) to fix than fixing it into production

Change begins with awareness

More Related Content

Similar to Appetite comes with testing

Building Large Scale Javascript Application
Building Large Scale Javascript ApplicationBuilding Large Scale Javascript Application
Building Large Scale Javascript ApplicationAnis Ahmad
 
Dependency injection in Drupal 8 : DrupalCon NOLA
Dependency injection in Drupal 8 : DrupalCon NOLADependency injection in Drupal 8 : DrupalCon NOLA
Dependency injection in Drupal 8 : DrupalCon NOLAAshwini Kumar
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)Matthias Noback
 
The quest for global design principles - PHP Benelux 2016
The quest for global design principles - PHP Benelux 2016The quest for global design principles - PHP Benelux 2016
The quest for global design principles - PHP Benelux 2016Matthias Noback
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy CodeNaresh Jain
 
Sending Email with Rails
Sending Email with RailsSending Email with Rails
Sending Email with RailsJames Gray
 
The Taming Of The Code
The Taming Of The CodeThe Taming Of The Code
The Taming Of The CodeAlan Stevens
 
Lesson10 behavioral patterns
Lesson10 behavioral patternsLesson10 behavioral patterns
Lesson10 behavioral patternsOktJona
 
Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 3camp
 
Environment Variables in Angular
Environment Variables in AngularEnvironment Variables in Angular
Environment Variables in AngularKnoldus Inc.
 
A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015Matthias Noback
 
Cosmos SDK Workshop: How to Build a Blockchain from Scratch
Cosmos SDK Workshop: How to Build a Blockchain from ScratchCosmos SDK Workshop: How to Build a Blockchain from Scratch
Cosmos SDK Workshop: How to Build a Blockchain from ScratchTendermint Inc
 
Command pattern in java
Command pattern in javaCommand pattern in java
Command pattern in javaRakibAhmed0
 
Behavioral pattern 4
Behavioral pattern 4Behavioral pattern 4
Behavioral pattern 4Naga Muruga
 
Resources and relationships at front-end
Resources and relationships at front-endResources and relationships at front-end
Resources and relationships at front-endWingify Engineering
 
NSNotificationCenter vs. AppDelegate
NSNotificationCenter vs. AppDelegateNSNotificationCenter vs. AppDelegate
NSNotificationCenter vs. AppDelegateJohn Wilker
 

Similar to Appetite comes with testing (20)

Cucumber Basics.pdf
Cucumber Basics.pdfCucumber Basics.pdf
Cucumber Basics.pdf
 
Building Large Scale Javascript Application
Building Large Scale Javascript ApplicationBuilding Large Scale Javascript Application
Building Large Scale Javascript Application
 
Dependency injection in Drupal 8 : DrupalCon NOLA
Dependency injection in Drupal 8 : DrupalCon NOLADependency injection in Drupal 8 : DrupalCon NOLA
Dependency injection in Drupal 8 : DrupalCon NOLA
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
 
The quest for global design principles - PHP Benelux 2016
The quest for global design principles - PHP Benelux 2016The quest for global design principles - PHP Benelux 2016
The quest for global design principles - PHP Benelux 2016
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Sending Email with Rails
Sending Email with RailsSending Email with Rails
Sending Email with Rails
 
A dive into Symfony 4
A dive into Symfony 4A dive into Symfony 4
A dive into Symfony 4
 
The Taming Of The Code
The Taming Of The CodeThe Taming Of The Code
The Taming Of The Code
 
Clean code
Clean codeClean code
Clean code
 
Lesson10 behavioral patterns
Lesson10 behavioral patternsLesson10 behavioral patterns
Lesson10 behavioral patterns
 
JUNit Presentation
JUNit PresentationJUNit Presentation
JUNit Presentation
 
Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2
 
Environment Variables in Angular
Environment Variables in AngularEnvironment Variables in Angular
Environment Variables in Angular
 
A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015
 
Cosmos SDK Workshop: How to Build a Blockchain from Scratch
Cosmos SDK Workshop: How to Build a Blockchain from ScratchCosmos SDK Workshop: How to Build a Blockchain from Scratch
Cosmos SDK Workshop: How to Build a Blockchain from Scratch
 
Command pattern in java
Command pattern in javaCommand pattern in java
Command pattern in java
 
Behavioral pattern 4
Behavioral pattern 4Behavioral pattern 4
Behavioral pattern 4
 
Resources and relationships at front-end
Resources and relationships at front-endResources and relationships at front-end
Resources and relationships at front-end
 
NSNotificationCenter vs. AppDelegate
NSNotificationCenter vs. AppDelegateNSNotificationCenter vs. AppDelegate
NSNotificationCenter vs. AppDelegate
 

Recently uploaded

Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 

Recently uploaded (20)

Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 

Appetite comes with testing

  • 1. Appetite comes with testing “It's a dangerous business, Frodo, going out your door. You step onto the road, and if you don't keep your feet, there's no knowing where you might be swept off to.” J.R.R. Tolkien, The Lord of the Rings Change begins with awareness
  • 2. Defect Cost Increase Change begins with awareness
  • 3. Defect Cost Increase Change begins with awareness
  • 4. Stress cycle Change begins with awareness
  • 5. Testing as... documentation Change begins with awareness
  • 6. Testing as... instrument for cooperation Change begins with awareness
  • 7. Testing as... instrument for open source cooperation Change begins with awareness
  • 9. All begins with... ...a need Change begins with awareness
  • 10. And... “Supporting multiple user classes is not easy at all. It would make the bundle code far more complex as we would basically need to change all places interacting with the user to be able to handle all user classes. I don't really want to go this way (it will also make it more likely to introduce bugs).” ...a delusion Change begins with awareness
  • 11. But... In Symfony2, all core classes use the service container, so it is easy to extend, configure and use any object ...a hope Change begins with awareness
  • 12. Service Container Dependency Injection Container use AcmeHelloBundleMailer; $mailer = new Mailer('sendmail'); $mailer->send('info@netmeans.net', ... ); Change begins with awareness
  • 13. Service Container Dependency Injection Container class Mailer { private $mailerType; public function __construct($mailerType) { $this->mailerType = $mailerType } public function send($to, ...) { ... } } services: my_mailer: class: AcmeHelloBundleMailer arguments: [sendmail] Change begins with awareness
  • 14. Service Container Dependency Injection Container class HelloController extends Controller { public function sendEmailAction() { $mailer = $this->get('my_mailer'); $mailer->send('info@netmeans.net', ... ); } } Change begins with awareness
  • 15. FOSUserBundle fos_user: db_driver: orm firewall_name: main user_class: AcmeUserBundleEntityUser Change begins with awareness
  • 16. FOSUserBundle fos_user: db_driver: orm firewall_name: main user_class: AcmeUserBundleEntityUser service: user_manager: custom_user_manager Change begins with awareness
  • 17. So ... We have to create our custom UserManager that accepts in the constructor an object that have the responsibility to discriminate user types ...a solution Change begins with awareness
  • 18. First of all: test We start writing some functional tests to check correct integration of FOSUserBundle Change begins with awareness
  • 19. Now we feel good We can extends FOSUser without pain improving changes step by step Change begins with awareness
  • 20. Custom UserManager Class UserManager extends FOSUserBundleEntityUserManager { protected $userDiscriminator; public function __construct(..., UserDiscriminator $userDiscriminator) public function getClass() { return $this->userDiscriminator->getClass(); } } Change begins with awareness
  • 21. UserDiscriminator public function getClass() { return 'Acme/UserBundle/Entity/UserOne'; } Change begins with awareness
  • 22. From here it's all smooth With little iterations, we improve UserManager and UserDiscriminator with unit and functional tests, passing from a dirty code to a more elegant one Change begins with awareness
  • 23. NmnMultiUserBundle fos_user: db_driver: orm firewall_name: main user_class: AcmeUserBundleEntityUser service: user_manager: nmn_user_manager registration: form: handler: nmn_user_registration_form_handler profile: form: handler: nmn_user_profile_form_handler Change begins with awareness
  • 24. NmnMultiUserBundle parameters: nmn_user_discriminator_parameters: classes: user_one: entity: AcmeUserBundleEntityUserOne registration: AcmeUserBundleFormTypeRegistrationUserOneFormType profile: AcmeUserBundleFormTypeProfileUserOneFormType factory: user_two: entity: AcmeUserBundleEntityUserTwo registration: AcmeUserBundleFormTypeRegistrationUserTwoFormType profile: AcmeUserBundleFormTypeProfileUserTwoFormType factory: Change begins with awareness
  • 25. NmnMultiUserBundle Ok, it is an hack :) A lazy way to use for free most of the functionality of FOSUserBundle ... ... but it is ready to be improved by anyone. Change begins with awareness
  • 26. NmnMultiUserBundle github.com/netmeansnet/NmnMultiUserBundle github.com/netmeansnet/NmnMultiUserBundleSandbox travis-ci.org/#!/netmeansnet/NmnMultiUserBundle @leonardo_nmn @euxpom Change begins with awareness
  • 27. Some Books The Clean Coder A code of Conduct for Professional Programmers Martin, Robert C. I know this sounds strident and unilateral, but given the record I don't think the surgeons should have to defend hand-washing, and I don't think programmers should have to defend TDD Change begins with awareness
  • 28. Some Books Extreme Programming Explained Embrace Change Beck, Kent In software development, “perfect” is a verb, not an adjective In XP, testing is as important as programming Change begins with awareness
  • 29. Some Books The Grumpy Programmer's Guide To Building Testable Applications in PHP Hartjes, Chris Building testable applications is Hard The reason for investing in automated testing is obvious: any bugs you catch before your application makes it into production cost less in terms of resources (money, developer time) to fix than fixing it into production Change begins with awareness