SlideShare a Scribd company logo
1 of 53
Download to read offline
SOLID Java Code
Omar Bashir
https://uk.linkedin.com/in/obprofile
@OmarBashir_40
obashir@yahoo.com
Coding Humanely
● What if our code had feelings ?
● What if we treated people like we treat code ?
– e.g., Sir, you will need a foot transplant to be able to
use our latest range of trainers.
Desirable Code Qualities
● Simplicity
– Ease of understanding.
● Extensibility
– Ease of extending functionality.
● Flexibility
– Ease of adapting to the operating environment.
● Testability
– Ease of testing from units of code to the entire
systems
Challenges: Size and Complexity
● Problems
– Most real world problems requiring automation are
complex.
● Requirements
– Increasing demand for comprehensive automation.
● Solutions
– Resulting solutions are large and sophisticated.
Modularisation
● Decomposing large systems into smaller and
simpler parts.
– Functions and procedures.
– Classes and modules.
● Building the parts.
● Assembling the parts to complete the system.
● To achieve desirable code qualities parts should
be interchangeable.
Keys to Interchangeability
● Coupling
– Interdependence between different software modules.
– Low coupling is preferred as it allows flexibility and
extensibility.
– Low coupling via simple and stable interfaces.
● Cohesion
– Degree to which elements of a module functionally
belong together.
– Higher cohesion reduces complexity of components.
● Higher cohesion and low coupling enables
interchangeability.
Spot Issues ?
package app;
import calc.Calculator;
public class App {
public static void main(String[] args) {
String line = System.console().readLine();
String[] parts = line.split(" ");
Calculator.operand1 = Double.parseDouble(parts[0]);
Calculator.operator = parts[1].charAt(0);
Calculator.operand2 = Double.parseDouble(parts[2]);
Calculator.calculate();
}
}
Spot Issues ?
package app;
import calc.Calculator;
public class App {
public static void main(String[] args) {
String line = System.console().readLine();
String[] parts = line.split(" ");
Calculator.operand1 = Double.parseDouble(parts[0]);
Calculator.operator = parts[1].charAt(0);
Calculator.operand2 = Double.parseDouble(parts[2]);
Calculator.calculate();
}
}
High Coupling
Spot Issues ?
package calc;
public class Calculator {
public static double operand1;
public static double operand2;
public static char operator;
public static void calculate() {
double result = Double.NaN;
switch(operator) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
result = operand1 / operand2;
break;
default:
System.out.printf("Unrecognised operator %cn", operator);
}
System.out.printf("%f %c %f = %fn",
operand1, operator, operand2, result);
}
}
Spot Issues
package calc;
public class Calculator {
public static double operand1;
public static double operand2;
public static char operator;
public static void calculate() {
double result = Double.NaN;
switch(operator) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
result = operand1 / operand2;
break;
default:
System.out.printf("Unrecognised operator %cn", operator);
}
System.out.printf("%f %c %f = %fn",
operand1, operator, operand2, result);
}
}
High Coupling
Low Cohesion
Simplifying with SOLID
● Types of coupling
– Content coupling, Common coupling, Stamp coupling,
Control coupling, Data coupling.
● Types of cohesion
– Co-incidental cohesion, Logical cohesion, Temporal
cohesion, Procedural cohesion, Communicational
cohesion, Sequential cohesion, Functional cohesion.
● SOLID
– Five principles of object oriented programming.
– Aims to deliver extensible and maintainable software.
SOLID
● Single Responsibility Principle (SRP)
– A class should have a single responsibility.
● Open Close Principle (OCP)
– Open for extension but closed for modification.
● Liskov Substitution Principle (LSP)
– Substitution of objects by instances of sub-classes.
● Interface Segregation Principle (ISP)
– Many client specific interfaces instead of one big one.
● Dependency Inversion Principle (DIP)
– Depend on abstractions instead of implementations.
1
Single Responsibility Principle
Single Responsibility Principle
● A class should have one and only one reason
to change.
– A class should have only one responsibility.
● Promotes high cohesion and low coupling.
– High cohesion because of focused classes.
– Low coupling because of dependency on other
cohesive classes.
Example
public class MeanCalculator {
public double calculate(final String data) {
double sum = 0.0;
final String[] parsedData = data.split(",");
for (String item : parsedData) {
sum += Double.parseDouble(item);
}
return sum/parsedData.length;
}
}
Example
public class MeanCalculator {
public double calculate(final String data) {
double sum = 0.0;
final String[] parsedData = data.split(",");
for (String item : parsedData) {
sum += Double.parseDouble(item);
}
return sum/parsedData.length;
}
}
Example
public class MeanCalculator {
public double calculate(final String data) {
double sum = 0.0;
final String[] parsedData = data.split(",");
for (String item : parsedData) {
sum += Double.parseDouble(item);
}
return sum/parsedData.length;
}
}
Two reasons to change
1. Parsing
2. Computation
Example
Functional (Java 8) Implementation
public class MeanCalculator {
public double calculate(final List<Double> data) {
double sum = 0.0;
for (Double item : data) {
sum += item;
}
return sum/data.size();
}
}
public class MeanCalculator {
public double calculate(final List<Double> data) {
return data.
stream().
collect(Collectors.
averagingDouble(item -> item));
}
}
2
Open Close Principle
Open/Close Principle
● Software entities (Classes, methods, modules
etc.) should be open for extension but closed
for modification.
– Changing functionality need not require modifying
existing code.
● Preferred approaches,
– Inheritance,
– Composition of abstractions (plugins).
Example
public class Parser {
List<Double> parse(final String data) {
final String[] parsedCsv = data.split(",");
return toDoubleList(parsedCsv);
}
private List<Double> toDoubleList(final String[] data) {
final List<Double> list = new ArrayList<>();
for(String item: data) {
list.add(Double.parseDouble(item));
}
return list;
}
}
Example:Extendinga
ClosedParser
public class Parser {
public List<Double> parse(final String data, final Format format) {
String[] parsedData = null;
switch(format){
case CSV:
parsedData = data.split(",");
break;
case XML:
try {
parsedData = parseXml(data);
} catch (Exception exp) {
throw new IllegalArgumentException(exp);
}
break;
default:
throw new IllegalArgumentException(String.format("Unknown format %s", format));
}
return toDoubleList(parsedData);
}
/**
* Format: <DataList><Item>3</Item><Item>4.5</Item><Item>7.5</Item></DataList>
*/
private String[] parseXml(final String xmlString) throws Exception {
final Document xmlDoc = DocumentBuilderFactory.
newInstance().
newDocumentBuilder().
parse(new ByteArrayInputStream(xmlString.getBytes()));
final NodeList nodes = xmlDoc.getElementsByTagName("Item");
final String[] textList = new String[nodes.getLength()];
for (int i = 0; i < nodes.getLength(); i++) {
textList[i] = nodes.item(i).getTextContent().trim();
}
return textList;
}
private List<Double> toDoubleList(final String[] data) {
final List<Double> list = new ArrayList<>();
for(String item: data) {
list.add(Double.parseDouble(item));
}
return list;
}
}
public List<Double> parse(final String data,
final Format format) {
String[] parsedData = null;
switch(format){
case CSV:
parsedData = data.split(",");
break;
case XML:
try {
parsedData = parseXml(data);
} catch (Exception exp) {
throw new IllegalArgumentException(exp);
}
break;
default:
throw new IllegalArgumentException(
String.format("Unknown format %s", format));
}
Example: Opening With Template
Method
public abstract class Parser {
public List<Double> parse(final String data) {
final String[] parsedData = split(data);
return toDoubleList(parsedData);
}
protected abstract String[] split(final String data);
private List<Double> toDoubleList(final String[] data) {
final List<Double> list = new ArrayList<>();
for(String item: data) {
list.add(Double.parseDouble(item));
}
return list;
}
}
Example: Parser Using Streams
public abstract class Parser {
public List<Double> parse(final String data) {
final String[] parsedData = split(data);
return Arrays.asList(parsedData).stream().
map(item -> Double.parseDouble(item)).
collect(Collectors.toList());
}
protected abstract String[] split(final String data);
}
Example: Opening With Template
Method
public class CsvParser extends Parser {
@Override
protected String[] split(String data) {
return data.split(",");
}
}
public class XmlParser extends Parser {
/**
* Format:
* <DataList><Item>3</Item><Item>4.5</Item><Item>7.5</Item></DataList>
*/
@Override
protected String[] split(String data) {
String[] textList = null;
try {
final Document xmlDoc = DocumentBuilderFactory.
newInstance().
newDocumentBuilder().
parse(new ByteArrayInputStream(data.getBytes()));
final NodeList nodes = xmlDoc.getElementsByTagName("Item");
textList = new String[nodes.getLength()];
for (int i = 0; i < nodes.getLength(); i++) {
textList[i] = nodes.item(i).getTextContent().trim();
}
} catch (Exception exp) {
throw new IllegalArgumentException(exp);
}
return textList;
}
}
3
Liskov Substitution Principle
Liskov Substitution Principle
● Named after MIT professor Barbara Liskov.
● Functions that use references to base classes
must be able to use objects of the derived class
without knowing it.
– Derived classes must be substitutable for base class.
● Caution,
– Should not alter the behaviour of the application.
– Inheritance hierarchies should not violate domain
concepts.
● E.g., a square is a rectangle instead of both are shapes.
public class AvergerApp {
public static void main(String[] args) {
final List<String> params = Arrays.asList(args);
if ((params.size() != 2) ||
(params.stream().filter(i -> i.contains("=")).count() != 2)) {
System.err.println("Parameters: f=<CSV/XML> m=<message>");
} else {
final String format = params.stream().
filter(str -> str.contains("f")).findFirst().get().split("=")[1];
final String message = params.stream().
filter(str -> str.contains("m")).findFirst().get().split("=")[1];
final Parser parser = getParser(format);
final List<Double> data = parser.parse(message);
final double avg = new MeanCalculator().calculate(data);
System.out.printf("Average(%s) = %f", data, avg);
}
}
private static Parser getParser(final String format) {
Parser parser = null;
switch (format) {
case "CSV":
parser = new CsvParser();
break;
case "XML":
parser = new XmlParser();
break;
default:
throw new IllegalArgumentException("Unknown format " + format));
}
return parser;
}
}
public class AvergerApp {
public static void main(String[] args) {
final List<String> params = Arrays.asList(args);
if ((params.size() != 2) ||
(params.stream().filter(i -> i.contains("=")).count() != 2)) {
System.err.println("Parameters: f=<CSV/XML> m=<message>");
} else {
final String format = params.stream().
filter(str -> str.contains("f")).findFirst().get().split("=")[1];
final String message = params.stream().
filter(str -> str.contains("m")).findFirst().get().split("=")[1];
final Parser parser = getParser(format);
final List<Double> data = parser.parse(message);
final double avg = new MeanCalculator().calculate(data);
System.out.printf("Average(%s) = %f", data, avg);
}
}
private static Parser getParser(final String format) {
Parser parser = null;
switch (format) {
case "CSV":
parser = new CsvParser();
break;
case "XML":
parser = new XmlParser();
break;
default:
throw new IllegalArgumentException("Unknown format " + format));
}
return parser;
}
}
4
Interface Segregation Principle
Interface Segragation Principle
● Multiple fine grained client or domain specific
interfaces are better than few coarse grained
interfaces.
● Consequences
– Classes only implement interfaces that are
requirement specific.
– Client classes are exposed only to the functionality
that they need.
Example
public interface AuthorisationService {
boolean isAuthorised(String userId,
Resource resource,
Action action);
List<Entitlement> entitlementReport(String userId);
List<Group> membershipReport(String userId);
boolean entitle(Group group, Entitlement entitlement);
boolean entitle(String userId, Entitlement entitlement);
boolean add(String userId, Group group);
boolean remove(String userId, Group group);
boolean remove(String userId, Entitlement entitlement);
boolean remove(Group group, Entitlement entitlement);
}
Example
public interface AuthorisationService {
boolean isAuthorised(String userId,
Resource resource,
Action action);
List<Entitlement> entitlementReport(String userId);
List<Group> membershipReport(String userId);
boolean entitle(Group group, Entitlement entitlement);
boolean entitle(String userId, Entitlement entitlement);
boolean add(String userId, Group group);
boolean remove(String userId, Group group);
boolean remove(String userId, Entitlement entitlement);
boolean remove(Group group, Entitlement entitlement);
}
Example
public interface AuthorisationService {
boolean isAuthorised(String userId,
Resource resource,
Action action);
List<Entitlement> entitlementReport(String userId);
List<Group> membershipReport(String userId);
boolean entitle(Group group, Entitlement entitlement);
boolean entitle(String userId, Entitlement entitlement);
boolean add(String userId, Group group);
boolean remove(String userId, Group group);
boolean remove(String userId, Entitlement entitlement);
boolean remove(Group group, Entitlement entitlement);
}
Example: Segregating Interfaces
public interface EntitlementsModifier {
boolean entitle(Group group, Entitlement entitlement);
boolean entitle(String userId, Entitlement entitlement);
boolean add(String userId, Group group);
boolean remove(String userId, Group group);
boolean remove(String userId, Entitlement entitlement);
boolean remove(Group group, Entitlement entitlement);
}
public interface EntitlementsChecker {
boolean isAuthorised(String userId,
Resource resource,
Action action);
List<Entitlement> entitlementReport(String userId);
List<Group> membershipReport(String userId);
}
5
Dependency Inversion Principle
Dependency Inversion Principle
● High-level modules should not depend on low-
level modules.
– Both should depend on abstractions.
● Abstractions should not depend on details.
– Details should depend on abstractions.
● Dependencies are a risk,
– Details bind dependants to concrete implementations.
● This limits flexibility and extensibility.
– Abstractions provides independence to dependants.
● Dependants are able to select most suitable
implementations.
Example: Averaging Calculator
● A class that uses
– An averaging algorithm to process input.
– A parser to parse text input to a collection of doubles.
– Input and output classes.
● Input formats can change.
– Binding the calculator to a concrete parser and IO
makes it inflexible.
– Averaging calculator references a parser, an input and
an output interface.
– The application specifies the parser and IO needed.
Example: Parser
public interface IParser {
List<Double> parse(final String data);
}
public abstract class Parser implements IParser {
public List<Double> parse(final String data) {
final String[] parsedData = split(data);
return Arrays.asList(parsedData).stream().
map(item -> Double.parseDouble(item)).
collect(Collectors.toList());
}
protected abstract String[] split(final String data);
}
Example: Input
public interface IInput {
String read();
}
public class FixedInput implements IInput {
private final String data;
public FixedInput(final String data) {
this.data = data;
}
@Override
public String read() {
return data;
}
}
Example: Output
public interface IOutput {
void write(final List<Double> data,
final double average);
}
public class ConsoleOutput implements IOutput {
@Override
public void write(final List<Double> data,
final double average) {
System.out.printf("Average%s = %fn",
data, average);
}
}
Example: Mean Processor
public interface IProcessor {
double process(List<Double> data);
}
public class MeanProcessor implements IProcessor {
public double process(final List<Double> data) {
return data.stream().
collect(Collectors.
averagingDouble(item -> item));
}
}
Example: Averaging Calculator
public class AveragingCalculator {
final private IInput input;
final private IOutput output;
final private IProcessor algo;
final private IParser parser;
public AveragingCalculator(final IProcessor algo,
final IParser parser,
final IInput input,
final IOutput output) {
this.algo = algo;
this.parser = parser;
this.input = input;
this.output = output;
}
public void run() {
final String inputData = input.read();
final List<Double> data = parser.parse(inputData);
final double average = algo.process(data);
output.write(data, average);
}
}
Example: CSV Averaging App
public class CsvAveragingApp {
public static void main(String[] args) {
final IInput input = new FixedInput(args[0]);
final IOutput output = new ConsoleOutput();
final IParser parser = new CsvParser();
final IProcessor algo = new MeanProcessor();
final AveragingCalculator calc =
new AveragingCalculator(algo,
parser,
input,
Output);
calc.run();
}
}
Example: XML Averaging App
public class XmlAveragingApp {
public static void main(String[] args) {
final IInput input = new FixedInput(args[0]);
final IOutput output = new ConsoleOutput();
final IParser parser = new XmlParser();
final IProcessor algo = new MeanProcessor();
final AveragingCalculator calc =
new AveragingCalculator(algo,
parser,
input,
output);
calc.run();
}
}
Opposite of SOLID
Single Responsibility Principle
Open Close Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Opposite of SOLID
Single Responsibility Principle
Open Close Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
S
T
U
P
I
D
Opposite of SOLID
Single Responsibility Principle
Open Close Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Singletons
Tight Coupling
Untestability
Premature Optimisation
Indescriptive Naming
Duplication
SOLID Java Code

