+ All Categories
Home > Software > SOLID mit Java 8

SOLID mit Java 8

Date post: 13-Apr-2017
Category:
Upload: roland-mast
View: 159 times
Download: 1 times
Share this document with a friend
35
SOLID mit Java 8 Java Forum Stuttgart 2016
Transcript
Page 1: SOLID mit Java 8

SOLID mit Java 8

Java Forum Stuttgart 2016

Page 2: SOLID mit Java 8

Roland MastSybit GmbHAgiler Software-ArchitektScrum [email protected]

Page 3: SOLID mit Java 8

Roland MastSybit GmbHAgiler [email protected]

Page 4: SOLID mit Java 8

5 Principles

• Single responsibility

• Open Closed

• Liskov Substitution

• Interface Segregation

• Dependency Inversion

SOLID und Uncle Bob

Page 5: SOLID mit Java 8

Single ResponsibilityPrinciple?Single ResponsibilityPrinciple?

A class should have one, and only one, reason to change.

A class should have one, and only one, reason to change.

Page 6: SOLID mit Java 8

// 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

Page 7: SOLID mit Java 8

List<Person> persons = Arrays.asList(// name, age, sizenew 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 anstattif (age >= 18) {

keep();

}Collectors berechnet den Durchschnitt

Single Responsibility

Page 8: SOLID mit Java 8

public interface BinaryOperation {long identity();long binaryOperator(long a, long b);

}

public class Sum implements BinaryOperation {@Overridepublic long identity() { return 0L; }

@Overridepublic 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 SummenberechnungThreadpool muss selbst erzeugt werden

Page 9: SOLID mit Java 8

private long[] data;

public long sumUp() {return LongStream.of(data)

.parallel()

.reduce(0, (a, b) -> a + b);}

Parallel ReduceSingle Responsibility

Page 10: SOLID mit Java 8

Single Responsibility Principle

Lambdas + Streams

Kapseln Verantwortlichkeiten

Page 11: SOLID mit Java 8

Open/ClosedPrinciple?Open/ClosedPrinciple?

You should be able to extend a classes behavior, without modifying it.

You should be able to extend a classes behavior, without modifying it.

Page 12: SOLID mit Java 8

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

Page 13: SOLID mit Java 8

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

Page 14: SOLID mit Java 8

Open/Closed Principle

Default-Implementierungen in Interfaces

Flexibel Frameworks erweitern

Page 15: SOLID mit Java 8

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.

Page 16: SOLID mit Java 8

/*** 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

Page 17: SOLID mit Java 8

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

}}

Page 18: SOLID mit Java 8

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, walkwerfen UncheckedIOException beim Zugriff innerhalb des Streams

Page 19: SOLID mit Java 8

Liskov´s Substitution Principle

Files + BufferedReader

UncheckedIOException nur bei neuen Methoden

Page 20: SOLID mit Java 8

Interface Segregation Principle?Interface Segregation Principle?

Make fine grained interfaces that are client specific.

Make fine grained interfaces that are client specific.

Page 21: SOLID mit Java 8

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 mit3 Methoden

Page 22: SOLID mit Java 8

<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

Page 23: SOLID mit Java 8

withLinesOf(() -> reader,

lines -> lines.filter(line -> line.contains("ERROR")).map(line -> line.split(":")[1]).collect(toList()),

LogAnalyseException::new);

Functional InterfacesInterface Segregation

Page 24: SOLID mit Java 8

LocalTimeInterface Segregation

Page 25: SOLID mit Java 8

Interface Segregation Principle

Functional Interfaces

Ermutigen zum Auftrennen von Interfaces

Page 26: SOLID mit Java 8

Dependency Inversion Principle?Dependency Inversion Principle?

Depend on abstractions, not on concretions.Depend on abstractions, not on concretions.

Page 27: SOLID mit Java 8

Warning: JDK internal APIs are unsupported andprivate 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/Java+Dependency+Analysis+Tool

jdeps -jdkinternalsDependency Inversion

Page 28: SOLID mit Java 8

jdeps -jdkinternals classes

classes -> C:\Program Files\Java\jdk1.8.0_74\jre\lib\rt.jar

de.sybit.warranty.facade.impl.DefaultWarrantyFacade (classes)

-> com.sun.xml.internal.fastinfoset.stax.events.UtilJDK internal API (rt.jar)

jdepsDependency Inversion

return (Util.isEmptyString(param) || "*".equals(param));

Page 29: SOLID mit Java 8

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

Page 30: SOLID mit Java 8

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

Page 31: SOLID mit Java 8

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

Page 32: SOLID mit Java 8

Dependency Inversion Principle

Lambdas

Sind starke Abstraktionen

Page 33: SOLID mit Java 8

module MyClient {

requires MyService;

}

module MyService {

exports de.sybit.myservice;

}

SOLID mit Java 9 - Jigsaw

Page 34: SOLID mit Java 8

“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

Page 35: SOLID mit Java 8

Roland Mast, Sybit GmbHAgiler Software-Architekt

[email protected]


Recommended