SOFTWARE HYGIENE€¦ · Big Ball of Mud . Johannes Siedersleben sd&m QUASAR „Software, die...

Preview:

Citation preview

S O F T W A R E H Y G I E N E

X P D A Y S S T U T T G A R T 2 0 1 7

oder was man von Blutgruppen über die Strukturierung von Software

lernen kann

sven bange jens himmelreich

N E U L A N D - B Ü R O F Ü R I N F O R M A T I K

ARCHITEKTUR

AGILE

ARCHITEKTDER EINSAME

Plan

ARCHITEKT

ARCHITEKT

ARCHITEKTUR evolvierend, inkrementell

Werte

Muster

Werte und Muster werden global kommuniziert und machen lokal handlungsfähig.

Big Ball of Mud

sauber einfach strukturiert aufgeräumt

willkürlich chaotisch wuchernd schmutzig

1 8 4 8

Ignaz Semmelweis

„Erkennung, Behandlung und Präventionvon Infektionskrankheiten“

H Y G I E N E

„Erkennung, Behandlung und Präventionvon Infektionskrankheiten“

E R K E N N U N G

Bedside-Test

A B 0

A B AB0

A B AB00 A B

AB

Spender

Empfänger

xxx

xxx x xx

Serafol® ABO

Anti-A Anti-B

Serafol® AB0

Anti-A Anti-B

Serafol® AB0

Anti-A Anti-B

Serafol® AB0

Anti-BAnti-A

Big Ball of Mud

Johannes Siedersleben sd&m

Q U A S A R

„Software, die sich unterschiedlich schnell ändert, wird in unterschiedliche Module aufgeteilt.“

David Parnas

A B AB0

A T AT0

universell verfügbare Software

A T AT0

Anwendungs-Software

A T AT0

Technische Software

A T AT0

Big Ball of Mud

A T AT0

Repräsentation

A T AT/R0

A T R0

A T R00 A T R

Aufgerufener

Aufrufer

xxx

xxx x xx

Quasar

Quasar® AT0

Anti-TAnti-A

„Erkennung, Behandlung und Präventionvon Infektionskrankheiten“

H Y G I E N E

„Erkennung, Behandlung und Präventionvon Infektionskrankheiten“

B E H A N D L U N G

TREN ∙ NUNG

Domain Driven Design

Eric Evans, Vaughn Vernon

I. Bounded Context

A B C

II. A-Software ∙ T-Software

III. Domain Model

Trennwand

R-Software

Hexagon

Hexagon

Port and Adapter

Application

Domain

Hexagon

WebController

AppService

Aggregate Repository

EntityValueObject

DomainServiceDomainEvent

RepositoryImpl

WebRequestPort and Adapter

Application

Domain

JDBCObject

A-Software

WebController

AppService

Aggregate Repository

EntityValueObject

DomainServiceDomainEvent

RepositoryImpl

WebRequestPort and Adapter

Application

Domain

JDBCObject

Aggregate Repository

EntityValueObject

DomainServiceDomainEvent

T-Software

WebController

AppService

Aggregate Repository

EntityValueObject

DomainServiceDomainEvent

RepositoryImpl

WebRequestPort and Adapter

Application

Domain

JDBCObject

WebRequest

JDBCObject

R-Software

WebController

AppService

Aggregate Repository

EntityValueObject

DomainServiceDomainEvent

RepositoryImpl

WebRequestPort and Adapter

Application

Domain

JDBCObject

WebController

AppService

RepositoryImpl

B E I S P I E L

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

@Controller public class WebController {

@Autowired private GreetingApplicationService greetingApplicationService;

@RequestMapping("/") public String home(Model model) { GreetingData greeting = greetingApplicationService.welcomePeople(); model.addAttribute("salutation", greeting.getSalutation()); model.addAttribute("name", greeting.getName()); return "home"; }

}

@Controller public class WebController {

@Autowired private GreetingApplicationService greetingApplicationService;

@RequestMapping("/") public String home(Model model) { GreetingData greeting = greetingApplicationService.welcomePeople(); model.addAttribute("salutation", greeting.getSalutation()); model.addAttribute("name", greeting.getName()); return "home"; }

}

