Presentation is loading. Please wait.

Presentation is loading. Please wait.

L’origine dei mali: le dipendenze tra componenti Stefano Leli 14° Workshop DotNetMarche Venerdì 16 aprile

Similar presentations


Presentation on theme: "L’origine dei mali: le dipendenze tra componenti Stefano Leli 14° Workshop DotNetMarche Venerdì 16 aprile"— Presentation transcript:

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

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

3 What is a Dependency?

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

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

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

7 Scenario

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

9 class Copier { Keyboard _reader; Keyboard _reader; Video _writer; Video _writer; public Copier() public Copier() { _reader = new Keyboard(); _reader = new Keyboard(); _writer = new Video(); _writer = new Video(); } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ( (chr = _reader.ReadFromKeyboard() ) != '\r') while ( (chr = _reader.ReadFromKeyboard() ) != '\r') _writer.WriteToVideo(chr); _writer.WriteToVideo(chr); }} class Keyboard { public int ReadFromKeyboard() public int ReadFromKeyboard() { return Console.ReadKey(true).KeyChar; return Console.ReadKey(true).KeyChar; }} class Video { public void WriteToVideo(int chr) public void WriteToVideo(int chr) { Console.Write((char)chr); Console.Write((char)chr); }} Copier Example

10 class Copier { Keyboard _reader; Keyboard _reader; Video _writer; Video _writer; public Copier() public Copier() { _reader = new Keyboard(); _reader = new Keyboard(); _writer = new Video(); _writer = new Video(); } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ( (chr = _reader.ReadFromKeyboard() ) != '\r') while ( (chr = _reader.ReadFromKeyboard() ) != '\r') _writer.WriteToVideo(chr); _writer.WriteToVideo(chr); }} class Keyboard { public int ReadFromKeyboard() public int ReadFromKeyboard() { return Console.ReadKey(true).KeyChar; return Console.ReadKey(true).KeyChar; }} class Video { public void WriteToVideo(int chr) public void WriteToVideo(int chr) { Console.Write((char)chr); Console.Write((char)chr); }} Copier Example Problem

11 Program to an interface, not an implementation

12 Copier Example > IWriterIReader Copier +PerformCopy() Keyboard +Read(c : char) Video + Write () : char Concrete class should depend on abstraction Robert Martin

13 class Copier { IReader _reader; IReader _reader; IWriter _writer; IWriter _writer; public Copier() public Copier() { _reader = new Keyboard(); _reader = new Keyboard(); _writer = new Video(); _writer = new Video(); } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ( (chr = _reader.Read() ) != '\r') while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); _writer.Write(chr); }} class Keyboard : IReader { public int Read() public int Read() { return Console.ReadKey(true).KeyChar; return Console.ReadKey(true).KeyChar; }} class Video : IWriter { public void Write(int chr) public void Write(int chr) { Console.Write((char)chr); Console.Write((char)chr); }} Copier Example

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

15 TowardsDecoupling

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

17 class Copier { IReader _reader; IReader _reader; IWriter _writer; IWriter _writer; public Copier() public Copier() { _reader = ReaderFactory.GetInstance(); _reader = ReaderFactory.GetInstance(); _writer = WriterFactory.GetInstance(); _writer = WriterFactory.GetInstance(); } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ( (chr = _reader.Read() ) != '\r') while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); _writer.Write(chr); }} class ReaderFactory { public static IReader GetInstance() public static IReader GetInstance() { return new Keyboard(); return new Keyboard(); }} class WriterFactory { public static IWriter GetInstance() public static IWriter GetInstance() { return new Video(); return new Video(); }} Using a Factory

18 class Copier { IReader _reader; IReader _reader; IWriter _writer; IWriter _writer; public Copier() public Copier() { _reader = ReaderFactory.GetInstance(); _reader = ReaderFactory.GetInstance(); _writer = WriterFactory.GetInstance(); _writer = WriterFactory.GetInstance(); } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ( (chr = _reader.Read() ) != '\r') while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); _writer.Write(chr); }} class ReaderFactory { public static IReader GetInstance() public static IReader GetInstance() { return new Keyboard(); return new Keyboard(); }} class WriterFactory { public static IWriter GetInstance() public static IWriter GetInstance() { return new Video(); return new Video(); }} Using a Factory We have just move the problem!!! Problem

19 > IWriterIReader Copier Keyboard +Read(c : char) Video + Write () : char +PerformCopy() ServiceLocator +Lookup() : Object +RegisterService(o : Object) _instance : ServiceLocator Service Locator …

