SlideShare a Scribd company logo
1 of 132
Using symfony events to create clean
class interfaces

                                       by Dennis Benkert
Dennis Who?!




               2
Dennis Who?!




               2
Dennis Who?!




               2
Dennis Who?!




               2
Dennis Who?!




               2
Agenda




         3
Agenda

         Code Coupling




                         3
Agenda

         Code Coupling
         Event Basics




                         3
Agenda

         Code Coupling
          Event Basics
         Events in Code




                          3
Agenda

         Code Coupling
          Event Basics
         Events in Code
         Usage Examples



                          3
Agenda

           Code Coupling
            Event Basics
          Events in Code
          Usage Examples
         Problems of Events


                              3
Code Coupling


                4
In the beginning it‘s all so cleaned up...




... but over time things start to change
                                                          5
„Coupling is the single greatest problem in large
                               software systems“

                                              - Ted Faison




                                                        6
„You don‘t want to achieve consistency by making the
classes tightly coupled, because that reduces their
reuseability“
                                          - Gang of Four




                                                       7
Separation of Concerns




                         8
Separation of Concerns




                         8
Separation of Concerns




                         8
Separation of Concerns




                         8
Separation of Concerns




                         8
Separation of Concerns




                         8
Separation of Concerns




                         8
Separation of Concerns




                         8
Separation of Concerns




                         8
Separation of Concerns




          Events, DI, ...




                            8
Event Basics


               9
Event Connection

               Event Dispatcher




           Software Components
                                  10
Event Connection

               Event Dispatcher




           Software Components
                                  10
Event Connection

                                  Event Dispatcher




                  connect
  (registration.complete) .




                              Software Components
                                                     10
Event Connection

                                  Event Dispatcher




                  connect
  (registration.complete) .




                              Software Components
                                                     10
Event Connection

                                  Event Dispatcher




                                                     connect
                  connect                              (registration.complete)
  (registration.complete) .




                              Software Components
                                                                         10
Basic Event Notification




                          11
Basic Event Notification




                          11
Basic Event Notification


     notify




                          11
Basic Event Notification


           notify
 (registration.complete)




                           11
Basic Event Notification


           notify
 (registration.complete)




                           11
Basic Event Notification


           notify
 (registration.complete)




                 notification




                               11
Basic Event Notification


           notify
 (registration.complete)




                 notification




                               11
Basic Event Notification


           notify
 (registration.complete)




                 notification




                               11
Basic Event Notification


           notify
 (registration.complete)



                               notification
                 notification




                                             11
Basic Event Notification


           notify
 (registration.complete)



                               notification
                 notification




                                             11
More Event Notifications




                          12
More Event Notifications




                          12
More Event Notifications


    filter




                          12
More Event Notifications


        filter
  (blog_post.render)




                          12
More Event Notifications


        filter
  (blog_post.render)




                          12
More Event Notifications


        filter
  (blog_post.render)




                       notification




                                     12
More Event Notifications


        filter
  (blog_post.render)




                       notification




                                     12
More Event Notifications


        filter
  (blog_post.render)




                       notification




                                     12
More Event Notifications


        filter
  (blog_post.render)



           returnValue
                         notification




                                       12
More Event Notifications


        filter
  (blog_post.render)



           returnValue
                         notification




                                       12
More Event Notifications


        filter
  (blog_post.render)



           returnValue             notification
                         notification




                                                 12
More Event Notifications


        filter
  (blog_post.render)



           returnValue             notification
                         notification




                                                 12
More Event Notifications


        filter
  (blog_post.render)



           returnValue             notification
                         notification




                                                 12
More Event Notifications


        filter
  (blog_post.render)


                                                 returnValue
           returnValue             notification
                         notification




                                                               12
More Event Notifications


        filter
  (blog_post.render)


                                                 returnValue
           returnValue             notification
                         notification




                                                               12
