lose gekoppelt wie nie: di vs. ioc - hendrik lösch @ dwx 2016

63
LOSE GEKOPPELT WIE NIE DI VS. IOC

Upload: saxonia-systems-ag

Post on 12-Apr-2017

92 views

Category:

Software


2 download

TRANSCRIPT

Page 1: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

LOSE GEKOPPELT WIE NIEDI VS.

IOC

Page 2: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Der Sprecher

Hendrik LöschSenior Consultant & [email protected]@HerrLoeschJust-About.Net

Page 3: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

1. It is hard to change because every change affects too many other parts of the system. (Rigidity - Starr)

2. When you make a change, unexpected parts of the system break. (Fragility - Zerbrechlich)

3. It is hard to reuse in another application because it cannot be disentangled from the current application. (Immobility - Unbeweglich)

Quelle: http://www.objectmentor.com/resources/articles/dip.pdf

Was ist schlechtes Design?!?

Page 4: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

A B X

Page 5: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

• Basistechnologien (.Net, Java, Ruby, …)

• Basisdatentypen (int, string, char…)

• Datenhaltungsklassen und Transferobjekte

• Domänen spezifische Algorithmen und Datenbanken

• UI Logik

• …

beständig

unbeständig

Arten von Abhängigkeiten

Page 6: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

X-Schichten Modell

User Interface

Business Layer

Data Access Layer

Cross Cutting

Concerns

Page 7: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

X-Schichten Modell

User Interface

Business Layer

Data Access Layer

Cross Cutting

Concerns

Page 8: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

A B Xb

?

Page 9: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Robert C. Martin(Uncle Bob)

The SOLID principles are not rules. They are not laws. They are not perfect truths. They are statements on the order of “An apple a day keeps the doctor away.” This is a good principle, it is good advice, but it’s not a pure truth, nor is it a rule.

“”

Quelle: https://sites.google.com/site/unclebobconsultingllc/getting-a-solid-start

Page 10: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

ingle Responsibility Principle

pen Closed Principle

iskov Substitution Principle

nterface Segregation Principle

ependency Inversion Principle

SOLID

Page 11: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

ingle Responsibility Principle

pen Closed Principle

iskov Substitution Principle

nterface Segregation Principle

ependency Inversion Principle

SOLID

Eine Klasse sollte nur eine Verantwortlichkeit haben.

Quelle: http://www.clean-code-developer.de/

Page 12: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

ingle Responsibility Principle

pen Closed Principle

iskov Substitution Principle

nterface Segregation Principle

ependency Inversion Principle

SOLID

Eine Klasse sollte offen für Erweiterungen, jedoch geschlossen für Modifikationen sein.

Quelle: http://www.clean-code-developer.de/

Page 13: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

ingle Responsibility Principle

pen Closed Principle

iskov Substitution Principle

nterface Segregation Principle

ependency Inversion Principle

SOLID

Abgeleitete Klassen sollten sich so verhalten wie es von ihren Basistypen erwartet wird.

Quelle: http://www.clean-code-developer.de/

Page 14: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

ingle Responsibility Principle

pen Closed Principle

iskov Substitution Principle

nterface Segregation Principle

ependency Inversion Principle

SOLID

Interfaces sollten nur die Funktionalität wiederspiegeln die ihre Klienten erwarten.

Quelle: http://www.clean-code-developer.de/

Page 15: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

ingle Responsibility Principle

pen Closed Principle

iskov Substitution Principle

nterface Segregation Principle

ependency Inversion Principle

SOLID High-Level Klassen sollen nicht von Low-Level Klassen abhängig

sein, sondern beide von Abstraktionen.Abstraktionen sollen nicht von Details abhängig sein, sondern

Details von Abstraktionen.Quelle: Wikipedia.org

Page 16: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein, sondern beide von

Abstraktionen.

Abstraktionen sollen nicht von Details abhängig sein, sondern Details von Interfaces.

Page 17: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein…

Klient Leistungs-träger

High-Level Low-Level

Page 18: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein…

Klient Leistungs-träger

High-Level Low-Level

Page 19: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein…

Person Bauer

High-Level Low-Level

Süßer Apfel

Page 20: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Person Boskoop Bauer

High-Level Low-Level

SüßerApfel

GetBoskoop!

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein…

Page 21: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein, sondern beide von

Abstraktionen.

Abstraktionen sollen nicht von Details abhängig sein, sondern Details von Interfaces.

Page 22: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein, sondern beide von

