software hygiene€¦ · big ball of mud . johannes siedersleben sd&m quasar „software, die...
TRANSCRIPT
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/