T B H P N

Code Artistry - Software Design Principles

Content:

This page provides summaries of design principles and ideas we've discussed in class.
  1. Single Responsibilitiy Principle (SRP)1:

    Each software entity: function, class, package, module should have one responsibility. That makes design, testing, maintanence easier, because it makes comprehension easier. We expand on this principle in Note 07.
  2. Full Responsibility Principle (FRP)

    Each software entity should take full responsiblity for managing its state. This may include filtering user requests to avoid inappropriate changes of state, returning error codes for requests that cannot be satisfied, and managing formats of returned state. The intent is to consolidate all state management in the owning class, so users don't have to understand it's design, nor replicate handling code at the site of invocations.
  3. Encapsulation Principle (EP):

    Encapsulation restricts access to a class's data to the member functions of that class. This means that, for well designed classes, all transformations on the class's state result in valid data. That is something that the designer cannot guarantee if the class isn't properly encapsulated. We provide encapsulation by making all the class data private. A weaker form of encapsulation allows some of the class's data to provide protected access. That means that derived classes also have access to the protected data. So a correctly designed class may break if a derived class treats the protected data inappropriately. We expand on this principle in Note 08.
  4. Least Knowledge (LKP):

    Most method calls are a form of client/server interaction. The client makes a call on the server and the server's service does some computation and returns a response. Here the client and server could be:
    • a method of an instance of one class invoking a method of an instance of another class
    • a method of an instance of a class in one process invoking, through Inter-Process Communication (IPC), a method on an instance of a class in another process.
    • a method of an instance of a class in a process on one machine invoking, through a proxy using Remote Proceedure Call (RPC), to a method of an instance of a class hosted in a process on another machine.
    Ideally a client knows only the service interface and needs to know nothing of the service implementation. We also want the server to be entirely ignorant of the client. Ideally the server only knows that a request has been made and it responds based on the content of the request, having nothing to do with the client's details. This is the Least Knowledge Principle (LKP). We expand on this in Note 09.
  5. Value Semantics Principle (VSP):

    The C++ language directly supports implementation of classes whose instances have value type behavior. That means that we can copy them and assign the state of one instance to another instance with the result that the instances have, at the moment of copying or assignment, the same state values, but thoses states are independent. Should the state of one be changed using its class interface, the other will not suffer that change. We implement value behavior by providing correctly implemented copy constructors, overloading assignment operators, and providing correctly implemented destructors. We also can, using C++11's move construction and move assignment, make changing ownership of an instance's values very efficient. By default ownership is only moved from a temporary (r value) to a declared named instance (l value). All of this is demonstrated in a simple way in the presentation on Value Types and code for the Str class, discussed in Lecture #4 and Lecture #5.
  6. Scoped-based Resource Management Principle (SRMP):

    The C++ language has a very elegant mechanism for managing allocation and deallocation of resources to instances of a class. Resources are allocated in a constructor at the site of the declaration of an instance, may be augmented by allocations in other member functions, and are deallocated using the class destructor at the end of the scope in which the instance is declared. This means that users of the class need know very little about its internal design and don't need to do anything explicit to quickly return resources when the instance is no longer needed. These resources may be things that are in limited supply in a process, like file handles, threads, database locks, etc..
  7. Liskov Substitution Principle (LSP)1:

    Inheritance is a powerful mechanism, used by most Object Oriented Languages. Here's a statement:
    "Functions that use pointers or references statically typed to some base class must be able to use objects of classes derived from the base through those pointers or references, without any knowledge specialized to the derived classes."
    LSP supports great flexibility in the implementation of programs using OOD. We will see many examples of this throughout the semester.
  8. Open/Closed Principle (OCP)1:

    OCP is a very broad principle. It says that we should strive to extend or wrap existing code rather than change the code to meet new requirements. Here's a statement:
    "Software entities [classes, packages, functdions] should be open for extension, but closed for modification.
    This is a very important goal when we design software. In order to satisfy new or changing requirements, we try to extend, through inheritance or template parameterization, existing code, or wrap parts of the code with new classes, using composition or aggregation. That is not always possible, but that should be our first attempt to satisfy a need for change.
  9. Dependency Inversion Principle (DIP)1:

    Making references to concrete classes and functions binds the caller to a specific design and implementation, and makes that software "brittle", e.g., hard to change without causing a lot of breakage. To avoid these brittle designs we use DIP:
    "High level components should not depend upon low level components. Instead, both should depend on abstractions."
    "Abstractions should not depend upon details. Details should depend on the abstractions."
    Here, abstractions refer to interfaces and object factories. We will discuss this many times throughout the semester and provide demos of several variations.
  10. Interface Segregation Principle (ISP)1:

    When a class has many clients with differing needs, it is tempting to extend the class's interface and implementation to satisfy the needs of each new client. However, the other clients may not need those new public methods, but must be recompiled every time a method changes, even if they don't use the method.
    "Clients should not be forced to depend upon interfaces they do not use.
    We usually satisfy the ISP by factoring a class into a core and specialized parts that can serve the specialized needs of each client. One common way to do that uses multiple inheritance, allowing selection of what's needed for each application.

  1. Principles of OOD - Robert Martin

CST strip