SlideShare a Scribd company logo
SOLID mit Java 8
Java Forum Stuttgart 2016
Roland Mast
Sybit GmbH
Agiler Software-Architekt
Scrum Master
roland.mast@sybit.de
Roland Mast
Sybit GmbH
Agiler Software-Architekt
roland.mast@sybit.de
5 Principles
• Single responsibility
• Open Closed
• Liskov Substitution
• Interface Segregation
• Dependency Inversion
SOLID und Uncle Bob
Single Responsibility
Principle?
Single Responsibility
Principle?
A class should have
one, and only one,
reason to change.
A class should have
one, and only one,
reason to change.
// Strings in einem Array nach deren Länge sortieren
Arrays.sort(strings, new Comparator<String>() {
public int compare(String a, String b) {
return Integer.compare(a.length(), b.length());
}
});
Arrays.sort(strings, (a, b) -> Integer.compare(a.length(), b.length()));
// Strings alphabetisch sortieren
Arrays.sort(strings, String::compareToIgnoreCase);
Lambdas
List<Person> persons = Arrays.asList(
// name, age, size
new Person("Max", 18, 1.9),
new Person("Peter", 23, 1.8),
new Person("Pamela", 23, 1.6),
new Person("David", 12, 1.5));
Double averageSize = persons
.stream()
.filter(p -> p.age >= 18)
.collect(Collectors.averagingDouble(p -> p.size));
Lambdas in Streams
Iteration über
die Daten
Filtern anstatt
if (age >= 18) {
keep();
}
Collectors berechnet
den Durchschnitt
Single Responsibility
public interface BinaryOperation {
long identity();
long binaryOperator(long a, long b);
}
public class Sum implements BinaryOperation {
@Override
public long identity() { return 0L; }
@Override
public long binaryOperator(long a, long b) {
return a + b;
}
}
Single Responsibility
private long[] data;
public long solve() {
int threadCount = Runtime.getRuntime().availableProcessors();
ForkJoinPool pool = new ForkJoinPool(threadCount);
pool.invoke(this);
return res;
}
protected void compute() {
if (data.length == 1) {
res=operation.binaryOperator(operation.identity(), data[0]);
} else {
int midpoint = data.length / 2;
long[] l1 = Arrays.copyOfRange(data, 0, midpoint);
long[] l2 = Arrays.copyOfRange(data, midpoint, data.length);
SolverJ7 s1 = new SolverJ7(l1, operation);
SolverJ7 s2 = new SolverJ7(l2, operation);
ForkJoinTask.invokeAll(s1, s2);
res = operation.binaryOperator(s1.res, s2.res);
}
}
Daten müssen
selbst aufgeteilt und
zusammengeführt
werden
Interface
und Klasse
definieren
Operation
Parallele Summenberechnung
Threadpool muss selbst
erzeugt werden
private long[] data;
public long sumUp() {
return LongStream.of(data)
.parallel()
.reduce(0, (a, b) -> a + b);
}
Parallel ReduceSingle Responsibility
Single Responsibility Principle
Lambdas + Streams
Kapseln Verantwortlichkeiten
Open/Closed
Principle?
Open/Closed
Principle?
You should be able to
extend a classes
behavior, without
modifying it.
You should be able to
extend a classes
behavior, without
modifying it.
public interface Iterable<T> {
Iterator<T> iterator();
}
Iterable Interface
public interface Iterable<T> {
Iterator<T> iterator();
void forEach(Consumer<? super T> action);
Spliterator<T> spliterator();
}
Open/Closed
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
for (T t : this) { action.accept(t); }
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
Default-ImplementationOpen/Closed
Open/Closed Principle
Default-Implementierungen in Interfaces
Flexibel Frameworks erweitern
Liskov's Substitution
Principle?
Liskov's Substitution
Principle?
“No new exceptions should be thrown by methods of the subtype,
except where those exceptions are themselves subtypes of exceptions
thrown by the methods of the supertype.”
Derived classes must
be substitutable for
their base classes.
Derived classes must
be substitutable for
their base classes.
/**
* Find the first occurrence of a text in files
* given by a list of file names.
*/
public Optional<String> findFirst(
String text, List<String> fileNames) {
return fileNames.stream()
.map(name -> Paths.get(name))
.flatMap(path -> Files.lines(path))
.filter(s -> s.contains(text))
.findFirst();
}
Checked Exception in StreamsLiskov‘s Substitution
public final class Files {
public static Stream<String> lines(Path path)
throws IOException {
BufferedReader br =
Files.newBufferedReader(path);
try {
return br.lines()
.onClose(asUncheckedRunnable(br));
} catch (Error|RuntimeException e) {
….. 8< ……………………
br.close();
….. 8< ……………………
}
}
IOException
/**
* Find the first occurrence of a text in files
* given by a list of file names.
*/
public Optional<String> findFirst(
String text, List<String> fileNames) {
return fileNames.stream()
.map(name -> Paths.get(name))
.flatMap(path -> mylines(path))
.filter(s -> s.contains(text))
.findFirst();
}
Handle IOExceptionLiskov‘s Substitution
private Stream<String> mylines(Path path){
try (BufferedReader br =
Files.newBufferedReader(path)) {
return br.lines()
.onClose(asUncheckedRunnable(br));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private static Runnable asUncheckedRunnable(Closeable c) {
return () -> {
try {
c.close();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
};
}
Close StreamLiskov‘s Substitution
java.io.BufferedReader::lines +
java.nio.file.Files::find, lines, list, walk
werfen UncheckedIOException beim Zugriff innerhalb des Streams
Liskov´s Substitution Principle
Files + BufferedReader
UncheckedIOException nur bei neuen Methoden
Interface Segregation
Principle?
Interface Segregation
Principle?
Make fine grained
interfaces that are
client specific.
Make fine grained
interfaces that are
client specific.
public interface ParserContext {
Reader getReader();
void handleLine(String line);
void handleException(Exception e);
}
public void parse(final ParserContext context) {
try (BufferedReader br = new BufferedReader(context.getReader())) {
String line;
do {
line = br.readLine();
if (line != null) { context.handleLine(line); }
} while (line != null)
} catch (IOException e) { context.handleException(e); }
}
InterfacesInterface Segregation
1 Interface mit
3 Methoden
<T> T withLinesOf(Supplier<Reader> reader,
Function<Stream<String>, T> handleLines,
Function<Exception, RuntimeException> transformException) {
try (BufferedReader br = new BufferedReader(reader.get())) {
return handleLines.apply(br.lines());
} catch (IOException e) {
throw transformException.apply(e);
}
}
Functional InterfacesInterface Segregation
3 separate
Interfaces
withLinesOf(
() -> reader,
lines -> lines
.filter(line -> line.contains("ERROR"))
.map(line -> line.split(":")[1])
.collect(toList()),
LogAnalyseException::new);
Functional InterfacesInterface Segregation
LocalTimeInterface Segregation
Interface Segregation Principle
Functional Interfaces
Ermutigen zum Auftrennen von Interfaces
Dependency Inversion
Principle?
Dependency Inversion
Principle?
Depend on abstractions,
not on concretions.
Depend on abstractions,
not on concretions.
Warning: JDK internal APIs are unsupported and
private to JDK implementation that are
subject to be removed or changed incompatibly
and could break your application.
Please modify your code to eliminate
dependency on any JDK internal APIs.
For the most recent update on JDK internal API
replacements, please check:
https://wiki.openjdk.java.net/display/JDK8/Jav
a+Dependency+Analysis+Tool
jdeps -jdkinternalsDependency Inversion
jdeps -jdkinternals classes
classes -> C:Program FilesJavajdk1.8.0_74jrelibrt.jar
de.sybit.warranty.facade.impl.DefaultWarrantyFacade (classes)
-> com.sun.xml.internal.fastinfoset.stax.events.Util
JDK internal API (rt.jar)
jdepsDependency Inversion
return (Util.isEmptyString(param) || "*".equals(param));
public List<String> filterError(Reader reader) {
try (BufferedReader br =new BufferedReader(reader)){
return br.lines()
.filter(line -> line.contains("ERROR"))
.map(line -> line.split(":")[1])
.collect(toList());
} catch (IOException e) {
throw new LogAnalyseException(e);
}
}
LambdasDependency Inversion
Filterimplementierung ist
abhängig von konkreten
Implementierungen
private Parser parser = new Parser();
public List<String> filterError(Reader reader) {
return parser.withLinesOf(
reader,
lines -> lines
.filter(line -> line.contains("ERROR"))
.map(line -> line.split(":")[1])
.collect(toList()),
LogAnalyseException::new);
}
LambdasDependency Inversion
filterError() ist nur
noch abhängig von
Abstraktionen
public class Parser {
<T> T withLinesOf(Reader reader,
Function<Stream<String>, T> handleLines,
Function<Exception, RuntimeException> onError) {
try (BufferedReader br = new BufferedReader(reader)) {
return handleLines.apply(br.lines());
} catch (IOException e) {
throw onError.apply(e);
}
}
}
LambdasDependency Inversion
withLinesOf()
kapselt die
Abhängigkeiten
Dependency Inversion Principle
Lambdas
Sind starke Abstraktionen
module MyClient {
requires MyService;
}
module MyService {
exports de.sybit.myservice;
}
SOLID mit Java 9 - Jigsaw
“The principles of software design still apply, regardless
of your programming style. The fact that you've decided
to use a [functional] language that doesn't have an
assignment operator does not mean that you can ignore
the Single Responsibility Principle; or that the Open
Closed Principle is somehow automatic.”
Robert C. Martin: OO vs FP (24 November 2014)
http://blog.cleancoder.com/uncle-bob/2014/11/24/FPvsOO.html
SOLID mit Java – OO vs FP
Roland Mast, Sybit GmbH
Agiler Software-Architekt
roland.mast@sybit.de

More Related Content

PDF
SOLID Java Code
Omar Bashir
 
PPTX
Lecture - 5 Control Statement
manish kumar
 
PPT
Effective Java - Generics
Roshan Deniyage
 
PPTX
Lecture - 3 Variables-data type_operators_oops concept
manish kumar
 
PPTX
Structural pattern 3
Naga Muruga
 
PPTX
Lecture 6 inheritance
manish kumar
 
PPT
ITU - MDD - XText
Tonny Madsen
 
PPTX
Java generics final
Akshay Chaudhari
 
SOLID Java Code
Omar Bashir
 
Lecture - 5 Control Statement
manish kumar
 
Effective Java - Generics
Roshan Deniyage
 
Lecture - 3 Variables-data type_operators_oops concept
manish kumar
 
Structural pattern 3
Naga Muruga
 
Lecture 6 inheritance
manish kumar
 
ITU - MDD - XText
Tonny Madsen
 
Java generics final
Akshay Chaudhari
 

What's hot (20)

PPTX
Java interface
Md. Tanvir Hossain
 
PPT
Effective Java - Enum and Annotations
Roshan Deniyage
 
PPTX
Lecture 4_Java Method-constructor_imp_keywords
manish kumar
 
PPTX
Java generics
Hosein Zare
 
PDF
Java Generics - by Example
Ganesh Samarthyam
 
PPT
Core java concepts
Ram132
 
PDF
Methods in Java
Jussi Pohjolainen
 
PDF
On Parameterised Types and Java Generics
Yann-Gaël Guéhéneuc
 
PDF
Java Generics Introduction - Syntax Advantages and Pitfalls
Rakesh Waghela
 
PDF
Java Annotation Processing: A Beginner Walkthrough
Mahfuz Islam Bhuiyan
 
PPTX
Unit 4 exceptions and threads
DevaKumari Vijay
 
PDF
Java8 - Interfaces, evolved
Charles Casadei
 
PDF
Solid Deconstruction
Kevlin Henney
 
PPTX
Java Generics
DeeptiJava
 
PPT
Java Generics
jeslie
 
PDF
Java q ref 2018
Christopher Akinlade
 
PPT
Chapter 8 Inheritance
OUM SAOKOSAL
 
PPTX
Lecture - 2 Environment setup & JDK, JRE, JVM
manish kumar
 
PDF
Comparing different concurrency models on the JVM
Mario Fusco
 
PPTX
Java fundamentals
HCMUTE
 
Java interface
Md. Tanvir Hossain
 
Effective Java - Enum and Annotations
Roshan Deniyage
 
Lecture 4_Java Method-constructor_imp_keywords
manish kumar
 
Java generics
Hosein Zare
 
Java Generics - by Example
Ganesh Samarthyam
 
Core java concepts
Ram132
 
Methods in Java
Jussi Pohjolainen
 
On Parameterised Types and Java Generics
Yann-Gaël Guéhéneuc
 
Java Generics Introduction - Syntax Advantages and Pitfalls
Rakesh Waghela
 
Java Annotation Processing: A Beginner Walkthrough
Mahfuz Islam Bhuiyan
 
Unit 4 exceptions and threads
DevaKumari Vijay
 
Java8 - Interfaces, evolved
Charles Casadei
 
Solid Deconstruction
Kevlin Henney
 
Java Generics
DeeptiJava
 
Java Generics
jeslie
 
Java q ref 2018
Christopher Akinlade
 
Chapter 8 Inheritance
OUM SAOKOSAL
 
Lecture - 2 Environment setup & JDK, JRE, JVM
manish kumar
 
Comparing different concurrency models on the JVM
Mario Fusco
 
Java fundamentals
HCMUTE
 
Ad

Viewers also liked (10)

PDF
SOLID Design Principles applied in Java
Ionut Bilica
 
PDF
SOLID design principles applied in Java
Bucharest Java User Group
 
PPT
principles of object oriented class design
Neetu Mishra
 
PPTX
Robert martin
Shiraz316
 
PPTX
Java Code Quality Tools
Anju ML
 
PPTX
SOLID Principles of Refactoring Presentation - Inland Empire User Group
Adnan Masood
 
PPTX
Presentation CentOS
rommel gavia
 
PDF
SOLID Principles and Design Patterns
Ganesh Samarthyam
 
PPTX
Install Linux CentOS 7.0
Mehdi Poustchi Amin
 
PPT
BDD with JBehave and Selenium
Nikolay Vasilev
 
SOLID Design Principles applied in Java
Ionut Bilica
 
SOLID design principles applied in Java
Bucharest Java User Group
 
principles of object oriented class design
Neetu Mishra
 
Robert martin
Shiraz316
 
Java Code Quality Tools
Anju ML
 
SOLID Principles of Refactoring Presentation - Inland Empire User Group
Adnan Masood
 
Presentation CentOS
rommel gavia
 
SOLID Principles and Design Patterns
Ganesh Samarthyam
 
Install Linux CentOS 7.0
Mehdi Poustchi Amin
 
BDD with JBehave and Selenium
Nikolay Vasilev
 
Ad

Recently uploaded (20)

PDF
Teaching Reproducibility and Embracing Variability: From Floating-Point Exper...
University of Rennes, INSA Rennes, Inria/IRISA, CNRS
 
PPTX
GALILEO CRS SYSTEM | GALILEO TRAVEL SOFTWARE
philipnathen82
 
PDF
Jenkins: An open-source automation server powering CI/CD Automation
SaikatBasu37
 
PDF
Wondershare Filmora 14.5.20.12999 Crack Full New Version 2025
gsgssg2211
 
PDF
Bandai Playdia The Book - David Glotz
BluePanther6
 
PDF
49784907924775488180_LRN2959_Data_Pump_23ai.pdf
Abilash868456
 
PPTX
Web Testing.pptx528278vshbuqffqhhqiwnwuq
studylike474
 
PPTX
The-Dawn-of-AI-Reshaping-Our-World.pptxx
parthbhanushali307
 
PDF
Protecting the Digital World Cyber Securit
dnthakkar16
 
PDF
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
ESUG
 
PDF
Microsoft Teams Essentials; The pricing and the versions_PDF.pdf
Q-Advise
 
PPTX
Maximizing Revenue with Marketo Measure: A Deep Dive into Multi-Touch Attribu...
bbedford2
 
PPTX
ConcordeApp: Engineering Global Impact & Unlocking Billions in Event ROI with AI
chastechaste14
 
PPTX
Role Of Python In Programing Language.pptx
jaykoshti048
 
PPTX
oapresentation.pptx
mehatdhavalrajubhai
 
DOCX
Can You Build Dashboards Using Open Source Visualization Tool.docx
Varsha Nayak
 
PDF
On Software Engineers' Productivity - Beyond Misleading Metrics
Romén Rodríguez-Gil
 
PDF
advancepresentationskillshdhdhhdhdhdhhfhf
jasmenrojas249
 
PDF
Why Use Open Source Reporting Tools for Business Intelligence.pdf
Varsha Nayak
 
PPTX
PFAS Reporting Requirements 2026 Are You Submission Ready Certivo.pptx
Certivo Inc
 
Teaching Reproducibility and Embracing Variability: From Floating-Point Exper...
University of Rennes, INSA Rennes, Inria/IRISA, CNRS
 
GALILEO CRS SYSTEM | GALILEO TRAVEL SOFTWARE
philipnathen82
 
Jenkins: An open-source automation server powering CI/CD Automation
SaikatBasu37
 
Wondershare Filmora 14.5.20.12999 Crack Full New Version 2025
gsgssg2211
 
Bandai Playdia The Book - David Glotz
BluePanther6
 
49784907924775488180_LRN2959_Data_Pump_23ai.pdf
Abilash868456
 
Web Testing.pptx528278vshbuqffqhhqiwnwuq
studylike474
 
The-Dawn-of-AI-Reshaping-Our-World.pptxx
parthbhanushali307
 
Protecting the Digital World Cyber Securit
dnthakkar16
 
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
ESUG
 
Microsoft Teams Essentials; The pricing and the versions_PDF.pdf
Q-Advise
 
Maximizing Revenue with Marketo Measure: A Deep Dive into Multi-Touch Attribu...
bbedford2
 
ConcordeApp: Engineering Global Impact & Unlocking Billions in Event ROI with AI
chastechaste14
 
Role Of Python In Programing Language.pptx
jaykoshti048
 
oapresentation.pptx
mehatdhavalrajubhai
 
Can You Build Dashboards Using Open Source Visualization Tool.docx
Varsha Nayak
 
On Software Engineers' Productivity - Beyond Misleading Metrics
Romén Rodríguez-Gil
 
advancepresentationskillshdhdhhdhdhdhhfhf
jasmenrojas249
 
Why Use Open Source Reporting Tools for Business Intelligence.pdf
Varsha Nayak
 
PFAS Reporting Requirements 2026 Are You Submission Ready Certivo.pptx
Certivo Inc
 

SOLID mit Java 8

  • 1. SOLID mit Java 8 Java Forum Stuttgart 2016
  • 2. Roland Mast Sybit GmbH Agiler Software-Architekt Scrum Master [email protected]
  • 4. 5 Principles • Single responsibility • Open Closed • Liskov Substitution • Interface Segregation • Dependency Inversion SOLID und Uncle Bob
  • 5. Single Responsibility Principle? Single Responsibility Principle? A class should have one, and only one, reason to change. A class should have one, and only one, reason to change.
  • 6. // Strings in einem Array nach deren Länge sortieren Arrays.sort(strings, new Comparator<String>() { public int compare(String a, String b) { return Integer.compare(a.length(), b.length()); } }); Arrays.sort(strings, (a, b) -> Integer.compare(a.length(), b.length())); // Strings alphabetisch sortieren Arrays.sort(strings, String::compareToIgnoreCase); Lambdas
  • 7. List<Person> persons = Arrays.asList( // name, age, size new Person("Max", 18, 1.9), new Person("Peter", 23, 1.8), new Person("Pamela", 23, 1.6), new Person("David", 12, 1.5)); Double averageSize = persons .stream() .filter(p -> p.age >= 18) .collect(Collectors.averagingDouble(p -> p.size)); Lambdas in Streams Iteration über die Daten Filtern anstatt if (age >= 18) { keep(); } Collectors berechnet den Durchschnitt Single Responsibility
  • 8. public interface BinaryOperation { long identity(); long binaryOperator(long a, long b); } public class Sum implements BinaryOperation { @Override public long identity() { return 0L; } @Override public long binaryOperator(long a, long b) { return a + b; } } Single Responsibility private long[] data; public long solve() { int threadCount = Runtime.getRuntime().availableProcessors(); ForkJoinPool pool = new ForkJoinPool(threadCount); pool.invoke(this); return res; } protected void compute() { if (data.length == 1) { res=operation.binaryOperator(operation.identity(), data[0]); } else { int midpoint = data.length / 2; long[] l1 = Arrays.copyOfRange(data, 0, midpoint); long[] l2 = Arrays.copyOfRange(data, midpoint, data.length); SolverJ7 s1 = new SolverJ7(l1, operation); SolverJ7 s2 = new SolverJ7(l2, operation); ForkJoinTask.invokeAll(s1, s2); res = operation.binaryOperator(s1.res, s2.res); } } Daten müssen selbst aufgeteilt und zusammengeführt werden Interface und Klasse definieren Operation Parallele Summenberechnung Threadpool muss selbst erzeugt werden
  • 9. private long[] data; public long sumUp() { return LongStream.of(data) .parallel() .reduce(0, (a, b) -> a + b); } Parallel ReduceSingle Responsibility
  • 10. Single Responsibility Principle Lambdas + Streams Kapseln Verantwortlichkeiten
  • 11. Open/Closed Principle? Open/Closed Principle? You should be able to extend a classes behavior, without modifying it. You should be able to extend a classes behavior, without modifying it.
  • 12. public interface Iterable<T> { Iterator<T> iterator(); } Iterable Interface public interface Iterable<T> { Iterator<T> iterator(); void forEach(Consumer<? super T> action); Spliterator<T> spliterator(); } Open/Closed
  • 13. public interface Iterable<T> { Iterator<T> iterator(); default void forEach(Consumer<? super T> action) { for (T t : this) { action.accept(t); } } default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } } Default-ImplementationOpen/Closed
  • 14. Open/Closed Principle Default-Implementierungen in Interfaces Flexibel Frameworks erweitern
  • 15. Liskov's Substitution Principle? Liskov's Substitution Principle? “No new exceptions should be thrown by methods of the subtype, except where those exceptions are themselves subtypes of exceptions thrown by the methods of the supertype.” Derived classes must be substitutable for their base classes. Derived classes must be substitutable for their base classes.
  • 16. /** * Find the first occurrence of a text in files * given by a list of file names. */ public Optional<String> findFirst( String text, List<String> fileNames) { return fileNames.stream() .map(name -> Paths.get(name)) .flatMap(path -> Files.lines(path)) .filter(s -> s.contains(text)) .findFirst(); } Checked Exception in StreamsLiskov‘s Substitution public final class Files { public static Stream<String> lines(Path path) throws IOException { BufferedReader br = Files.newBufferedReader(path); try { return br.lines() .onClose(asUncheckedRunnable(br)); } catch (Error|RuntimeException e) { ….. 8< …………………… br.close(); ….. 8< …………………… } } IOException
  • 17. /** * Find the first occurrence of a text in files * given by a list of file names. */ public Optional<String> findFirst( String text, List<String> fileNames) { return fileNames.stream() .map(name -> Paths.get(name)) .flatMap(path -> mylines(path)) .filter(s -> s.contains(text)) .findFirst(); } Handle IOExceptionLiskov‘s Substitution private Stream<String> mylines(Path path){ try (BufferedReader br = Files.newBufferedReader(path)) { return br.lines() .onClose(asUncheckedRunnable(br)); } catch (IOException e) { throw new UncheckedIOException(e); } }
  • 18. private static Runnable asUncheckedRunnable(Closeable c) { return () -> { try { c.close(); } catch (IOException e) { throw new UncheckedIOException(e); } }; } Close StreamLiskov‘s Substitution java.io.BufferedReader::lines + java.nio.file.Files::find, lines, list, walk werfen UncheckedIOException beim Zugriff innerhalb des Streams
  • 19. Liskov´s Substitution Principle Files + BufferedReader UncheckedIOException nur bei neuen Methoden
  • 20. Interface Segregation Principle? Interface Segregation Principle? Make fine grained interfaces that are client specific. Make fine grained interfaces that are client specific.
  • 21. public interface ParserContext { Reader getReader(); void handleLine(String line); void handleException(Exception e); } public void parse(final ParserContext context) { try (BufferedReader br = new BufferedReader(context.getReader())) { String line; do { line = br.readLine(); if (line != null) { context.handleLine(line); } } while (line != null) } catch (IOException e) { context.handleException(e); } } InterfacesInterface Segregation 1 Interface mit 3 Methoden
  • 22. <T> T withLinesOf(Supplier<Reader> reader, Function<Stream<String>, T> handleLines, Function<Exception, RuntimeException> transformException) { try (BufferedReader br = new BufferedReader(reader.get())) { return handleLines.apply(br.lines()); } catch (IOException e) { throw transformException.apply(e); } } Functional InterfacesInterface Segregation 3 separate Interfaces
  • 23. withLinesOf( () -> reader, lines -> lines .filter(line -> line.contains("ERROR")) .map(line -> line.split(":")[1]) .collect(toList()), LogAnalyseException::new); Functional InterfacesInterface Segregation
  • 25. Interface Segregation Principle Functional Interfaces Ermutigen zum Auftrennen von Interfaces
  • 26. Dependency Inversion Principle? Dependency Inversion Principle? Depend on abstractions, not on concretions. Depend on abstractions, not on concretions.
  • 27. Warning: JDK internal APIs are unsupported and private to JDK implementation that are subject to be removed or changed incompatibly and could break your application. Please modify your code to eliminate dependency on any JDK internal APIs. For the most recent update on JDK internal API replacements, please check: https://wiki.openjdk.java.net/display/JDK8/Jav a+Dependency+Analysis+Tool jdeps -jdkinternalsDependency Inversion
  • 28. jdeps -jdkinternals classes classes -> C:Program FilesJavajdk1.8.0_74jrelibrt.jar de.sybit.warranty.facade.impl.DefaultWarrantyFacade (classes) -> com.sun.xml.internal.fastinfoset.stax.events.Util JDK internal API (rt.jar) jdepsDependency Inversion return (Util.isEmptyString(param) || "*".equals(param));
  • 29. public List<String> filterError(Reader reader) { try (BufferedReader br =new BufferedReader(reader)){ return br.lines() .filter(line -> line.contains("ERROR")) .map(line -> line.split(":")[1]) .collect(toList()); } catch (IOException e) { throw new LogAnalyseException(e); } } LambdasDependency Inversion Filterimplementierung ist abhängig von konkreten Implementierungen
  • 30. private Parser parser = new Parser(); public List<String> filterError(Reader reader) { return parser.withLinesOf( reader, lines -> lines .filter(line -> line.contains("ERROR")) .map(line -> line.split(":")[1]) .collect(toList()), LogAnalyseException::new); } LambdasDependency Inversion filterError() ist nur noch abhängig von Abstraktionen
  • 31. public class Parser { <T> T withLinesOf(Reader reader, Function<Stream<String>, T> handleLines, Function<Exception, RuntimeException> onError) { try (BufferedReader br = new BufferedReader(reader)) { return handleLines.apply(br.lines()); } catch (IOException e) { throw onError.apply(e); } } } LambdasDependency Inversion withLinesOf() kapselt die Abhängigkeiten
  • 33. module MyClient { requires MyService; } module MyService { exports de.sybit.myservice; } SOLID mit Java 9 - Jigsaw
  • 34. “The principles of software design still apply, regardless of your programming style. The fact that you've decided to use a [functional] language that doesn't have an assignment operator does not mean that you can ignore the Single Responsibility Principle; or that the Open Closed Principle is somehow automatic.” Robert C. Martin: OO vs FP (24 November 2014) http://blog.cleancoder.com/uncle-bob/2014/11/24/FPvsOO.html SOLID mit Java – OO vs FP
  • 35. Roland Mast, Sybit GmbH Agiler Software-Architekt [email protected]