20 > IWriterIReader Copier Keyboard +Read(c : char) Video + Write () : char +PerformCopy() ServiceLocator +Lookup() : Object +RegisterService(o : Object) _instance : ServiceLocator Service Locator … Assembler

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

22 Service Locator class Copier { IReader _reader; IReader _reader; IWriter _writer; IWriter _writer; public Copier() public Copier() { _reader = (IReader)ServiceLocator.Lookup("reader"); _reader = (IReader)ServiceLocator.Lookup("reader"); _writer = (IWriter)ServiceLocator.Lookup("writer"); ; _writer = (IWriter)ServiceLocator.Lookup("writer"); ; } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ( (chr = _reader.Read() ) != '\r') while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); _writer.Write(chr); }} /* Configure Service Locator method*/ /* Configure Service Locator method*/ private void configureLocator() { ServiceLocator locator = new ServiceLocator(); ServiceLocator locator = new ServiceLocator(); locator.LoadService("reader", new Keyboard()); locator.LoadService("reader", new Keyboard()); locator.LoadService("writer", new Video()); locator.LoadService("writer", new Video()); ServiceLocator.Load(locator); ServiceLocator.Load(locator);}

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

24 Inversion of Control

25 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. 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 Hollywood Principle “don't call us, we'll call you.” There are many implementations of IoC, Dependency Injections is one of there. There are many implementations of IoC, Dependency Injections is one of there. What is IoC?

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

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

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

29 DI: Constructor Injection class Copier { IReader _reader; IReader _reader; IWriter _writer; IWriter _writer; public Copier(IReader reader, IWriter writer) public Copier(IReader reader, IWriter writer) { _reader = reader; _reader = reader; _writer = writer; _writer = writer; } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ( (chr = _reader.Read() ) != '\r') while ( (chr = _reader.Read() ) != '\r') _writer.Write(chr); _writer.Write(chr); }} To prefer in case of Mandatory Dependencies

30 DI: Setter Injection class Copier { private IReader _reader; private IReader _reader; public IReader Reader public IReader Reader { set{_reader = value;} set{_reader = value;} } private IWriter _writer; private IWriter _writer; public IWriter Writer public IWriter Writer { set{_writer = value;} set{_writer = value;} } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ((chr = _reader.Read()) != '\r') while ((chr = _reader.Read()) != '\r') _writer.Write(chr); _writer.Write(chr); }} To prefer in case of Optional Dependencies

31 DI: Interface Injection class Copier { private IReader _reader; private IReader _reader; public void InjectReader(IReader reader) public void InjectReader(IReader reader) { _reader = reader; _reader = reader; } private IWriter _writer; private IWriter _writer; public void InjectWriter(IWriter writer) public void InjectWriter(IWriter writer) { _writer = writer; _writer = writer; } public void PerformCopy() public void PerformCopy() { int chr; int chr; while ((chr = _reader.Read()) != '\r') while ((chr = _reader.Read()) != '\r') _writer.Write(chr); _writer.Write(chr); }} interface IReaderInject { void injectReader(IReader reader); void injectReader(IReader reader);} interface IWriterInject { void injectWriter(IWriter reader); void injectWriter(IWriter reader);} Quite Never Used

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

33 Aspect Oriented Programming

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

35 Separation of Concern Searching Booking Payment

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

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

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

39 Object_BObject_A How it works… method_Amethod_B Object Oriented Flow

40 Aspect Object_BObject_A How it works… method_Amethod_B advice Object Oriented Flow Aspect Oriented Flow pointcut = method_B Target Object = Object_B jointpoint = method invocation

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

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

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

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

45 Aspect Object_BObject_A How it works… method_Amethod_B advice Object Oriented Flow Aspect Oriented Flow pointcut = method_B Target Object = Object_B jointpoint = method invocation Target Object Target Object Also called Advised Object Also called Advised Object Object being advised by one or more aspects Object being advised by one or more aspects

46 Aspect Object_BObject_A method_Amethod_B advice Object Oriented Flow Aspect Oriented Flow pointcut = method_B Target Object = Object_B jointpoint = method invocation Weaving Weaving Weaving Run-Time Weaving Run-Time Weaving Compile-Time Weaving Compile-Time Weaving … behind the scenes

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

48 Questions?

49 Slide and Materials www.dotnetmarche.org Grazie!


Download ppt "L’origine dei mali: le dipendenze tra componenti Stefano Leli 14° Workshop DotNetMarche Venerdì 16 aprile"

Similar presentations


Ads by Google