More Event Notifications

                 returnValue

        filter
  (blog_post.render)


                                                  returnValue
           returnValue              notification
                          notification




                                                                12
More Event Notifications




                          13
More Event Notifications




                          13
More Event Notifications


  notifyUntil




                          13
More Event Notifications


     notifyUntil
(registration.complete)




                          13
More Event Notifications


     notifyUntil
(registration.complete)




                          13
More Event Notifications


     notifyUntil
(registration.complete)




                          notification




                                        13
More Event Notifications


     notifyUntil
(registration.complete)




                          notification




                                        13
More Event Notifications


     notifyUntil
(registration.complete)




                          notification




                                        13
More Event Notifications


     notifyUntil
(registration.complete)



             returnValue
                           notification




                                         13
More Event Notifications


     notifyUntil
(registration.complete)



             returnValue
                           notification




                                         13
More Event Notifications

                    returnValue

     notifyUntil
(registration.complete)



             returnValue
                             notification




                                           13
More Event Notifications

                    returnValue

     notifyUntil
(registration.complete)



             returnValue
                             notification




                                           13
More Event Notifications

                    returnValue

     notifyUntil
(registration.complete)



             returnValue
                             notification




                                           13
More Event Notifications

                    returnValue

     notifyUntil
(registration.complete)



             returnValue
                             notification




                                           13
More Event Notifications

                    returnValue

     notifyUntil
(registration.complete)



             returnValue
                             notification




                                           13
Events in Code


                 14
Events in Code


 class frontendConfiguration extends sfApplicationConfiguration
 {
   public function configure()
   {
     $this->dispatcher->connect('registration.complete',
       array(SomeClass, 'listenToRegistrationComplete'));

         // [...]
     }
 }




                                                                  15
Events in Code


 class frontendConfiguration extends sfApplicationConfiguration
 {
   public function configure()
   {
     $this->dispatcher->connect('registration.complete',
       array(SomeClass, 'listenToRegistrationComplete'));

         // [...]
     }
 }




                                                                  15
Events in Code

                                       Event Name

 class frontendConfiguration extends sfApplicationConfiguration
 {
   public function configure()
   {
     $this->dispatcher->connect('registration.complete',
       array(SomeClass, 'listenToRegistrationComplete'));

         // [...]
     }
 }




                                                                  15
Events in Code

                                       Event Name

 class frontendConfiguration extends sfApplicationConfiguration
 {
   public function configure()
   {
     $this->dispatcher->connect('registration.complete',
       array(SomeClass, 'listenToRegistrationComplete'));

         // [...]
     }
 }




                                                                  15
Events in Code

                                                Event Name

 class frontendConfiguration extends sfApplicationConfiguration
 {
   public function configure()
   {
     $this->dispatcher->connect('registration.complete',
       array(SomeClass, 'listenToRegistrationComplete'));

         // [...]
     }
 }



                           Callable
                    (can be static or non-static)


                                                                  15
Events in Code




  $this->dispatcher->notify(new sfEvent($user, 'registration.complete'));




                                                                            16
Events in Code




  $this->dispatcher->notify(new sfEvent($user, 'registration.complete'));




                                                                            16
Events in Code

      Notification Type


  $this->dispatcher->notify(new sfEvent($user, 'registration.complete'));




                                                                            16
Events in Code

      Notification Type


  $this->dispatcher->notify(new sfEvent($user, 'registration.complete'));




                                                                            16
Events in Code

      Notification Type


  $this->dispatcher->notify(new sfEvent($user, 'registration.complete'));




                                  Subject

                                                                            16
Events in Code

      Notification Type


  $this->dispatcher->notify(new sfEvent($user, 'registration.complete'));




                                  Subject

                                                                            16
Events in Code

                                              Event Name
      Notification Type


  $this->dispatcher->notify(new sfEvent($user, 'registration.complete'));




                                  Subject

                                                                            16