More Related Content

Similar to SOLID Java Code

External Language Stored Procedures for MySQL
External Language Stored Procedures for MySQLExternal Language Stored Procedures for MySQL
External Language Stored Procedures for MySQLAntony T Curtis
 
Addressing Scenario
Addressing ScenarioAddressing Scenario
Addressing ScenarioTara Hardin
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionKent Huang
 
Ensure code quality with vs2012
Ensure code quality with vs2012Ensure code quality with vs2012
Ensure code quality with vs2012Sandeep Joshi
 
Flink Batch Processing and Iterations
Flink Batch Processing and IterationsFlink Batch Processing and Iterations
Flink Batch Processing and IterationsSameer Wadkar
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
Java fundamentals
Java fundamentalsJava fundamentals
Java fundamentalsHCMUTE
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeDaniel Wellman
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good TestsTomek Kaczanowski
 
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...Akaks
 
Functional Programming in Java 8
Functional Programming in Java 8Functional Programming in Java 8
Functional Programming in Java 8Omar Bashir
 
Chapter i(introduction to java)
Chapter i(introduction to java)Chapter i(introduction to java)
Chapter i(introduction to java)Chhom Karath
 
Advanced data structures slide 1 2
Advanced data structures slide 1 2Advanced data structures slide 1 2
Advanced data structures slide 1 2jomerson remorosa
 

