Manage software dependencies with ioc and aop

Post on 06-May-2015

1,026 views 0 download

Tags:

description

Manage software dependencies with io c and aop

transcript

Manage software Manage software dependencies with IoC and dependencies with IoC and

AOPAOP

Stefano LeliStefano Leli

14° Workshop 14° Workshop DotNetMarcheDotNetMarcheFriday 16Friday 16thth April 2010 April 2010

@sleli@sleli

stefano.leli@gmail.comstefano.leli@gmail.com

Software DependenciesSoftware Dependencies

Service LocatorService Locator

Inversion of ControlInversion of Control

Dependency InjectionDependency Injection

Aspect Oriented ProgrammingAspect Oriented Programming

AgendaAgenda

What is a What is a Dependency?Dependency?

ClassA

+RequestService()

ClassB

public RequestService(){ ClassB b = new ClassB() b.DoService();}

DependenciesDependencies

dependent

+DoService()

Layer DependenciesLayer Dependencies

Presentation Layer

Business Layer

Data Access Layer

Depends on

High-level modules High-level modules should not depend on should not depend on

low-level modules. low-level modules. Both should depend Both should depend

on abstractionson abstractionsRobert C. MartinRobert C. Martin

DB

Depends on

Depends on

Why dependencies are evil?Why dependencies are evil?

Tight coupling of software componentsTight coupling of software components hard to change because every change affects hard to change because every change affects

too many other parts of the system (Rigidity)too many other parts of the system (Rigidity) When you make a change, unexpected parts of When you make a change, unexpected parts of

the system break. (Fragility)the system break. (Fragility) hard to reuse in another application. hard to reuse in another application.

(Immobility)(Immobility)

Software becomes hard to maintainSoftware becomes hard to maintain

Difficult to isolate when testingDifficult to isolate when testing

ScenarioScenario

Copier ExampleCopier Example

Copier

+PerformCopy()

Keyboard

+ReadFromKB(c : char)

Video

+WriteToVideo() : char

class Copierclass 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 Keyboardclass Keyboard

{{

public int ReadFromKeyboard()public int ReadFromKeyboard()

{ {

return Console.ReadKey(true).KeyChar;return Console.ReadKey(true).KeyChar;

}}

}}

class Videoclass Video

{{

public void WriteToVideo(int chr)public void WriteToVideo(int chr)

{{

Console.Write((char)chr);Console.Write((char)chr);

}}

}}

Copier ExampleCopier Example

class Copierclass 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 Keyboardclass Keyboard

{{

public int ReadFromKeyboard()public int ReadFromKeyboard()

{ {

return Console.ReadKey(true).KeyChar;return Console.ReadKey(true).KeyChar;

}}

}}

class Videoclass Video

{{

public void WriteToVideo(int chr)public void WriteToVideo(int chr)

{{

Console.Write((char)chr);Console.Write((char)chr);

}}

}}

Copier ExampleCopier Example

Problem

Program to an Program to an interface, not an interface, not an implementationimplementation

Copier ExampleCopier Example

<<create>>

<<create>>

IWriterIReader

Copier

+PerformCopy()

Keyboard

+Read(c : char)

Video

+Write() : char

Concrete class should depend on abstraction

Robert Martin

class Copierclass Copier

