Intro to: Design Principles

Similar documents
Lecture: Modular Design

Software Engineering

CS 320 Introduction to Software Engineering Spring March 06, 2017

Software Engineering CSC40232: SOFTWARE ENGINEERING. Guest Lecturer: Jin Guo SOLID Principles sarec.nd.edu/courses/se2017

CS 520 Theory and Practice of Software Engineering Fall 2017

CSC207H: Software Design SOLID. CSC207 Winter 2018

CS 520 Theory and Practice of Software Engineering Fall 2018

Outline. Subtype Polymorphism, Subtyping vs. Subclassing, Liskov Substitution Principle. Benefits of Subtype Polymorphism. Subtype Polymorphism

CS 370 Design Heuristics D R. M I C H A E L J. R E A L E F A L L

CS 320 Introduction to Software Engineering Spring March

Object-Oriented Concepts and Design Principles

Principles of Object-Oriented Design

GRASP Design Patterns A.A. 2018/2019

Component-Level Design

OO Class Design Principles

11/2/09. Code Critique. What goal are we designing to? What is the typical fix for code smells? Refactoring Liskov Substitution Principle

Object Oriented Software Design - I

Open Closed Principle (OCP)

17.11 Bean Rules persistent

Last Time: Object Design. Comp435 Object-Oriented Design. Last Time: Responsibilities. Last Time: Creator. Last Time: The 9 GRASP Patterns

n HW5 out, due Tuesday October 30 th n Part 1: Questions on material we ll cover today n Part 2: BFS using your graph from HW4

Liskov Substitution Principle

CHAPTER 5 GENERAL OOP CONCEPTS

Plan. Design principles: laughing in the face of change. What kind of change? What are we trying to achieve?

Index. Index. More information. block statements 66 y 107 Boolean 107 break 55, 68 built-in types 107

The Liskov Substitution Principle

Design Principles: Part 2

Outline. Design Principles: Part 2. e.g. Rectangles and Squares. The Liskov Substitution Principle (LSP) ENGI 5895: Software Design.

Single Responsibility Principle (SRP)

COURSE 2 DESIGN PATTERNS

INTERNAL ASSESSMENT TEST III Answer Schema

SOLID Principles. Equuleus Technologies. Optional Subheading October 19, 2016

From Module To Objects

Welcome to Design Patterns! For syllabus, course specifics, assignments, etc., please see Canvas

What are the characteristics of Object Oriented programming language?

Bruno Bossola SOLID Design Principles

Software Development. Modular Design and Algorithm Analysis

Design patterns. Jef De Smedt Beta VZW

Design Principles: Part 2

Object-Oriented Design II

Lethbridge/Laganière 2005 Chapter 9: Architecting and designing software 6

S.O.L.I.D: Software Engineering Principles

The Software Design Process. CSCE 315 Programming Studio, Fall 2017 Tanzir Ahmed

Lessons Learned. Johnny Bigert, Ph.D., Skype/Microsoft October 26, 2011

6.001 Notes: Section 6.1

Princípy tvorby softvéru Dizajnové princípy

Maintainable Software. Software Engineering Andreas Zeller, Saarland University

Inheritance (Chapter 7)

Eliminate enterprise software design instability - protect variations! Nickolay Kofanov

CSE 331 Final Exam 3/16/15 Sample Solution

L4: Inheritance. Inheritance. Chapter 8 and 10 of Budd.

OO Frameworks. Introduction. Using Frameworks

Originality is Overrated: OO Design Principles

Summary of the course lectures

PRINCIPLES OF SOFTWARE DESIGN

Ingegneria del Software Corso di Laurea in Informatica per il Management. Software quality and Object Oriented Principles

Software Design and SOLID Principles

Introduction to Object Oriented Programming. (Hebrew University, CS / Spring 2012 )

11/4/15. Review. Objec&ves. Refactoring for Readability. Review. Liskov Subs&tu&on Principle (LSP) LISKOV SUBSTITUTION PRINCIPLE

Tecniche di Progettazione: Design Patterns

Software Development. Modular Design and Algorithm Analysis