@Controller public class WebController {

@Autowired private GreetingApplicationService greetingApplicationService;

@RequestMapping("/") public String home(Model model) { GreetingData greeting = greetingApplicationService.welcomePeople(); model.addAttribute("salutation", greeting.getSalutation()); model.addAttribute("name", greeting.getName()); return "home"; }

}

@Controller public class WebController {

@Autowired private GreetingApplicationService greetingApplicationService;

@RequestMapping("/") public String home(Model model) { GreetingData greeting = greetingApplicationService.welcomePeople(); model.addAttribute("salutation", greeting.getSalutation()); model.addAttribute("name", greeting.getName()); return "home"; }

}

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

@Service public class GreetingApplicationService {

@Autowired private GreetingRepository repository;

public GreetingData welcomePeople() { Greeting greeting = repository.firstGreeting(); GreetingData greetingData = new GreetingData(greeting); return greetingData; } }

@Service public class GreetingApplicationService {

@Autowired private GreetingRepository repository;

public GreetingData welcomePeople() { Greeting greeting = repository.firstGreeting(); GreetingData greetingData = new GreetingData(greeting); return greetingData; } }

@Service public class GreetingApplicationService {

@Autowired private GreetingRepository repository;

public GreetingData welcomePeople() { Greeting greeting = repository.firstGreeting(); GreetingData greetingData = new GreetingData(greeting); return greetingData; } }

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

@Repository public class JpaGreetingRepository implements GreetingRepository {

@Autowired private HibernateGreetingRepository hibernateGreetingRepository;

@Override public Greeting firstGreeting() { Iterable<GreetingTable> rows = hibernateGreetingRepository.findAll(); GreetingTable r = rows.iterator().next(); Greeting greeting = new Greeting( new Salutation(r.getSalutation()), new Name(r.getName())); return greeting; } }

@Repository public class JpaGreetingRepository implements GreetingRepository {

@Autowired private HibernateGreetingRepository hibernateGreetingRepository;

@Override public Greeting firstGreeting() { Iterable<GreetingTable> rows = hibernateGreetingRepository.findAll(); GreetingTable r = rows.iterator().next(); Greeting greeting = new Greeting( new Salutation(r.getSalutation()), new Name(r.getName())); return greeting; } }

@Repository public class JpaGreetingRepository implements GreetingRepository {

@Autowired private HibernateGreetingRepository hibernateGreetingRepository;

@Override public Greeting firstGreeting() { Iterable<GreetingTable> rows = hibernateGreetingRepository.findAll(); GreetingTable r = rows.iterator().next(); Greeting greeting = new Greeting( new Salutation(r.getSalutation()), new Name(r.getName())); return greeting; } }

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

@SpringBootApplication @EnableAutoConfiguration public class XpdemoApplication {

public static void main(String[] args) { SpringApplication.run(XpdemoApplication.class, args); } }

@SpringBootApplication @EnableAutoConfiguration public class XpdemoApplication {

public static void main(String[] args) { SpringApplication.run(XpdemoApplication.class, args); } }

├── java │   └── de.neuland.xpdemo │   ├── XpdemoApplication.java │   ├── application │   │   ├── GreetingApplicationService.java │   │   └── GreetingData.java │   ├── domain.model │   │  ├── Greeting.java │   │ ├── GreetingInterest.java │   │ ├── GreetingRepository.java │   │ ├── Name.java │   │ └── Salutation.java │   └── port.adapter │   ├── persistence │   │   ├── GreetingTable.java │   │   ├── HibernateGreetingRepository.java │   │   └── JpaGreetingRepository.java │   └── web │   └── WebController.java └── resources ├── application.properties ├── static └── templates └── home.html

„Erkennung, Behandlung und Präventionvon Infektionskrankheiten“

P R Ä V E N T I O N

Bedside-Test your Code!

Quasar® AT0

Anti-TAnti-A

F R A G E N ?

Q U E L L E N

https://www.flickr.com/photos/23967095@N00/

Vaughn Vernon, Implementing Domain Driven Design

Johannes Siedersleben, Moderne Softwarearchitektur

http://www.laputan.org/mud/

Recommended