Events in Code


 class SomeClass
 {
   public static function listenToRegistrationComplete(sfEvent $event)
   {
     $user = $event->getSubject();

         // [...]
     }
 }




                                                                         17
Events in Code


 class SomeClass
 {
   public static function listenToRegistrationComplete(sfEvent $event)
   {
     $user = $event->getSubject();

         // [...]
     }
 }




                                                                         17
Events in Code
                               Registered Method
                                     (called via notfiy)



 class SomeClass
 {
   public static function listenToRegistrationComplete(sfEvent $event)
   {
     $user = $event->getSubject();

         // [...]
     }
 }




                                                                         17
Events in Code
                               Registered Method
                                     (called via notfiy)



 class SomeClass
 {
   public static function listenToRegistrationComplete(sfEvent $event)
   {
     $user = $event->getSubject();

         // [...]
     }
 }




                                                                         17
Events in Code
                               Registered Method
                                     (called via notfiy)



 class SomeClass
 {
   public static function listenToRegistrationComplete(sfEvent $event)
   {
     $user = $event->getSubject();

         // [...]
     }
 }




                                     Event as Parameter
                                                                         17
Events in Code
                               Registered Method
                                     (called via notfiy)



 class SomeClass
 {
   public static function listenToRegistrationComplete(sfEvent $event)
   {
     $user = $event->getSubject();

         // [...]
     }
 }




                                     Event as Parameter
                                                                         17
Events in Code
                               Registered Method
                                     (called via notfiy)



 class SomeClass
 {
   public static function listenToRegistrationComplete(sfEvent $event)
   {
     $user = $event->getSubject();

         // [...]
     }
 }



         Passed Subject
                                     Event as Parameter
                                                                         17
Events in Code




 $returnValue = $this->dispatcher->filter(new sfEvent($blogPost,
 'blog_post.render'), $blogPost->getBody());




                                                                   18
Events in Code




 $returnValue = $this->dispatcher->filter(new sfEvent($blogPost,
 'blog_post.render'), $blogPost->getBody());




                                                                   18
Events in Code

                               Notification Type


 $returnValue = $this->dispatcher->filter(new sfEvent($blogPost,
 'blog_post.render'), $blogPost->getBody());




                                                                   18
Events in Code

                               Notification Type


 $returnValue = $this->dispatcher->filter(new sfEvent($blogPost,
 'blog_post.render'), $blogPost->getBody());




                                                                   18
Events in Code

                               Notification Type


 $returnValue = $this->dispatcher->filter(new sfEvent($blogPost,
 'blog_post.render'), $blogPost->getBody());




                                      Raw Value

                                                                   18
Events in Code

                               Notification Type


 $returnValue = $this->dispatcher->filter(new sfEvent($blogPost,
 'blog_post.render'), $blogPost->getBody());




                                      Raw Value

                                                                   18
Events in Code

                               Notification Type


 $returnValue = $this->dispatcher->filter(new sfEvent($blogPost,
 'blog_post.render'), $blogPost->getBody());




      Filtered Value
                                      Raw Value

                                                                   18
Events in Code

 class MarkdownParser
 {

     // [...]

     public static function listenToRegistrationComplete(sfEvent $event, $body)
     {
       $markdownParser = new self();
       $parsedBody = $markdownParser->parse($body);

         // [...]

         return $parsedBody;
     }
 }




                                                                                  19
Events in Code

 class MarkdownParser
 {

     // [...]

     public static function listenToRegistrationComplete(sfEvent $event, $body)
     {
       $markdownParser = new self();
       $parsedBody = $markdownParser->parse($body);

         // [...]

         return $parsedBody;
     }
 }




                                                                                  19
Events in Code
                               Raw Value as Parameter
 class MarkdownParser
 {

     // [...]

     public static function listenToRegistrationComplete(sfEvent $event, $body)
     {
       $markdownParser = new self();
       $parsedBody = $markdownParser->parse($body);

         // [...]

         return $parsedBody;
     }
 }




                                                                                  19
