1 / 49

L’origine dei mali: le dipendenze tra componenti

stefano.leli@gmail.com. @ sleli. L’origine dei mali: le dipendenze tra componenti. Stefano Leli. 14° Workshop DotNetMarche Venerdì 16 aprile 2010. Agenda. Software Dependencies Service Locator Inversion of Control Dependency Injection Aspect Oriented Programming.

conley
Download Presentation

L’origine dei mali: le dipendenze tra componenti

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. stefano.leli@gmail.com @sleli L’origine dei mali: le dipendenze tra componenti Stefano Leli 14° Workshop DotNetMarche Venerdì 16 aprile 2010

  2. Agenda • Software Dependencies • Service Locator • Inversion of Control • Dependency Injection • Aspect Oriented Programming

  3. What is a Dependency?

  4. Dependencies ClassA ClassB +RequestService() dependent +DoService() public RequestService() { ClassB b = new ClassB() b.DoService(); }

  5. Layer Dependencies Presentation Layer Depends on Business Layer Depends on Data Access Layer Depends on DB High-level modules should not depend on low-level modules. Both should depend on abstractions Robert C. Martin

  6. Why dependencies are evil? • Tight coupling of software components • hard to change because every change affects too many other parts of the system (Rigidity) • When you make a change, unexpected parts of the system break. (Fragility) • hard to reuse in another application. (Immobility) • Software becomes hard to maintain • Difficult to isolate when testing

  7. Scenario

  8. Copier Example Copier Keyboard Video +PerformCopy() +WriteToVideo() : char +ReadFromKB(c : char)

  9. Copier Example class Keyboard { public intReadFromKeyboard() { returnConsole.ReadKey(true).KeyChar; } } class Video { public voidWriteToVideo(intchr) { Console.Write((char)chr); } } class Copier { Keyboard _reader; Video _writer; public Copier() { _reader = new Keyboard(); _writer = new Video(); } public voidPerformCopy() { intchr; while ( (chr = _reader.ReadFromKeyboard() ) != '\r') _writer.WriteToVideo(chr); } }

  10. Copier Example class Keyboard { public intReadFromKeyboard() { returnConsole.ReadKey(true).KeyChar; } } class Video { public voidWriteToVideo(intchr) { Console.Write((char)chr); } } Problem class Copier { Keyboard _reader; Video _writer; public Copier() { _reader = new Keyboard(); _writer = new Video(); } public voidPerformCopy() { intchr; while ( (chr = _reader.ReadFromKeyboard() ) != '\r') _writer.WriteToVideo(chr); } }

  11. Program to an interface, not an implementation

  12. Copier Example IReader IWriter Copier Keyboard Video +PerformCopy() +Write() : char +Read(c : char) <<create>> <<create>> Concrete class should depend on abstraction Robert Martin

  13. Copier Example class Keyboard : IReader { public intRead() { return Console.ReadKey(true).KeyChar; } } class Video : IWriter { public voidWrite(intchr) { Console.Write((char)chr); } } class Copier { IReader_reader; IWriter_writer; public Copier() { _reader = new Keyboard(); _writer = new Video(); } public voidPerformCopy() { intchr; while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); } }

  14. Copier Example class Keyboard : IReader { public intRead() { return Console.ReadKey(true).KeyChar; } } class Video : IWriter { public voidWrite(intchr) { Console.Write((char)chr); } } Problem class Copier { IReader_reader; IWriter_writer; public Copier() { _reader = new Keyboard(); _writer = new Video(); } public voidPerformCopy() { intchr; while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); } } Dependencies resolution is still here!!!

  15. Towards Decoupling

  16. Using a Factory Copier IReader IWriter ReaderFactory WriterFactory Keyboard Video +Copier(r : IReader, w : IWriter) +PerformCopy() +GetInstance() : IReader +GetInstance() : IWriter +Write() : char +Read(c : char) <<create>> <<create>>

  17. Using a Factory class ReaderFactory { public static IReaderGetInstance() { return new Keyboard(); } } class WriterFactory { public static IWriterGetInstance() { return new Video(); } } class Copier { IReader_reader; IWriter_writer; public Copier() { _reader = ReaderFactory.GetInstance(); _writer = WriterFactory.GetInstance(); } public voidPerformCopy() { intchr; while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); } }

  18. Using a Factory class ReaderFactory { public static IReaderGetInstance() { return new Keyboard(); } } class WriterFactory { public static IWriterGetInstance() { return new Video(); } } Problem We have just move the problem!!! class Copier { IReader_reader; IWriter_writer; public Copier() { _reader = ReaderFactory.GetInstance(); _writer = WriterFactory.GetInstance(); } public voidPerformCopy() { intchr; while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); } }

  19. Service Locator Copier IReader IWriter Keyboard Video +PerformCopy() +Write() : char +Read(c : char) <<create>> <<create>> ServiceLocator _instance : ServiceLocator +Lookup() : Object +RegisterService(o : Object) …

  20. Service Locator Copier IReader IWriter Keyboard Video +PerformCopy() +Write() : char +Read(c : char) <<create>> <<create>> ServiceLocator _instance : ServiceLocator +Lookup() : Object +RegisterService(o : Object) …

  21. Service Locator class ServiceLocator { /* Singleton instance */ private static ServiceLocator _instance; public static void Load(ServiceLocatorarg) { _instance = arg; } /* Storing and Retrieve services */ private Dictionary<string, Object> _services = new Dictionary<string, Object>(); public Object RegisterService(String key) { return _instance._services[key]; } public static void Lookup(String key, Object service) { _services.Add(key, service); } }

  22. Service Locator /* Configure Service Locator method*/ private voidconfigureLocator() { ServiceLocatorlocator = newServiceLocator(); locator.LoadService("reader", new Keyboard()); locator.LoadService("writer", new Video()); ServiceLocator.Load(locator); } class Copier { IReader_reader; IWriter_writer; public Copier() { _reader = (IReader)ServiceLocator.Lookup("reader"); _writer = (IWriter)ServiceLocator.Lookup("writer"); ; } public voidPerformCopy() { intchr; while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); } }

  23. Service Locator • Pro • Help to avoid coupling • Centralize dependencies resolution • Cons • Introduce dependencies with the locator • Difficult to test

  24. Inversion of Control

  25. What is IoC? • Inversion of Control, or IoC, is an abstract principle describing an aspect of some software architecture designs in which the flow of control of a system is inverted in comparison to traditional programming. • Hollywood Principle “don't call us, we'll call you.” • There are many implementations of IoC, Dependency Injections is one of there.

  26. What is Dependency Injection? • Technique for supplying an external dependency to a software component. • Implemented by a Container (IoC) • Creates and assembles component/objects and manages their lifecycle • Generally configured by coding or external file • Three forms of injection • Constructor Injection • Setter Injection • Interface Injection

  27. IoC Container Copier IReader IWriter Keyboard Video +Copier(r : IReader, w : IWriter) +PerformCopy() +Write() : char +Read(c : char)

  28. IoC Container Copier IReader IWriter IoCContainer Keyboard Video +Copier(r : IReader, w : IWriter) +PerformCopy() … +Write() : char +Read(c : char) <<create>> <<create>> <<create>> XML Config

  29. DI: Constructor Injection To prefer in case of Mandatory Dependencies class Copier { IReader_reader; IWriter_writer; public Copier(IReaderreader, IWriterwriter) { _reader = reader; _writer = writer; } public voidPerformCopy() { intchr; while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); } }

  30. DI: Setter Injection To prefer in case of Optional Dependencies class Copier { private IReader_reader; public IReaderReader { set{_reader = value;} } private IWriter_writer; public IWriterWriter { set{_writer = value;} } public voidPerformCopy() { intchr; while ((chr = _reader.Read()) != '\r') _writer.Write(chr); } }

  31. DI: Interface Injection interface IReaderInject { void injectReader(IReader reader); } interface IWriterInject { void injectWriter(IWriter reader); } Quite Never Used class Copier { private IReader_reader; public voidInjectReader(IReaderreader) { _reader = reader; } private IWriter_writer; public voidInjectWriter(IWriterwriter) { _writer = writer; } public voidPerformCopy() { intchr; while ((chr = _reader.Read()) != '\r') _writer.Write(chr); } }

  32. DI: Consideration • Pro • High Decoupling level • Completely transparent to the Domain Model • High Configurable • Integrated with lots of framework • Cons • Difficult to understand by newbie • Complex to debug

  33. Aspect Oriented Programming

  34. What is AOP? AOP is a programming paradigm AOP is a new way of thinking about software design Enhance OOP in separating concerns to improve modularization OOP modularizes concerns AOP addresses cross-cutting concerns

  35. Separation of Concern Searching Booking Payment

  36. Separation of Concern Searching Booking Payment Searching Booking Payment OOP Reduce software complexity Limit the impact of change Facilitate reuse Simplify components integration

  37. Crosscutting Concern Searching Booking Payment Searching Security Logging Booking Security Logging Payment Security Logging OOP Crosscutting Concerns • Crosscutting concerns are functionalities that span multiple modules • Security • Logging • Transaction Management • … • Hard to model with traditional OOP approach • Code Scattering • Code Tangling

  38. Crosscutting Concern Searching Booking Payment Searching Security Logging Booking Security Logging Payment Security Logging OOP Crosscutting Concerns AOP Searching Booking Payment Security Logging

  39. How it works… Object_A Object_B Object Oriented Flow method_A method_B

  40. How it works… Object_A Object_B Object Oriented Flow method_A method_B Aspect Oriented Flow jointpoint = method invocation advice Aspect pointcut = method_B Target Object = Object_B

  41. How it works… Object_A Object_B Object Oriented Flow method_A method_B Aspect Oriented Flow jointpoint = method invocation advice Aspect pointcut = method_B Target Object = Object_B • Aspect • Equivalent to class in OOP • Used to describe a Crosscutting Concern

  42. How it works… Object_A Object_B Object Oriented Flow method_A method_B Aspect Oriented Flow jointpoint = method invocation advice Aspect pointcut = method_B Target Object = Object_B • Join Point • Well-defined point during the execution of a program (e.g. method invocation, attribute access, exception handling,…)

  43. How it works… Object_A Object_B Object Oriented Flow method_A method_B Aspect Oriented Flow jointpoint = method invocation advice Aspect pointcut = method_B Target Object = Object_B • Advice • action taken by an aspect at a particular join point

  44. How it works… Object_A Object_B Object Oriented Flow method_A method_B Aspect Oriented Flow jointpoint = method invocation advice Aspect pointcut = method_B Target Object = Object_B • Pointcut • Predicate that matches join points • Advice is associated with a pointcut expression and runs at any join point matched by the pointcut

  45. How it works… Object_A Object_B Object Oriented Flow method_A method_B Aspect Oriented Flow jointpoint = method invocation advice Aspect pointcut = method_B Target Object = Object_B • Target Object • AlsocalledAdvisedObject • Object being advised by one or more aspects

  46. … behind the scenes Object_A Object_B Object Oriented Flow method_A method_B Aspect Oriented Flow jointpoint = method invocation advice Aspect pointcut = method_B Weaving Target Object = Object_B • Weaving • Run-TimeWeaving • Compile-TimeWeaving

  47. References • Martin Fowler • Inversion of Control Containers and the Dependency Injection pattern • Robert C. Martin • The Dependency Inversion Principle • AOP Alliance

  48. Questions?

  49. Slide and Materials www.dotnetmarche.org Grazie!

More Related