1 of 27

Software Design Principles

CS 240: Advanced Software Construction

2 of 27

Introduction

3 of 27

Goals of Software Design

  • Create systems that:
    • Work and satisfy customer requirements
    • Are easy as possible to understand, debug, and maintain
    • Hold up well under changes

3

4 of 27

Principle #1: Design is Inherently Iterative

5 of 27

Design is Inherently Iterative

  • Design, implement, test, Design, implement, test, …
  • Feedback loop from implementation back into design provides valuable knowledge
  • Designing everything before beginning implementation doesn’t work
  • Beginning implementation without doing any design also doesn’t work
  • The appropriate balance is achieved by interleaving design and implementation activities in relatively short iterations

5

6 of 27

Principle #2: Abstraction

7 of 27

Abstraction

  • Abstraction is one of the software designer’s primary tools for coping with COMPLEXITY
  • In object-oriented programming, abstractions are represented by classes
  • Programming languages provide classes that model low-level concepts such as strings and file I/O
  • Programs written solely in terms of these low-level classes are very difficult to understand
  • Software designers must create higher-level, domain-specific classes, and write their software in terms of those
    • High-level classes are implemented in terms of low-level classes

7

8 of 27

Abstraction

  • Some classes correspond to “real world” concepts in the application domain
    • Example: Bank, Customer, Account, Loan, Broker, …
    • Example: Person, Event, Marriage, Baptism, Christening, Death, …
  • Other classes do not correspond to “real world” domain concepts, but are needed for internal implementation
    • Examples: HttpServer, Database, HashTable, …

8

9 of 27

Abstraction

  • Each class has a carefully designed public interface that defines how the rest of the system interacts with it
  • A client can invoke operations on an object without understanding how it works internally
  • This is a powerful technique for reducing the cognitive burden of building complex systems

9

10 of 27

Abstraction

  • Classes often model complex, real-world objects
  • You generally can’t fully represent the thing you are abstracting, so you make domain appropriate decisions about what to represent in methods and variables
  • Example:
    • Do you care about heart-rate or fingerprint in a Person class?
    • Probably not, but what if you are building a system for a heart surgeon or for the FBI?

10

11 of 27

Principle #3: �Good Naming

12 of 27

Naming

  • A central part of abstraction is giving things names (or identifiers)
  • Selecting good names for things is critical
  • Class, method, and variable names should clearly convey their function or purpose
  • Class and variable names are usually nouns
  • Method names are usually verbs

12

13 of 27

Principle #4:�Single-Responsibility Principle

14 of 27

Single Responsibility / Cohesion

  • Each class and method should have a single responsibility
  • Each class should represent one, well-defined concept
    • All variables and methods in a class should be highly related to the class’ single responsibility (cohesion)
  • Each method should perform one, well-defined task
    • Unrelated or loosely related tasks should be in different methods
  • Methods that need to perform multiple tasks should delegate tasks to sub-methods that each perform a single task
  • Cohesive classes and methods are easy to name

14

15 of 27

Principle #5:�Decomposition

16 of 27

Decomposition

  • Decomposition is another fundamental technique for managing COMPLEXITY
  • Large problems subdivided into smaller sub-problems
  • Subdivision continues until leaf-level problems are simple enough to solve directly
  • Solutions to sub-problems are recombined into solutions to larger problems

16

17 of 27

Decomposition

  • Decomposition is strongly related to Abstraction
  • The solution to each sub-problem is encapsulated in its own abstraction (class or function)
  • Solutions to larger problems are expressed in terms of sub-problem solutions, which leads to concise, readable code
  • The decomposition process helps us discover (or invent) the abstractions that we need

17

18 of 27

Decomposition

  • Levels of decomposition
    • System
    • Subsystem
    • Packages
    • Classes
    • Methods

18

19 of 27

Principle #6: Good Algorithm & Data Structure Selection

20 of 27

Algorithm & Data Structure Selection

  • No amount of decomposition or abstraction will hide a fundamentally flawed selection of algorithm or data structure.

20

21 of 27

Principle #7:�Low Coupling

22 of 27

Low Coupling

  • Coupling between classes should be minimized
  • The less classes know about each other the better
  • Minimize the number of other classes a class interacts with or knows about
  • Low coupling reduces ripple effects when a class changes

23 of 27

Encapsulation / Information Hiding

  • A class should hide, or “encapsulate”, its internal implementation (variables and methods) that are not essential for its users to know about
  • Encapsulation is central to achieving low coupling between classes
  • Many languages provide “public”, “private”, and “protected” access levels
  • All internal implementation should be “private” unless there’s a good reason to make it “protected” or “public”
  • A class’ public interface should be as simple and minimal as possible

23

24 of 27

Encapsulation / Information Hiding

  • Don’t let internal details “leak out” of a class
    • ClassRoll instead of StudentLinkedList
  • Some classes or methods are inherently tied to a particular implementation. For these it is OK to use an implementation-specific name
    • HashTable
    • TreeSet
    • binarySearch

24

25 of 27

Separation of Interface and Implementation

  • Maintain a strict separation between a class’ interface and its implementation
  • This allows internal details to change without affecting clients
  • Program to interfaces instead of concrete classes

25

26 of 27

Principle #8:�Avoid Code Duplication

27 of 27

Code Duplication

  • The DRY principle: Don’t repeat yourself
  • Code duplication should be avoided
    • Identical or similar sections of code
  • Disadvantages of duplication:
    • N copies to maintain
    • Bugs are duplicated N times
    • Makes program longer, decreasing maintainability
  • Solutions
    • Factor common code into a separate method or class
    • Shared code might be placed in a common superclass

27