Events in Code
                               Raw Value as Parameter
 class MarkdownParser
 {

     // [...]

     public static function listenToRegistrationComplete(sfEvent $event, $body)
     {
       $markdownParser = new self();
       $parsedBody = $markdownParser->parse($body);

         // [...]

         return $parsedBody;
     }
 }




                                                                                  19
Events in Code
                               Raw Value as Parameter
 class MarkdownParser
 {

     // [...]

     public static function listenToRegistrationComplete(sfEvent $event, $body)
     {
       $markdownParser = new self();
       $parsedBody = $markdownParser->parse($body);

         // [...]

         return $parsedBody;
     }
 }


                        Filtered Value
                                                                                  19
Usage Examples


                 20
Other Usage Examples




 skoop


                       21
Other Usage Examples



         Being able to add extra actions to
         specific functionality without having
         to alter the existing code.



 skoop


                                                21
Other Usage Examples




snzapka


                       22
Other Usage Examples


          I use events mostly with object
          states changes, for example to send
          email, notify someone, clear cache,
          calculate sth.



snzapka


                                                22
Other Usage Examples




b00giZm


                       23
Other Usage Examples


          I have a centralized "spot" for file
          system operations. e.g. when a user
          deletes an image from the DB, it
          kicks off an event



b00giZm


                                                23
Other Usage Examples




helasliban


                       24
Other Usage Examples


             Right now I'm using symfony events
             for loose coupling of symfony
             plugins.



helasliban


                                                  24
Other Usage Examples




ubermuda


                       25
Other Usage Examples


           Obfuscate code, totally screwing up
           the app's workflow with chain-
           binded useless events. o/



ubermuda


                                                 25
Problems of Events


                     26
Problems of Events


          No Silver Bullet




                             27
Problems of Events


             No Silver Bullet

     Events won‘t help with every problem!




                                             27
Problems of Events


    Use Events for optional coupling




                                       28
Problems of Events


    Use Events for optional coupling

     If you need mandatory coupling use DI.




                                              28
Problems of Events


       No Notification Order




                              29
Problems of Events


          No Notification Order

  If your listeners need ordering ure doin it rong!




                                                      29
Problems of Events


         Harder debugging




                            30
Problems of Events


              Harder debugging
   It can get complicated if you do weird things.




                                                    30
Problems of Events


              Harder debugging
   It can get complicated if you do weird things.
               (Remember ubermuda)




                                                    30
Problems of Events


      Real Setup Hardly Testable




                                   31
Problems of Events


        Real Setup Hardly Testable

  You can never know who connected to an event.




                                                  31
Problems of Events


            Slowness




                       32
Problems of Events


                   Slowness

  Every firing starts the Events notification chain.




                                                     32
Thank you!
Give feedback on joind.in, please
 http://joind.in/talk/view/1415



                                    33
Credits

         Thanks to:
         - Bernhard and Andreas for the reviews and tips.
         - Konrad and Samim for the designs and the artworks.


Creative Commons stuff used:
- „Cog, Gear, Settings“ icon by „Visual Pharm“ - http://www.iconfinder.net/icondetails/27879/128/
- „Crying, Man“ icon by Rokey - http://www.iconfinder.net/icondetails/37613/128/
- „Box, Package“ icon by Alessandro Rei - http://www.iconfinder.net/icondetails/6507/128/




                                                                                            34

More Related Content

More from D

Dockerizing Symfony Applications - Symfony Live Berlin 2014
Dockerizing Symfony Applications - Symfony Live Berlin 2014Dockerizing Symfony Applications - Symfony Live Berlin 2014
Dockerizing Symfony Applications - Symfony Live Berlin 2014
D
 
The Dog Ate My Deployment - PHP Uncoference September 2013
The Dog Ate My Deployment - PHP Uncoference September 2013The Dog Ate My Deployment - PHP Uncoference September 2013
The Dog Ate My Deployment - PHP Uncoference September 2013
D
 