Similar to SOLID Java Code (20)

Week 12 code
Week 12 codeWeek 12 code
Week 12 code
 
External Language Stored Procedures for MySQL
External Language Stored Procedures for MySQLExternal Language Stored Procedures for MySQL
External Language Stored Procedures for MySQL
 
Functional Programming
Functional ProgrammingFunctional Programming
Functional Programming
 
Addressing Scenario
Addressing ScenarioAddressing Scenario
Addressing Scenario
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
Wien15 java8
Wien15 java8Wien15 java8
Wien15 java8
 
Ensure code quality with vs2012
Ensure code quality with vs2012Ensure code quality with vs2012
Ensure code quality with vs2012
 
Flink Batch Processing and Iterations
Flink Batch Processing and IterationsFlink Batch Processing and Iterations
Flink Batch Processing and Iterations
 
00_Introduction to Java.ppt
00_Introduction to Java.ppt00_Introduction to Java.ppt
00_Introduction to Java.ppt
 
Chapter 2
Chapter 2Chapter 2
Chapter 2
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Java fundamentals
Java fundamentalsJava fundamentals
Java fundamentals
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy Code
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
 
Functional Programming in Java 8
Functional Programming in Java 8Functional Programming in Java 8
Functional Programming in Java 8
 
Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
Writing MySQL UDFs
Writing MySQL UDFsWriting MySQL UDFs
Writing MySQL UDFs
 
