63

DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

Embed Size (px)

Citation preview

Page 1: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC
Page 3: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

1. It is hard to change because every change affects too many other partsof 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 bedisentangled from the current application. (Immobility - Unbeweglich)

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

Page 4: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

A B X

Page 5: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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

• Basisdatentypen (int, string, char…)

• Datenhaltungsklassen und Transferobjekte

• Domänen spezifische Algorithmen und Datenbanken

• UI Logik

• …

beständig

unbeständig

Page 6: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

User Interface

Business Layer

Data Access Layer

Cross Cutting

Concerns

Page 7: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

User Interface

Business Layer

Data Access Layer

Cross Cutting

Concerns

Page 8: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

A B Xb

?

Page 9: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

public class A{

IB b;

public A(IB b){

this.b = b;}

}

Page 10: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

User Interface

Business Layer

Data Access Layer

Cross Cutting

Concerns

Page 11: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 12: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

ingle Responsibility Principle

pen Closed Principle

iskov Substitution Principle

nterface Segregation Principle

ependency Inversion Principle

SOLID

Page 13: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 14: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 15: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 16: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 17: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 18: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 19: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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

KlientLeistungs-

träger

High-Level Low-Level

Page 20: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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

KlientLeistungs-

träger

High-Level Low-Level

Page 21: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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

Person Bauer

High-Level Low-Level

Süßer Apfel

Page 22: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

PersonBoskoop

Bauer

High-Level Low-Level

SüßerApfel

GetBoskoop!

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

Page 23: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 24: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 25: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

PersonBoskoop

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 26: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 27: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 28: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 29: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 30: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 31: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 32: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

Was ist Inversion of Control???

Person IObsthändler

Low-Level

GetApfel

Obsthändler

B

Obsthändler

A

Obsthändler

C

SüßerApfel

Page 33: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

ohne IoC mit IoC

Page 34: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

DIP IoC

Low-Level

Creation

Inversion

Flow

Inversion

Interface

Inversion

Page 35: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

DIP IoC

Low-Level

Creation

Inversion

Flow

Inversion

Interface

Inversion

Page 36: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

Flow

Inversion

Page 37: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

Publisher Subscriber

Flow

Inversion

Page 38: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

SubscriberSubscriber

PublisherPublisher

Publisher Event Aggregator Subscriber

Flow

Inversion

Page 39: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

DIP IoC

Low-Level

Creation

Inversion

Flow

Inversion

Interface

Inversion

Page 40: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

Request Factory Typdefinition

Creation

Inversion

Request Typdefinition

Page 41: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

SubscriberSubscriber

Request IoC Container Typdefinitionen

Creation

Inversion

Page 42: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

public class StudentContext : DbContext{

public StudentContext() : base(){}

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

Creation

Inversion

Page 43: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 44: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 45: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 46: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 47: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

DIP IoC

Low-Level

Creation

Inversion

Flow

Inversion

Interface

Inversion

Page 48: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 49: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 50: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

[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 51: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 52: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 53: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 54: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 55: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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

Page 56: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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 57: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

DIP IoC

Low-Level

Creation

Inversion

Flow

Inversion

Interface

Inversion

Page 58: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

User Interface

Business Layer

Data Access Layer

Cross Cutting

Concerns

Page 59: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

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

ApplicationServices

Domain Services

Domain Model

User Interface

File

DB

Web Service

Page 60: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

Page 61: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

„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

Page 62: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC

Der Code bestimmt die Lösung.

Der Konsument bestimmen den

Code.

Page 63: DevDay 2016: Hendrik Lösch - Lose gekoppelt wie nie: DI vs. IoC