The Dog Ate My Deployment - Symfony Usergroup Cologne July 2013
The Dog Ate My Deployment - Symfony Usergroup Cologne July 2013The Dog Ate My Deployment - Symfony Usergroup Cologne July 2013
The Dog Ate My Deployment - Symfony Usergroup Cologne July 2013
D
 
Dennis Benkert - The Dog Ate My Deployment - Symfony Usergroup Berlin March ...
Dennis Benkert -  The Dog Ate My Deployment - Symfony Usergroup Berlin March ...Dennis Benkert -  The Dog Ate My Deployment - Symfony Usergroup Berlin March ...
Dennis Benkert - The Dog Ate My Deployment - Symfony Usergroup Berlin March ...
D
 
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
D
 
What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012
D
 
symfony Live 2010 - Using Doctrine Migrations
symfony Live 2010 -  Using Doctrine Migrationssymfony Live 2010 -  Using Doctrine Migrations
symfony Live 2010 - Using Doctrine Migrations
D
 
Railslove Lightningtalk 20 02 09 - Web Debug Toolbars
Railslove Lightningtalk 20 02 09 - Web Debug ToolbarsRailslove Lightningtalk 20 02 09 - Web Debug Toolbars
Railslove Lightningtalk 20 02 09 - Web Debug Toolbars
D
 

More from D (11)

Monitoring und Metriken im Wunderland
Monitoring und Metriken im WunderlandMonitoring und Metriken im Wunderland
Monitoring und Metriken im Wunderland
 
Dockerizing Symfony Applications - Symfony Live Berlin 2014
Dockerizing Symfony Applications - Symfony Live Berlin 2014Dockerizing Symfony Applications - Symfony Live Berlin 2014
Dockerizing Symfony Applications - Symfony Live Berlin 2014
 
The Dog Ate My Deployment - PHP Uncoference September 2013
The Dog Ate My Deployment - PHP Uncoference September 2013The Dog Ate My Deployment - PHP Uncoference September 2013
The Dog Ate My Deployment - PHP Uncoference September 2013
 
The Dog Ate My Deployment - Symfony Usergroup Cologne July 2013
The Dog Ate My Deployment - Symfony Usergroup Cologne July 2013The Dog Ate My Deployment - Symfony Usergroup Cologne July 2013
The Dog Ate My Deployment - Symfony Usergroup Cologne July 2013
 
Dennis Benkert - The Dog Ate My Deployment - Symfony Usergroup Berlin March ...
Dennis Benkert -  The Dog Ate My Deployment - Symfony Usergroup Berlin March ...Dennis Benkert -  The Dog Ate My Deployment - Symfony Usergroup Berlin March ...
Dennis Benkert - The Dog Ate My Deployment - Symfony Usergroup Berlin March ...
 
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
 
What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012
 
symfony Live 2010 - Using Doctrine Migrations
symfony Live 2010 -  Using Doctrine Migrationssymfony Live 2010 -  Using Doctrine Migrations
symfony Live 2010 - Using Doctrine Migrations
 
symfony and immobilienscout24.de - Dennis Benkert
symfony and immobilienscout24.de - Dennis Benkertsymfony and immobilienscout24.de - Dennis Benkert
symfony and immobilienscout24.de - Dennis Benkert
 
symfony and immobilienscout24.de - Rob Bors
symfony and immobilienscout24.de - Rob Borssymfony and immobilienscout24.de - Rob Bors
symfony and immobilienscout24.de - Rob Bors
 
Railslove Lightningtalk 20 02 09 - Web Debug Toolbars
Railslove Lightningtalk 20 02 09 - Web Debug ToolbarsRailslove Lightningtalk 20 02 09 - Web Debug Toolbars
Railslove Lightningtalk 20 02 09 - Web Debug Toolbars
 

Recently uploaded

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Recently uploaded (20)

Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 

symfony live 2010 - Using symfony events to create clean class interfaces