The following topics will be covered in this course (not necessarily in this order).

CSSE 220 Day 13. Encapsulation Coupling and Cohesion Scoping. Please download EncapsulationExamples from your SVN

09. Component-Level Design

Software Engineering /48

Subtypes and Subclasses

Single Responsibility Principle

OO Design Principles

Object-Oriented Design I - SOLID

Designing Robust Classes

Component-Level Design. Slides copyright 1996, 2001, 2005, 2009 by Roger S. Pressman. For non-profit educational use only

Abstraction. Design fundamentals in OO Systems. Fundamental Software Development Principles

Software Engineering Design & Construction Dr. Michael Eichberg Fachgebiet Softwaretechnik Technische Universität Darmstadt

CS 292 Software Development

Object- Oriented Design with UML and Java Part I: Fundamentals

School of Computer Science CPS109 Course Notes Set 7 Alexander Ferworn Updated Fall 15 CPS109 Course Notes 7

Expanding Our Horizons. CSCI 4448/5448: Object-Oriented Analysis & Design Lecture 9 09/25/2011

More About Objects. Zheng-Liang Lu Java Programming 255 / 282

Principles of Software Design. Software Engineering Alessio Gambi Saarland University

CSE 331 Software Design and Implementation. Lecture 12 Subtypes and Subclasses

CPS122 Lecture: Cohesion and Coupling. 1. To introduce cohesion and coupling as criteria for evaluating designs

SOLID: Principles of OOD

Design Process Overview. At Each Level of Abstraction. Design Phases. Design Phases James M. Bieman

CS Introduction to Data Structures How to Parse Arithmetic Expressions

Lecturer: Sebastian Coope Ashton Building, Room G.18 COMP 201 web-page:

CSE 70 Final Exam Fall 2009

Software Engineering Design & Construction

Objec&ves. Review. Liskov Subs&tu&on Principle Refactoring for Extensibility. What are reasons that we refactor our code?

Software Design Fundamentals. CSCE Lecture 11-09/27/2016

Organization of User Interface Software

Socket attaches to a Ratchet. 2) Bridge Decouple an abstraction from its implementation so that the two can vary independently.

Design Pattern. CMPSC 487 Lecture 10 Topics: Design Patterns: Elements of Reusable Object-Oriented Software (Gamma, et al.)

Readability [Skrien 4.0] Programs must be written for people to read, and only incidentally for machines to execute.

CS 370 High-Quality Routines D R. M I C H A E L J. R E A L E F A L L

Object Relationships

OOP Design Conclusions and Variations

Chapter 11 Classes Continued

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

CSC207H: Software Design Lecture 6

Client Code - the code that uses the classes under discussion. Coupling - code in one module depends on code in another module

Transcription:

Intro to: Design Principles Pragmatic Programmer: Eliminate Effects Between Unrelated Things design components that are: self-contained, independent, and have a single, well-defined purpose

Software Design Modularity The goal of all software design techniques is to break a complicated problem into simple pieces.

Why Modularity?

Why Modularity? Minimize Complexity Reusability Extensibility Portability Maintainability

What is a good modular Design? There is no right answer with design Applying heuristics/principles can provide insights and lead to a good design

Design Principles Pragmatic Programmer: Eliminate Effects Between Unrelated Things design components that are: self-contained, independent, and have a single, well-defined purpose 15

Principles & Heuristics for modular Design http://en.wikipedia.org/wiki/solid_%28object-oriented_design%29 S O L I D (one nice combo of principles) S O L I D Single Responsibility Principle (High Cohesion, Low Coupling) Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principles