{{

IReaderIReader _reader; _reader;

IWriterIWriter _writer; _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 class Keyboard : IReader: IReader

{{

public int public int ReadRead()()

{ {

return Console.ReadKey(true).KeyChar;return Console.ReadKey(true).KeyChar;

}}

}}

class Video class Video : IWriter: IWriter

{{

public void public void WriteWrite(int chr)(int chr)

{{

Console.Write((char)chr);Console.Write((char)chr);

}}

}}

Copier ExampleCopier Example

class Copierclass Copier

{{

IReaderIReader _reader; _reader;

IWriterIWriter _writer; _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 class Keyboard : IReader: IReader

{{

public int public int ReadRead()()

{ {

return Console.ReadKey(true).KeyChar;return Console.ReadKey(true).KeyChar;

}}

}}

class Video class Video : IWriter: IWriter

{{

public void public void WriteWrite(int chr)(int chr)

{{

Console.Write((char)chr);Console.Write((char)chr);

}}

}}

Copier ExampleCopier Example

Problem

Dependencies resolution is still here!!!

Towards Towards

DecouplingDecoupling

<<create>>

Using a FactoryUsing a Factory

<<create>>

IWriterIReader

Copier

Keyboard

+Read(c : char)

Video

+Write() : char

ReaderFactory

+GetInstance() : IReader

+Copier(r : IReader, w : IWriter)+PerformCopy()

WriterFactory

+GetInstance() : IWriter

class Copierclass Copier

{{

IReader _reader;IReader _reader;

IWriter _writer;IWriter _writer;

public Copier()public Copier()

{{

__reader = ReaderFactory.reader = ReaderFactory.GetInstanceGetInstance();();

_writer = WriterFactory._writer = WriterFactory.GetInstanceGetInstance();();

}}

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 ReaderFactoryclass ReaderFactory

{{

public static IReader GetInstance()public static IReader GetInstance()

{{

return new Keyboard();return new Keyboard();

}}

}}

class WriterFactoryclass WriterFactory

{{

public static IWriter GetInstance()public static IWriter GetInstance()

{{

return new Video();return new Video();

}}

}}

Using a FactoryUsing a Factory

class Copierclass Copier

{{

IReader _reader;IReader _reader;

IWriter _writer;IWriter _writer;

public Copier()public Copier()

{{

_reader = ReaderFactory._reader = ReaderFactory.GetInstanceGetInstance();();

_writer = WriterFactory._writer = WriterFactory.GetInstanceGetInstance();();

}}

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 ReaderFactoryclass ReaderFactory

{{

public static IReader GetInstance()public static IReader GetInstance()

{{

return new Keyboard();return new Keyboard();

}}

}}

class WriterFactoryclass WriterFactory

{{

public static IWriter GetInstance()public static IWriter GetInstance()

{{

return new Video();return new Video();

}}

}}

Using a FactoryUsing a Factory

We have just moved the problem!!!

Problem

<<create>> <<create>>

IWriterIReader

Copier

Keyboard

+Read(c : char)

Video

+Write() : char

+PerformCopy()

ServiceLocator

+Lookup() : Object+RegisterService(o : Object)

_instance : ServiceLocator

Service LocatorService Locator

<<create>> <<create>>

IWriterIReader

Copier

Keyboard

+Read(c : char)

Video

+Write() : char

+PerformCopy()

ServiceLocator

+Lookup() : Object+RegisterService(o : Object)

_instance : ServiceLocator

Service LocatorService Locator

Service LocatorService Locator

class ServiceLocatorclass 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<string, Object> _services = new Dictionary<string, Object>();private Dictionary<string, Object> _services = new Dictionary<string, Object>();

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);

}}

}}

Service LocatorService Locator

class Copierclass 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 methodConfigure Service Locator method*/*/

private void configureLocator()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);

}}

ProPro Help to avoid couplingHelp to avoid coupling Centralize dependencies resolutionCentralize dependencies resolution

ConsCons Introduce dependencies with the Introduce dependencies with the

locatorlocator Difficult to testDifficult to test

Service LocatorService Locator

IInversion nversion

oof f

CControlontrol

Inversion of ControlInversion of Control, or , or IoCIoC, is an , is an abstract principle describing an aspect of abstract principle describing an aspect of some software architecture designs in some software architecture designs in which the flow of control of a system is which the flow of control of a system is inverted in comparison to traditional inverted in comparison to traditional programming.programming.

Hollywood PrincipleHollywood Principle

““don't call us, we'll call you.”don't call us, we'll call you.”

There are many implementations of IoC, There are many implementations of IoC, Dependency Injections is one of there.Dependency Injections is one of there.

What is IoC?What is IoC?

Technique for supplying an external Technique for supplying an external dependency to a software component.dependency to a software component.

Implemented by a Container (IoC)Implemented by a Container (IoC) Creates and assembles component/objects and Creates and assembles component/objects and

manages their lifecyclemanages their lifecycle Generally configured by coding or external fileGenerally configured by coding or external file

Three forms of injectionThree forms of injection Constructor InjectionConstructor Injection Setter InjectionSetter Injection Interface InjectionInterface Injection

What is Dependency Injection?What is Dependency Injection?

IoC Container

IWriterIReader

Copier

Keyboard

+Read(c : char)

Video

+Write() : char

+Copier(r : IReader, w : IWriter)+PerformCopy()

<<create>> <<create>>

IoC Container

<<create>>

IWriterIReader

Copier

Keyboard

+Read(c : char)

Video

+Write() : char

IoCContainer

+Copier(r : IReader, w : IWriter)+PerformCopy()

XMLConfi

g

DI: Constructor InjectionDI: Constructor Injection

class Copierclass Copier

{{

IReader _reader;IReader _reader;

IWriter _writer;IWriter _writer;

public Copier(public Copier(IReader reader, IWriter writerIReader 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 ofMandatory Dependencies

DI: Setter InjectionDI: Setter Injection

class Copierclass Copier

{ {

private IReader _reader;private IReader _reader;

public IReader Readerpublic IReader Reader

{{

set{_reader = value;}set{_reader = value;}

}}

private IWriter _writerprivate IWriter _writer;;

public IWriter Writerpublic 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 ofOptional Dependencies

DI: Interface InjectionDI: Interface Injection

class Copierclass 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 IReaderInjectinterface IReaderInject

{{

void injectReader(IReader reader); void injectReader(IReader reader);

}}

interface IWriterInjectinterface IWriterInject

{{

void injectWriter(IWriter reader); void injectWriter(IWriter reader);

}}

Quite Never Used

ProPro High Decoupling levelHigh Decoupling level Completely transparent to the Domain Completely transparent to the Domain

ModelModel High ConfigurableHigh Configurable Integrated with lots of frameworkIntegrated with lots of framework

ConsCons Difficult to understand by newbieDifficult to understand by newbie Complex to debugComplex to debug

DI: ConsiderationDI: Consideration

AAspectspect

OOriented riented

PProgrammingrogramming

AOP is a programming paradigmAOP is a programming paradigm

AOP is a new way of thinking about AOP is a new way of thinking about software designsoftware design

Enhance OOP in separating concerns Enhance OOP in separating concerns to improve modularizationto improve modularization

OOP modularizes concernsOOP modularizes concerns

AOP addresses AOP addresses cross-cutting cross-cutting concernsconcerns

What is AOP?What is AOP?

Separation of ConcernSeparation of Concern

Searching

Booking

Payment

Separation of ConcernSeparation of Concern

Booking PaymentSearching

OOPSearching

Booking

Payment

Reduce software complexityReduce software complexity

Limit the impact of changeLimit the impact of change

Facilitate reuseFacilitate reuse

Simplify components Simplify components integrationintegration

Crosscutting ConcernCrosscutting Concern

Booking

SecurityLogging

Payment

SecurityLogging

Searching

SecurityLogging

OOP

Crosscutting concerns are functionalities that span Crosscutting concerns are functionalities that span multiple modulesmultiple modules SecuritySecurity LoggingLogging Transaction ManagementTransaction Management ……

Hard to model with traditional OOP approachHard to model with traditional OOP approach Code Scattering Code Scattering Code TanglingCode Tangling

Crosscutting Concerns

Searching

Booking

Payment

Crosscutting ConcernCrosscutting Concern

Booking PaymentSearching

Security Logging

AOP

Booking

SecurityLogging

Payment

SecurityLogging

Searching

SecurityLogging

OOP

Crosscutting Concerns

Searching

Booking

Payment

Object_BObject_A

How it works…How it works…

Object Oriented Flow

Aspect

Object_BObject_A

How it works…How it works…

advice

Object Oriented Flow

Aspect Oriented Flow

pointcut = method_B

Target Object = Object_B

jointpoint = method invocation

Aspect

Object_BObject_A

How it works…How it works…

advice

Object Oriented Flow

Aspect Oriented Flow

pointcut = method_B

Target Object = Object_B

jointpoint = method invocation

AspectAspect Equivalent to class in OOPEquivalent to class in OOP Used to describe a Used to describe a

Crosscutting ConcernCrosscutting Concern

Aspect

Object_BObject_A

How it works…How it works…

advice

Object Oriented Flow

Aspect Oriented Flow

pointcut = method_B

Target Object = Object_B

jointpoint = method invocation

Join PointJoin Point Well-defined point during the Well-defined point during the

execution of a program (e.g. execution of a program (e.g. method invocation, attribute method invocation, attribute access, exception handling,access, exception handling,…)…)

Aspect

Object_BObject_A

How it works…How it works…

advice

Object Oriented Flow

Aspect Oriented Flow

pointcut = method_B

Target Object = Object_B

jointpoint = method invocation

AdviceAdvice action taken by an aspect at action taken by an aspect at

a particular join pointa particular join point

Aspect

Object_BObject_A

How it works…How it works…

advice

Object Oriented Flow

Aspect Oriented Flow

pointcut = method_B

Target Object = Object_B

jointpoint = method invocation

PointcutPointcut Predicate that matches join Predicate that matches join

pointspoints Advice is associated with a Advice is associated with a

pointcut expression and runs pointcut expression and runs at any join point matched by at any join point matched by the pointcutthe pointcut

Aspect

Object_BObject_A

How it works…How it works…

advice

Object Oriented Flow

Aspect Oriented Flow

pointcut = method_B

Target Object = Object_B

jointpoint = method invocation

Target ObjectTarget Object Also called Advised ObjectAlso called Advised Object Object being advised by one Object being advised by one

or more aspectsor more aspects

Aspect

Object_BObject_A

advice

Object Oriented Flow

Aspect Oriented Flow

pointcut = method_B

Target Object = Object_B

jointpoint = method invocation

Wea

ving

WeavingWeaving Run-Time WeavingRun-Time Weaving Compile-Time WeavingCompile-Time Weaving

… … behind the scenesbehind the scenes

ReferencesReferences

Martin FowlerMartin Fowler Inversion of Control Containers and the Inversion of Control Containers and the

Dependency Injection patternDependency Injection pattern

Robert C. MartinRobert C. Martin The Dependency Inversion PrincipleThe Dependency Inversion Principle

AOP AllianceAOP Alliance

Questions?Questions?

Slide and MaterialsSlide and Materials

www.dotnetmarche.orgwww.dotnetmarche.org

Grazie!Grazie!