Abstraktionen.

Abstraktionen sollen nicht von Details abhängig sein, sondern Details von Interfaces.

Page 23: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Person Boskoop Bauer

High-Level Low-Level

Süßer Apfel

GetBoskoop

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein, sondern beide von Abstraktionen…

!

Page 24: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Person Obsthändler

Pink Lady Bauer

Boskoop Bauer

Granny Smith Bauer

High-Level Low-Level

SüßerApfel

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein, sondern beide von Abstraktionen…

Page 25: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein, sondern beide von

Abstraktionen.

Abstraktionen sollen nicht von Details abhängig sein, sondern Details von Abstraktionen.

Page 26: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

High-Level Klassen sollen nicht von Low-Level Klassen abhängig sein, sondern beide von

Abstraktionen.

Abstraktionen sollen nicht von Details abhängig sein, sondern Details von Abstraktionen.

Page 27: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Person Obsthändler

Pink Lady Bauer

Boskoop Bauer

Granny Smith Bauer

High-Level Low-Level

SüßerApfel

Abstraktionen sollen nicht von Details abhängig sein, sondern Details von Abstraktionen.

GetBoskoop!

Page 28: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Person Obsthändler

High-Level Low-Level

SüßerApfel

Abstraktionen sollen nicht von Details abhängig sein, sondern Details von Abstraktionen.

GetApfel

Pink Lady Bauer

Boskoop Bauer

Granny Smith Bauer

Page 29: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Person IObsthändler

Low-Level

GetApfel

Obsthändler B

Obsthändler A

Obsthändler C

SüßerApfel

Abstraktionen sollen nicht von Details abhängig sein, sondern Details von Abstraktionen.

High-Level

Page 30: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Was ist Inversion of Control???

Person IObsthändler

Low-Level

GetApfel

Obsthändler B

Obsthändler A

Obsthändler C

SüßerApfel

Page 31: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

ohne IoC mit IoC

Page 32: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

DIP IoC

Low-Level

Creation Inversion

Flow Inversion

Interface Inversion

Page 33: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

DIP IoC

Low-Level

Creation Inversion

Flow Inversion

Interface Inversion

Page 34: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Flow Inversion

Page 35: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Publisher Subscriber

PUB SUB PATTERN

Flow Inversion

Page 36: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

SubscriberSubscriber

PublisherPublisher

EVENT AGGREGATOR / MESSAGE BUS / PUB SUB SERVICE

Publisher Event Aggregator Subscriber

Flow Inversion

Page 37: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

DIP IoC

Low-Level

Creation Inversion

Flow Inversion

Interface Inversion

Page 38: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

FACTORY

Request Factory Typdefinition

Creation Inversion

Request Typdefinition

Page 39: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

SubscriberSubscriber

IOC CONTAINER

Request IoC Container Typdefinitionen

Creation Inversion

Page 40: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

public class StudentContext : DbContext{ public StudentContext() : base() {}

public DbSet<StudentEntity> Students { get; set; }}

Creation Inversion

Page 41: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

public class StudentContext : DbContext, IStudentContext{ public StudentContext() : base() {}

public DbSet<StudentEntity> Students { get; set; }}

public class IStudentContext{ DbSet<StudentEntity> Students { get; set; }}

Creation Inversion

Page 42: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Creation Inversion

public class StudentManagementViewModel { StudentContext context;

public StudentEntity Student { get; set; }

public StudentManagementViewModel() { this.context = new StudentContext(); }

public void ShowStudent(string name) { this.Student =

this.context.Students.FirstOrDefault<StudentEntity>(s => s.StudentName == name);

} }

Page 43: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Creation Inversion

public class StudentManagementViewModel { IStudentContext context;

public StudentEntity Student { get; set; }

public StudentManagementViewModel() { this.context = ServiceLocator.Create<IStudentContext>();

}

public void ShowStudent(string name) { this.Student =

this.context.Students.FirstOrDefault<StudentEntity>(s => s.StudentName == name);

} }

Page 44: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Creation Inversion

public class StudentManagementViewModel { IStudentContext context;

public StudentEntity Student { get; set; }

public StudentManagementViewModel(IStudentContext context) { this.context = context; }

public void ShowStudent(string name) { this.Student =

this.context.Students.FirstOrDefault<StudentEntity>(s => s.StudentName == name);

} }

Page 45: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

DIP IoC

Low-Level

Creation Inversion

Flow Inversion

Interface Inversion

Page 46: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