Chapter i(introduction to java)
Chapter i(introduction to java)Chapter i(introduction to java)
Chapter i(introduction to java)
 
Advanced data structures slide 1 2
Advanced data structures slide 1 2Advanced data structures slide 1 2
Advanced data structures slide 1 2
 

More from Omar Bashir

Cloud migration challenges london ct os
Cloud migration challenges   london ct osCloud migration challenges   london ct os
Cloud migration challenges london ct osOmar Bashir
 
5 Software Development Lessons From a Mountaineer
5 Software Development Lessons From a Mountaineer5 Software Development Lessons From a Mountaineer
5 Software Development Lessons From a MountaineerOmar Bashir
 
Technology Agility
Technology AgilityTechnology Agility
Technology AgilityOmar Bashir
 
Quality Loopback
Quality LoopbackQuality Loopback
Quality LoopbackOmar Bashir
 
Achieving Technological Agility
Achieving Technological AgilityAchieving Technological Agility
Achieving Technological AgilityOmar Bashir
 
Technical Debt: Measured and Implied
Technical Debt: Measured and ImpliedTechnical Debt: Measured and Implied
Technical Debt: Measured and ImpliedOmar Bashir
 
Distilling Agile for Effective Execution
Distilling Agile for Effective ExecutionDistilling Agile for Effective Execution
Distilling Agile for Effective ExecutionOmar Bashir
 
Authorisation: Concepts and Implementation
Authorisation: Concepts and ImplementationAuthorisation: Concepts and Implementation
Authorisation: Concepts and ImplementationOmar Bashir
 
