Principles and Patterns 26 February, 2020
Recap Principles Patterns Inheritance Anti-patterns Lecture overview • agile development • agile design • principles and patterns • software testing Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Lecture overview • agile development • agile design • principles and patterns • software testing Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Recap: agile development • A mindset: • Adaptability: be prepared for changing requirements; react to changes in the world • Communication: work closely with the client, communicate in-team all the time • Respect and responsibility: developers have input on planning and priorities, but are responsible for their results • Scrum Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Recap: agile design • How to write code that supports changing requirements? • information hiding • low coupling • high cohesion • Incremental design • avoid premature generalisation • when a possible improvement presents itself, refactor Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Today: principles and patterns • Principles: rules you adhere to in your code • setting rules can be important in team work • tried and tested principles that help keep coupling low and cohesion high • Patterns: standardised solutions • often recurring problems have standard solutions • note: some modern languages implement patterns as language features • Anti-patterns: bad solutions • often recurring problems have bad solutions that are often used Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Design and workflow principles to maintain simplicity • Principle of Least Astonishment • You Aren’t Gonna Need It • Once and Only Once • Fail Fast • Self-Documenting Code • Isolate Third-Party Components • Limit Published Interfaces Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns The SOLID principles • Single Responsibility Principle • Open-Closed Principle • Liskov’s Substitution Principle • Interface Segregation Principle • Dependency Inversion Principle Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Single Responsibility Principle Every module/class should have responsibility over a single part of the functionality, and that responsibility should be entirely encapsulated by the class. • A module/class should have only one reason to change. • Bad example: a module that compiles and prints a report. • Good example: a module that compiles a report. • Good example: a module that is responsible for arithmetic reasoning. • large responsibility, but only one responsibility • may contain sub-modules for specific sub-responsibilities • Note: a responsibility should not contain “and”. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns The Open-Closed Principle Entities should be open for extension, but closed for modification. • Extension should not involve/require changing existing code. • Original meaning: use inheritance! • Meaning changed as programming languages and methodologies developed. • Now: code should rely mostly on interfaces and abstract classes, which are open for extension. Implementations need not be. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns The Open-Closed Principle class GraphicEditor { public void drawShape(Shape s) { if (s.queryType() == 1) drawRectangle((Rectangle)s); else if (s.queryType() == 2) drawCircle((Circle)s); } public void drawCircle(Circle r) { ... } public void drawRectangle(Rectangle r) { ... } } interface Shape { int queryType(); } class Rectangle implements Shape { ... int queryType() { return 1; } } class Circle extends Shape { ... int queryType() { return 2; } } Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns The Open-Closed Principle class GraphicEditor { public void drawShape(Shape s) { } s.draw( myCanvas); } interface Shape { public void draw(Canvas canvas); } class Rectangle implements Shape { ... public void draw(Canvas canvas); } class Circle implements Shape { ... public void draw(Canvas canvas); } Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Liskov’s Substitution Principle (Objects of) sub-classes must be substitutable for (suitable objects of) their base classes without change in behaviour of the overall program. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Liskov’s Substitution Principle Given: public class Rectangle { ... public int getHeight() { ... } public int getWidth() { ... } public void setHeight(int height) { ... } public void setWidth(int width) { ... } } We might want to have another, more restricted class of squares. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Liskov’s Substitution Principle How about: public class Square extends Rectangle { ... public int getHeight() { ... } public int getWidth() { ... } public void setHeight(int height) { // enforce } public void setWidth(int width) { // enforce } } Seems very reasonable relationship, since squares are rectangles. But violates the principle! Not each Square is-a Rectangle . Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Interface Segregation Principle No client should be forced to depend on methods it does not use. • Accomplish by splitting large interfaces into role interfaces. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Interface Segregation Principle public interface Vehicle { void drive(); void refuel(int amount); } public class Car implements Vehicle { void drive() { ... } void refuel(int amount) { ... } } public class Bike implements Vehicle { void drive() { ... } void refuel(int amount) { throw new Exception(); } } Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Dependency Inversion Principle (A) High-level components should not depend on low-level components. Both should depend on abstractions. (B) Abstractions should not depend on details. Details should depend on abstractions. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Dependency Inversion Principle (A) High-level components should not depend on low-level components. Both should depend on abstractions. (B) Abstractions should not depend on details. Details should depend on abstractions. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Dependency Inversion Principle (A) High-level components should not depend on low-level components. Both should depend on abstractions. (B) Abstractions should not depend on details. Details should depend on abstractions. • Suppose high-level class A depends (via interaction coupling) on low-level class B. • If a mechanism in B changes, we should not have to adapt A. • Instead, we should have made an abstract interface B ′ on which A depends and which B implements. • In essence, it becomes the role of B ′′ to capture the interaction aspect between A and B. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns The SOLID principles • Single Responsibility Principle • Open-Closed Principle • Liskov’s Substitution Principle • Interface Segregation Principle • Dependency Inversion Principle Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Honourable mention: Law of Demeter Don’t talk to strangers! Method f of class A may only talk to: • A itself • variables of A • global variables • the parameters to f • any objects created within f Alternative formulation: use only one dot. Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Software design pattern In software engineering, a software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design. • not code, but rather a kind of template, a standard way of doing things • arguably: a missing programming language feature Principles and Patterns
Recap Principles Patterns Inheritance Anti-patterns Some design patterns • Adapter pattern: use a wrapper to convert the interface of a class without modifying its source code • Facade pattern: tidy up the interfaces to a number of related objects that have often been developed incrementally • Closely related: isolate third-party components! • Observer pattern: tell several objects that the state of some other object has changed • Decorator pattern: allow for the possibility of extending the functionality of an existing class at runtime • . . . Principles and Patterns
Recommend
More recommend