public class StudentContext : DbContext, IStudentContext{ public StudentContext() : base() {}

public DbSet<StudentEntity> Students { get; set; }}

public class IStudentContext{ DbSet<StudentEntity> Students { get; set; }}

Interface Inversion

Page 47: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

public class IStudentRepository{ IQueryable<StudentEntity> Students { get; set; }}Interface

Inversion

public class StudentContext : DbContext, IStudentRepository{ public StudentContext() : base() { // ... }

private DbSet<StudentEntity> students;

public IQueryable<StudentEntity> Students { get{ return this.students} }}

Page 48: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

[Table("StudentInfo")]public class StudentEntity{ public StudentEntity() { }

[Key] public int SID { get; set; }

[Column("Name", TypeName = "ntext")] [MaxLength(20)] public string StudentName { get; set; }

[Column("BDate", TypeName = "datetime")] public DateTime BirthDate { get; set; }

[NotMapped] public int? Age { get;}

}Interface Inversion

Page 49: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

public class Student{ public int SID { get; set; }

public string Name { get; set; }

public DateTime BirthDate { get; set; }

public int? Age { get; }}

Interface Inversion

public class IStudentRepository{ IQueryable<Student> Students { get; set; }}

[Table("StudentInfo")]public class StudentEntity{ [Key] public int SID { get; set; }

[Column("Name", TypeName = "ntext")] [MaxLength(20)] public string StudentName { get; set; }

[Column("BDate", TypeName = "datetime")] public DateTime BirthDate { get; set; }}

Page 50: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Interface Inversion

public class StudentManagementViewModel { IStudentContext context;

public StudentEntity Student { get; set; }

public StudentManagementViewModel(IStudentContext context) { this.context = context; }

public void ShowStudent(string name) { this.Student =

this.context.Students.FirstOrDefault<StudentEntity>(s => s.StudentName == name);

} }

Page 51: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Interface Inversion

public class StudentManagementViewModel { IStudentRepository repository;

public Student Student { get; set; }

public StudentManagementViewModel(IStudentRepository repository) { this.repository = repository; }

public void ShowStudent(string name) { this.Student =

this.repository.Students.FirstOrDefault<Student>(s => s.StudentName == name);

} }

Page 52: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

var student = this.repository.Students.Single(s => s.StudentName == name);

Student student = this.repository.Students.Single(s => s.StudentName == name);

Student stud = this.repository.Students.Single(s => s.StudentName == name);

Interface Inversion

Page 53: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Interface Inversion

internal class StudentsFromDatabase : IManageStudents, DbSet {...}

public class IStudentRepository{ IQueryable<Student> Students { get; set; }}

public interface IManageStudents : IQueryable<Student>{ Student Create();

void Add(Student student);

...}

Siehe auch: cessor.de

this.Student = this.students.FirstOrDefault(s => s.StudentName == name);

Pseudocode!!!

Page 54: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Header Interfaces

public interface IManageStudents : IQueryable<Student>{ Student Create();

Student GetStudent(string name)

void Add(Student student);

...}

public class IStudentContext{ DbSet<StudentEntity> Students { get; set; }}

Role Interfaces

Interface Inversion

Page 55: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

DIP IoC

Low-Level

Creation Inversion

Flow Inversion

Interface Inversion

Page 56: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Test

Implementierung

Refaktorisierung

Page 57: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Test

Implementierung

Refaktorisierung

Systemtest

Page 58: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

UI

BL

DA

UI

BL

DA

Page 59: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Quelle: http://jeffreypalermo.com/blog/the-onion-architecture-part-1/

User Interface

Tests

Infrastr

ucture

File

DB

Web Service

Page 60: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

• Entkopplung der Ausführung einer Aktion von ihrer Implementierung.

• Fokussierung von Bestandteilen auf deren eigentliche Aufgabe.

• Grundstrukturen werden durch Verträge festgehalten.

• Zulieferer können einfacher durch andere ersetzt werden.

Was bringt uns Inversion of Control?

Page 61: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

„The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.“

Quelle: https://en.wikiquote.org/wiki/Donald_Knuth

Donald Knuth

Premature Optimization

Page 62: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Was lernen wir?

Der Code bestimmt die Schnittstellen.

Der Konsument bestimmt die Schnittstellen.

Page 63: Lose gekoppelt wie nie: DI vs. IOC - Hendrik Lösch @ DWX 2016

Der Sprecher

Hendrik LöschSenior Consultant & [email protected]