Coding for 11 Year Olds
Coding for 11 Year OldsCoding for 11 Year Olds
Coding for 11 Year OldsOmar Bashir
 
High Speed Networks - Applications in Finance
High Speed Networks - Applications in FinanceHigh Speed Networks - Applications in Finance
High Speed Networks - Applications in FinanceOmar Bashir
 
An Introduction to Java Compiler and Runtime
An Introduction to Java Compiler and RuntimeAn Introduction to Java Compiler and Runtime
An Introduction to Java Compiler and RuntimeOmar Bashir
 
Computing at Schools: A Guide to Parents
Computing at Schools: A Guide to ParentsComputing at Schools: A Guide to Parents
Computing at Schools: A Guide to ParentsOmar Bashir
 
Information technology
Information technologyInformation technology
Information technologyOmar Bashir
 
Maths with Programming
Maths with ProgrammingMaths with Programming
Maths with ProgrammingOmar Bashir
 
Code Club Talk 2014
Code Club Talk 2014Code Club Talk 2014
Code Club Talk 2014Omar Bashir
 

More from Omar Bashir (16)

Cloud migration challenges london ct os
Cloud migration challenges   london ct osCloud migration challenges   london ct os
Cloud migration challenges london ct os
 
5 Software Development Lessons From a Mountaineer
5 Software Development Lessons From a Mountaineer5 Software Development Lessons From a Mountaineer
5 Software Development Lessons From a Mountaineer
 
Why Java ?
Why Java ?Why Java ?
Why Java ?
 
Technology Agility
Technology AgilityTechnology Agility
Technology Agility
 
Quality Loopback
Quality LoopbackQuality Loopback
Quality Loopback
 
Achieving Technological Agility
Achieving Technological AgilityAchieving Technological Agility
Achieving Technological Agility
 
Technical Debt: Measured and Implied
Technical Debt: Measured and ImpliedTechnical Debt: Measured and Implied
Technical Debt: Measured and Implied
 
Distilling Agile for Effective Execution
Distilling Agile for Effective ExecutionDistilling Agile for Effective Execution
Distilling Agile for Effective Execution
 
Authorisation: Concepts and Implementation
Authorisation: Concepts and ImplementationAuthorisation: Concepts and Implementation
Authorisation: Concepts and Implementation
 
Coding for 11 Year Olds
Coding for 11 Year OldsCoding for 11 Year Olds
Coding for 11 Year Olds
 
High Speed Networks - Applications in Finance
High Speed Networks - Applications in FinanceHigh Speed Networks - Applications in Finance
High Speed Networks - Applications in Finance
 
An Introduction to Java Compiler and Runtime
An Introduction to Java Compiler and RuntimeAn Introduction to Java Compiler and Runtime
An Introduction to Java Compiler and Runtime
 
Computing at Schools: A Guide to Parents
Computing at Schools: A Guide to ParentsComputing at Schools: A Guide to Parents
Computing at Schools: A Guide to Parents
 
Information technology
Information technologyInformation technology
Information technology
 
Maths with Programming
Maths with ProgrammingMaths with Programming
Maths with Programming
 
Code Club Talk 2014
Code Club Talk 2014Code Club Talk 2014
Code Club Talk 2014
 

Recently uploaded

Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxRTS corp
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLionel Briand
 
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesKrzysztofKkol1
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
Patterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencePatterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencessuser9e7c64
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...Bert Jan Schrijver
 
SoftTeco - Software Development Company Profile
SoftTeco - Software Development Company ProfileSoftTeco - Software Development Company Profile
SoftTeco - Software Development Company Profileakrivarotava
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorTier1 app
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZABSYZ Inc
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identityteam-WIBU
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
VictoriaMetrics Anomaly Detection Updates: Q1 2024
VictoriaMetrics Anomaly Detection Updates: Q1 2024VictoriaMetrics Anomaly Detection Updates: Q1 2024
VictoriaMetrics Anomaly Detection Updates: Q1 2024VictoriaMetrics
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfkalichargn70th171
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldRoberto Pérez Alcolea
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?Alexandre Beguel
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shardsChristopher Curtin
 

Recently uploaded (20)

Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and Repair
 
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
Patterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencePatterns for automating API delivery. API conference
Patterns for automating API delivery. API conference
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
 
SoftTeco - Software Development Company Profile
SoftTeco - Software Development Company ProfileSoftTeco - Software Development Company Profile
SoftTeco - Software Development Company Profile
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryError
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZ
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identity
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
VictoriaMetrics Anomaly Detection Updates: Q1 2024
VictoriaMetrics Anomaly Detection Updates: Q1 2024VictoriaMetrics Anomaly Detection Updates: Q1 2024
VictoriaMetrics Anomaly Detection Updates: Q1 2024
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards
 