S O L I D The Single Responsibility Principle a class should have only a single responsibility (i.e. only one potential change in the software's specification should be able to affect the specification of the class) http://en.wikipedia.org/wiki/single_responsibility_principle

S O L I D High Cohesion http://en.wikipedia.org/wiki/cohesion_(computer_science) Cohesion refers to how closely the functions in a module are related Modules should contain functions that logically belong together Group functions that work on the same data Classes should have a single responsibility.

S O L I D Cohesion (try to increase) versus methods that serve the given class tend to be similar in many aspects The functionalities embedded in a class, accessed through its methods, have little in common. Methods carry out many varied activities, often using coarsely-grained or unrelated sets of data.

S O L I D The Or-Check A class description that describes a class in terms of alternatives is probably not a class, but a set of classes

Coincidental cohesion (bad) Coincidental cohesion is when parts of a module are grouped arbitrarily; the only relationship between the parts is that they have been grouped together (e.g. a Utilities class). Logical cohesion (bad) Logical cohesion is when parts of a module are grouped because they logically are categorized to do the same thing, even if they are different by nature (e.g. grouping all mouse and keyboard input handling routines). Temporal cohesion Temporal cohesion is when parts of a module are grouped by when they are processed - the parts are processed at a particular time in program execution (e.g. a function which is called after catching an exception which closes open files, creates an error log, and notifies the user). Procedural cohesion Procedural cohesion is when parts of a module are grouped because they always follow a certain sequence of execution (e.g. a function which checks file permissions and then opens the file). Communicational cohesion Communicational cohesion is when parts of a module are grouped because they operate on the same data (e.g. a module which operates on the same record of information). Sequential cohesion (very good) Sequential cohesion is when parts of a module are grouped because the output from one part is the input to another part like an assembly line (e.g. a function which reads data from a file and processes the data). Functional cohesion (best) Functional cohesion is when parts of a module are grouped because they all contribute to a single well-defined task of the module (e.g. tokenizing a string of XML). S O L I D Types of Cohesion

S O L I D points from: http://it.toolbox.com/blogs/enterprise-solutions/design-principles-cohesion-16069 Functional Cohesion (best) Functionally cohesive objects do ONE thing only. Good because they re easy to reuse, and understand Warning: functionally cohesive can proliferate and get very tiny (overly fine grained, overly numerous)

S O L I D High or low cohesion? public class EmailMessage { public void sendmessage() { } remember: classes should be about one thing public void setsubject(string subj) { } public void setsender(sender sender) { } public void login(string user, String passw) { }. }

S O L I D Loose Coupling http://en.wikipedia.org/wiki/coupling_(computer_science) Coupling assesses how tightly a module is related to other modules Goal is loose coupling: modules should depend on as few other modules as possible Changes in modules should not impact other modules; easier to work with them separately

S O L I D Coupling (try to decrease) versus A change in one module usually forces a ripple effect of changes in other modules. Assembly of modules might require more effort and/or time due to the increased intermodule dependency. A particular module might be harder to reuse and/or test because dependent modules must be included.

S O L I D Types of Coupling Content coupling (high) Content coupling is when one module modifies or relies on the internal workings of another module (e.g., accessing local data of another module). Therefore changing the way the second module produces data (location, type, timing) will lead to changing the dependent module. Common coupling Common coupling is when two modules share the same global data (e.g., a global variable). Changing the shared resource implies changing all the modules using it. External coupling External coupling occurs when two modules share an externally imposed data format, communication protocol, or device interface.this is basically related to the communication to external tools and devices. Control coupling Control coupling is one module controlling the flow of another, by passing it information on what to do (e.g., passing a what-to-do flag). Stamp coupling (Data-structured coupling) Stamp coupling is when modules share a composite data structure and use only a part of it, possibly a different part (e.g., passing a whole record to a function that only needs one field of it). This may lead to changing the way a module reads a record because a field that the module doesn't need has been modified. Data coupling Data coupling is when modules share data through, for example, parameters. Each datum is an elementary piece, and these are the only data shared (e.g., passing an integer to a function that computes a square root). Message coupling (low) This is the loosest type of coupling. It can be achieved by state decentralization (as in objects) and component communication is done via parameters or message passing No coupling Modules do not communicate at all with one another.

S O L I D Semantic coupling: The most insidious kind of coupling occurs when one module makes use not of some syntactic element of another module but of some semantic knowledge of another module s inner workings. http://courses.cs.washington.edu/courses/cse403/07sp/assignments/chapter5-design.pdf, page 102 Semantic coupling is dangerous because changing code in the used module can break code in the using module in ways that are completely undetectable by the compiler. When code like this breaks, it breaks in subtle ways that seem unrelated to the change made in the used module, which turns debugging into a Sisyphean task. The point of loose coupling is that an effective module provides an additional level of abstraction once you write it, you can take it for granted. It reduces overall program complexity and allows you to focus on one thing at a time. If using a module requires you to focus on more than one thing at once knowledge of its internal workings, modification to global data, uncertain functionality the abstractive power is lost and the module s ability to help manage complexity is reduced or eliminated.

S O L I D The OPEN/CLOSED principle software entities should be open for extension, but closed for modification. http://en.wikipedia.org/wiki/open/closed_principle

S O L I D Open/Closed Principle A class must be closed for internal change But must be open for extensions When designing classes, do not plan for brand new functionality to be added by modifying the core of the class. Instead, design your class so that extensions can be made in a modular way, to provide new functionality by leveraging the power of the inheritance facilities of the language, or through pre-accommodated addition of methods.

S O L I D Open/Closed Example class Drawing { public void drawallshapes(list<ishape> shapes) { for (IShape shape : shapes) { if (shape instanceof Square()) { drawsquare((square) shape); } else if (shape instanceof Circle) { drawcircle((circle) shape)); } } } private void drawsquare(square square) {..} // draw the square private void drawcircle(circle square) {..} // draw the circle } This class assumes developers will modify the drawsquare and drawcircle methods directly to change their behaviour. This results in what looks like unplanned change class Drawing { public void drawallshapes(list<ishape> shapes) { for (IShape shape : shapes) { shape.draw(); } } } interface IShape { public void draw();} class Square implements IShape { public void draw() { // draw the square }} this class has made specialising the shape draw method much more straightforward (also indicating that developers see this potential change coming)

S O L I D Liskov Substitution Subtype Requirement: Let ϕ(x) be a property provable about objects x of type T. Then ϕ(y) should be true for objects y of type S where S is a subtype of T. Principle [Barbara Liskov and Jeanette Wing, A Behavioral Notion of Subtyping, ACM Transactions on Programming Languages and Systems, Vol 16, No 6. November 1994, Pages 1811-1841.] if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program http://en.wikipedia.org/wiki/liskov_substitution_principle

S O L I D Liskov Substitution Principle An object of a superclass should always be substitutable by an object of a subclass Subclass has same or weaker preconditions Subclass has same or stronger postconditions

S O L I D Fixing violations of LSP LSP shows that a design can be structurally consistent (A Square ISA Rectangle) But behaviourally inconsistent So, we must verify whether the pre and postconditions in properties will hold when a subclass is used. It is only when derived types are completely substitutable for their base types that functions which use those base types can be reused with impunity, and the derived types can be changed with impunity.

S O L I D The Interface Segregation Principle many client-specific interfaces are better than one general-purpose interface. http://en.wikipedia.org/wiki/interface_segregation_principle

S O L I D The Interface Segregation Principle no client should be forced to depend on methods it does not use A move towards role-based interfaces clients need only know about the methods that are of interest to them. This relates strongly to the concept of high cohesion

S O L I D Example BakeryApp BakeryInterface uses all of sellcake() sellbread() sellcoffee() selljuice() So far so good... BakeryImpl sellcake() sellbread() sellcoffee() selljuice()

S O L I D But what if we want a coffee shop? CoffeeShopApp BakeryInterface This is not as good uses SOME of sellcake() sellbread() sellcoffee() selljuice() Now the CoffeeShopApp client is only using part of the BakeryInterface. But it has to "know about" all of it. it's likely that changes to the implementation of some of those methods will affect the implementations of the others. BakeryImpl sellcake() sellbread() sellcoffee() selljuice()

S O L I D How about a special implementation? CoffeeShopApp BakeryInterface uses SOME of sellcake() sellbread() sellcoffee() selljuice() Also, mycoffeeshop app violates LSP CoffeeShopImpl BakeryImpl This is still bad. Now we have a sellcake() //not implemented CoffeeShop sellbread() //not implemented implementation that sellcoffee() focuses on coffee shop selljuice() stuff, but now it has to hand out errors for the Bakery stuff if it's ever accidentally used sellcake() sellbread() sellcoffee() selljuice()

S O L I D recall: this class would contain code that amounted to: CoffeeShopInterface c = new CoffeeShopImpl() A better arrangement CoffeeShopApp BakeryApp We have no LSK violations CoffeeShopImpl CoffeeShopInterface BakedGoodsInterface BakeryImpl sellcoffee() selljuice() sellcoffee() selljuice() sellcake() sellbread() sellcake() sellbread() Now we have nice high cohesion in the interfaces (respecting Single Responsibility) because of the arrangement, these are also open for extension, so we have also got the Open Closed principle checked off

S O L I D Dependency Inversion one should Depend upon Abstractions. Do not depend upon concretions. A. High-level modules should not depend on lowlevel modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions. We are going to think of this in about the same way as coarser grained information hiding, though there s much more to it than that. http://en.wikipedia.org/wiki/dependency_inversion_principle

S O L I D Dependency Inversion Class arrangement Client ConcreteService means that the Client is "hooked up to" just one concrete service. Any chances to the concrete service will propagate to the client, meaning it will be harder to change or switch out the underlying service. Client ServiceInterface With this arrangement the client only knows about the interface, and is impervious to underlying changes (as long as the other principles are followed) ConcreteService1 ConcreteService2

S O L I D Information Hiding A good class is a lot like an iceberg: seven-eights is under water, and you can see only the one-eight that s above the surface. from CodeComplete by Steve McConnell

S O L I D Information Hiding Only expose necessary functions Abstraction hides complexity by emphasizing on essential characteristics and suppressing detail Caller should not assume anything about how the interface is implemented Effects of internal changes are localized http://www.fatagnus.com/program-to-an-interface-not-an-implementation/ 22

S O L I D Information Hiding: Example Class DentistScheduler has A public method automaticallyschedule() Private methods: whotoschedulenext() whotogivebadhour() ishourbad() To use DentistScheduler, just call automaticallyschedule() Don t have to know how it s done internally Could use a different scheduling technique: no problem 24

S O L I D Typical class design Class public private

S O L I D The public methods are the class s interface Class public private

S O L I D They make calls down to the implementation. the call is made to a class's PUBLIC methods 1 Class 2 The public method delegates the implementation down to private methods (unless it's really trivial) public private 3 The private methods do all the heavy lifting. Often the dependencies on other classes sit down here.