SOLID Java Code

  • 1. SOLID Java Code Omar Bashir https://uk.linkedin.com/in/obprofile @OmarBashir_40 obashir@yahoo.com
  • 2. Coding Humanely ● What if our code had feelings ? ● What if we treated people like we treat code ? – e.g., Sir, you will need a foot transplant to be able to use our latest range of trainers.
  • 3. Desirable Code Qualities ● Simplicity – Ease of understanding. ● Extensibility – Ease of extending functionality. ● Flexibility – Ease of adapting to the operating environment. ● Testability – Ease of testing from units of code to the entire systems
  • 4. Challenges: Size and Complexity ● Problems – Most real world problems requiring automation are complex. ● Requirements – Increasing demand for comprehensive automation. ● Solutions – Resulting solutions are large and sophisticated.
  • 5.
  • 6. Modularisation ● Decomposing large systems into smaller and simpler parts. – Functions and procedures. – Classes and modules. ● Building the parts. ● Assembling the parts to complete the system. ● To achieve desirable code qualities parts should be interchangeable.
  • 7. Keys to Interchangeability ● Coupling – Interdependence between different software modules. – Low coupling is preferred as it allows flexibility and extensibility. – Low coupling via simple and stable interfaces. ● Cohesion – Degree to which elements of a module functionally belong together. – Higher cohesion reduces complexity of components. ● Higher cohesion and low coupling enables interchangeability.
  • 8. Spot Issues ? package app; import calc.Calculator; public class App { public static void main(String[] args) { String line = System.console().readLine(); String[] parts = line.split(" "); Calculator.operand1 = Double.parseDouble(parts[0]); Calculator.operator = parts[1].charAt(0); Calculator.operand2 = Double.parseDouble(parts[2]); Calculator.calculate(); } }
  • 9. Spot Issues ? package app; import calc.Calculator; public class App { public static void main(String[] args) { String line = System.console().readLine(); String[] parts = line.split(" "); Calculator.operand1 = Double.parseDouble(parts[0]); Calculator.operator = parts[1].charAt(0); Calculator.operand2 = Double.parseDouble(parts[2]); Calculator.calculate(); } } High Coupling
  • 10. Spot Issues ? package calc; public class Calculator { public static double operand1; public static double operand2; public static char operator; public static void calculate() { double result = Double.NaN; switch(operator) { case '+': result = operand1 + operand2; break; case '-': result = operand1 - operand2; break; case '*': result = operand1 * operand2; break; case '/': result = operand1 / operand2; break; default: System.out.printf("Unrecognised operator %cn", operator); } System.out.printf("%f %c %f = %fn", operand1, operator, operand2, result); } }
  • 11. Spot Issues package calc; public class Calculator { public static double operand1; public static double operand2; public static char operator; public static void calculate() { double result = Double.NaN; switch(operator) { case '+': result = operand1 + operand2; break; case '-': result = operand1 - operand2; break; case '*': result = operand1 * operand2; break; case '/': result = operand1 / operand2; break; default: System.out.printf("Unrecognised operator %cn", operator); } System.out.printf("%f %c %f = %fn", operand1, operator, operand2, result); } } High Coupling Low Cohesion
  • 12. Simplifying with SOLID ● Types of coupling – Content coupling, Common coupling, Stamp coupling, Control coupling, Data coupling. ● Types of cohesion – Co-incidental cohesion, Logical cohesion, Temporal cohesion, Procedural cohesion, Communicational cohesion, Sequential cohesion, Functional cohesion. ● SOLID – Five principles of object oriented programming. – Aims to deliver extensible and maintainable software.
  • 13. SOLID ● Single Responsibility Principle (SRP) – A class should have a single responsibility. ● Open Close Principle (OCP) – Open for extension but closed for modification. ● Liskov Substitution Principle (LSP) – Substitution of objects by instances of sub-classes. ● Interface Segregation Principle (ISP) – Many client specific interfaces instead of one big one. ● Dependency Inversion Principle (DIP) – Depend on abstractions instead of implementations.
  • 15. Single Responsibility Principle ● A class should have one and only one reason to change. – A class should have only one responsibility. ● Promotes high cohesion and low coupling. – High cohesion because of focused classes. – Low coupling because of dependency on other cohesive classes.
  • 16. Example public class MeanCalculator { public double calculate(final String data) { double sum = 0.0; final String[] parsedData = data.split(","); for (String item : parsedData) { sum += Double.parseDouble(item); } return sum/parsedData.length; } }
  • 17. Example public class MeanCalculator { public double calculate(final String data) { double sum = 0.0; final String[] parsedData = data.split(","); for (String item : parsedData) { sum += Double.parseDouble(item); } return sum/parsedData.length; } }
  • 18. Example public class MeanCalculator { public double calculate(final String data) { double sum = 0.0; final String[] parsedData = data.split(","); for (String item : parsedData) { sum += Double.parseDouble(item); } return sum/parsedData.length; } } Two reasons to change 1. Parsing 2. Computation
  • 19. Example Functional (Java 8) Implementation public class MeanCalculator { public double calculate(final List<Double> data) { double sum = 0.0; for (Double item : data) { sum += item; } return sum/data.size(); } } public class MeanCalculator { public double calculate(final List<Double> data) { return data. stream(). collect(Collectors. averagingDouble(item -> item)); } }
  • 21. Open/Close Principle ● Software entities (Classes, methods, modules etc.) should be open for extension but closed for modification. – Changing functionality need not require modifying existing code. ● Preferred approaches, – Inheritance, – Composition of abstractions (plugins).
  • 22. Example public class Parser { List<Double> parse(final String data) { final String[] parsedCsv = data.split(","); return toDoubleList(parsedCsv); } private List<Double> toDoubleList(final String[] data) { final List<Double> list = new ArrayList<>(); for(String item: data) { list.add(Double.parseDouble(item)); } return list; } }
  • 23. Example:Extendinga ClosedParser public class Parser { public List<Double> parse(final String data, final Format format) { String[] parsedData = null; switch(format){ case CSV: parsedData = data.split(","); break; case XML: try { parsedData = parseXml(data); } catch (Exception exp) { throw new IllegalArgumentException(exp); } break; default: throw new IllegalArgumentException(String.format("Unknown format %s", format)); } return toDoubleList(parsedData); } /** * Format: <DataList><Item>3</Item><Item>4.5</Item><Item>7.5</Item></DataList> */ private String[] parseXml(final String xmlString) throws Exception { final Document xmlDoc = DocumentBuilderFactory. newInstance(). newDocumentBuilder(). parse(new ByteArrayInputStream(xmlString.getBytes())); final NodeList nodes = xmlDoc.getElementsByTagName("Item"); final String[] textList = new String[nodes.getLength()]; for (int i = 0; i < nodes.getLength(); i++) { textList[i] = nodes.item(i).getTextContent().trim(); } return textList; } private List<Double> toDoubleList(final String[] data) { final List<Double> list = new ArrayList<>(); for(String item: data) { list.add(Double.parseDouble(item)); } return list; } }
  • 24. public List<Double> parse(final String data, final Format format) { String[] parsedData = null; switch(format){ case CSV: parsedData = data.split(","); break; case XML: try { parsedData = parseXml(data); } catch (Exception exp) { throw new IllegalArgumentException(exp); } break; default: throw new IllegalArgumentException( String.format("Unknown format %s", format)); }
  • 25. Example: Opening With Template Method public abstract class Parser { public List<Double> parse(final String data) { final String[] parsedData = split(data); return toDoubleList(parsedData); } protected abstract String[] split(final String data); private List<Double> toDoubleList(final String[] data) { final List<Double> list = new ArrayList<>(); for(String item: data) { list.add(Double.parseDouble(item)); } return list; } }
  • 26. Example: Parser Using Streams public abstract class Parser { public List<Double> parse(final String data) { final String[] parsedData = split(data); return Arrays.asList(parsedData).stream(). map(item -> Double.parseDouble(item)). collect(Collectors.toList()); } protected abstract String[] split(final String data); }
  • 27. Example: Opening With Template Method public class CsvParser extends Parser { @Override protected String[] split(String data) { return data.split(","); } }
  • 28. public class XmlParser extends Parser { /** * Format: * <DataList><Item>3</Item><Item>4.5</Item><Item>7.5</Item></DataList> */ @Override protected String[] split(String data) { String[] textList = null; try { final Document xmlDoc = DocumentBuilderFactory. newInstance(). newDocumentBuilder(). parse(new ByteArrayInputStream(data.getBytes())); final NodeList nodes = xmlDoc.getElementsByTagName("Item"); textList = new String[nodes.getLength()]; for (int i = 0; i < nodes.getLength(); i++) { textList[i] = nodes.item(i).getTextContent().trim(); } } catch (Exception exp) { throw new IllegalArgumentException(exp); } return textList; } }
  • 30. Liskov Substitution Principle ● Named after MIT professor Barbara Liskov. ● Functions that use references to base classes must be able to use objects of the derived class without knowing it. – Derived classes must be substitutable for base class. ● Caution, – Should not alter the behaviour of the application. – Inheritance hierarchies should not violate domain concepts. ● E.g., a square is a rectangle instead of both are shapes.
  • 31. public class AvergerApp { public static void main(String[] args) { final List<String> params = Arrays.asList(args); if ((params.size() != 2) || (params.stream().filter(i -> i.contains("=")).count() != 2)) { System.err.println("Parameters: f=<CSV/XML> m=<message>"); } else { final String format = params.stream(). filter(str -> str.contains("f")).findFirst().get().split("=")[1]; final String message = params.stream(). filter(str -> str.contains("m")).findFirst().get().split("=")[1]; final Parser parser = getParser(format); final List<Double> data = parser.parse(message); final double avg = new MeanCalculator().calculate(data); System.out.printf("Average(%s) = %f", data, avg); } } private static Parser getParser(final String format) { Parser parser = null; switch (format) { case "CSV": parser = new CsvParser(); break; case "XML": parser = new XmlParser(); break; default: throw new IllegalArgumentException("Unknown format " + format)); } return parser; } }
  • 32. public class AvergerApp { public static void main(String[] args) { final List<String> params = Arrays.asList(args); if ((params.size() != 2) || (params.stream().filter(i -> i.contains("=")).count() != 2)) { System.err.println("Parameters: f=<CSV/XML> m=<message>"); } else { final String format = params.stream(). filter(str -> str.contains("f")).findFirst().get().split("=")[1]; final String message = params.stream(). filter(str -> str.contains("m")).findFirst().get().split("=")[1]; final Parser parser = getParser(format); final List<Double> data = parser.parse(message); final double avg = new MeanCalculator().calculate(data); System.out.printf("Average(%s) = %f", data, avg); } } private static Parser getParser(final String format) { Parser parser = null; switch (format) { case "CSV": parser = new CsvParser(); break; case "XML": parser = new XmlParser(); break; default: throw new IllegalArgumentException("Unknown format " + format)); } return parser; } }
  • 34. Interface Segragation Principle ● Multiple fine grained client or domain specific interfaces are better than few coarse grained interfaces. ● Consequences – Classes only implement interfaces that are requirement specific. – Client classes are exposed only to the functionality that they need.
  • 35. Example public interface AuthorisationService { boolean isAuthorised(String userId, Resource resource, Action action); List<Entitlement> entitlementReport(String userId); List<Group> membershipReport(String userId); boolean entitle(Group group, Entitlement entitlement); boolean entitle(String userId, Entitlement entitlement); boolean add(String userId, Group group); boolean remove(String userId, Group group); boolean remove(String userId, Entitlement entitlement); boolean remove(Group group, Entitlement entitlement); }
  • 36. Example public interface AuthorisationService { boolean isAuthorised(String userId, Resource resource, Action action); List<Entitlement> entitlementReport(String userId); List<Group> membershipReport(String userId); boolean entitle(Group group, Entitlement entitlement); boolean entitle(String userId, Entitlement entitlement); boolean add(String userId, Group group); boolean remove(String userId, Group group); boolean remove(String userId, Entitlement entitlement); boolean remove(Group group, Entitlement entitlement); }
  • 37. Example public interface AuthorisationService { boolean isAuthorised(String userId, Resource resource, Action action); List<Entitlement> entitlementReport(String userId); List<Group> membershipReport(String userId); boolean entitle(Group group, Entitlement entitlement); boolean entitle(String userId, Entitlement entitlement); boolean add(String userId, Group group); boolean remove(String userId, Group group); boolean remove(String userId, Entitlement entitlement); boolean remove(Group group, Entitlement entitlement); }
  • 38. Example: Segregating Interfaces public interface EntitlementsModifier { boolean entitle(Group group, Entitlement entitlement); boolean entitle(String userId, Entitlement entitlement); boolean add(String userId, Group group); boolean remove(String userId, Group group); boolean remove(String userId, Entitlement entitlement); boolean remove(Group group, Entitlement entitlement); } public interface EntitlementsChecker { boolean isAuthorised(String userId, Resource resource, Action action); List<Entitlement> entitlementReport(String userId); List<Group> membershipReport(String userId); }
  • 40. Dependency Inversion Principle ● High-level modules should not depend on low- level modules. – Both should depend on abstractions. ● Abstractions should not depend on details. – Details should depend on abstractions. ● Dependencies are a risk, – Details bind dependants to concrete implementations. ● This limits flexibility and extensibility. – Abstractions provides independence to dependants. ● Dependants are able to select most suitable implementations.
  • 41. Example: Averaging Calculator ● A class that uses – An averaging algorithm to process input. – A parser to parse text input to a collection of doubles. – Input and output classes. ● Input formats can change. – Binding the calculator to a concrete parser and IO makes it inflexible. – Averaging calculator references a parser, an input and an output interface. – The application specifies the parser and IO needed.
  • 42. Example: Parser public interface IParser { List<Double> parse(final String data); } public abstract class Parser implements IParser { public List<Double> parse(final String data) { final String[] parsedData = split(data); return Arrays.asList(parsedData).stream(). map(item -> Double.parseDouble(item)). collect(Collectors.toList()); } protected abstract String[] split(final String data); }
  • 43. Example: Input public interface IInput { String read(); } public class FixedInput implements IInput { private final String data; public FixedInput(final String data) { this.data = data; } @Override public String read() { return data; } }
  • 44. Example: Output public interface IOutput { void write(final List<Double> data, final double average); } public class ConsoleOutput implements IOutput { @Override public void write(final List<Double> data, final double average) { System.out.printf("Average%s = %fn", data, average); } }
  • 45. Example: Mean Processor public interface IProcessor { double process(List<Double> data); } public class MeanProcessor implements IProcessor { public double process(final List<Double> data) { return data.stream(). collect(Collectors. averagingDouble(item -> item)); } }
  • 46. Example: Averaging Calculator public class AveragingCalculator { final private IInput input; final private IOutput output; final private IProcessor algo; final private IParser parser; public AveragingCalculator(final IProcessor algo, final IParser parser, final IInput input, final IOutput output) { this.algo = algo; this.parser = parser; this.input = input; this.output = output; } public void run() { final String inputData = input.read(); final List<Double> data = parser.parse(inputData); final double average = algo.process(data); output.write(data, average); } }
  • 47. Example: CSV Averaging App public class CsvAveragingApp { public static void main(String[] args) { final IInput input = new FixedInput(args[0]); final IOutput output = new ConsoleOutput(); final IParser parser = new CsvParser(); final IProcessor algo = new MeanProcessor(); final AveragingCalculator calc = new AveragingCalculator(algo, parser, input, Output); calc.run(); } }
  • 48. Example: XML Averaging App public class XmlAveragingApp { public static void main(String[] args) { final IInput input = new FixedInput(args[0]); final IOutput output = new ConsoleOutput(); final IParser parser = new XmlParser(); final IProcessor algo = new MeanProcessor(); final AveragingCalculator calc = new AveragingCalculator(algo, parser, input, output); calc.run(); } }
  • 49.
  • 50. Opposite of SOLID Single Responsibility Principle Open Close Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle
  • 51. Opposite of SOLID Single Responsibility Principle Open Close Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle S T U P I D
  • 52. Opposite of SOLID Single Responsibility Principle Open Close Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle Singletons Tight Coupling Untestability Premature Optimisation Indescriptive Naming Duplication