S O L I D So putting these together Interface ConcreteClass So information and Dependency Inversion means that we get arrangements that often look like this... public private interface interface interface interface interface interface interface

S O L I D This gives the app more Using the bakery example CoffeeShopInterface BakedGoodsInterface This is how you want the arrangement to look. flexibility. It can depend upon additional interfaces, without having to wait for the perfectly combined underlying implementation. sellcoffee() selljuice() sellcake() sellbread() BakeryCoffeeShopImpl CoffeeShopApp BakeryApp sellcake() sellbread() sellcoffee() selljuice() BakeryCoffeeShopApp CoffeeShopInterface BakedGoodsInterface The BakeryCoffeeShop is depending on an IMPLEMENTATION, rather than a collection of nice, specific interfaces sellcoffee() selljuice() CoffeeShopImpl sellcoffee() selljuice() sellcake() sellbread() BakeryImpl sellcake() sellbread()

S O L I D Summary Classes should do ONE THING (sometimes (often) that aligns better with a role than with a noun) (pass the and/orcheck) Don t force extenders to change the implementation directly allow them to truly extend. Don t violate type substitutability Pass the is-a test. Have small, role-specific interfaces (interfaces should also just do one thing) Depend upon abstractions, not implementations.

ACTIVITY Make a design for your sample system that complies with the principles we discussed in class. Take some time to do this. We will go over several of them carefully in the second half of class. Hand in your work INDIVIDUALLY to the relevant handin folder.