public class Length {
protected final double length;
public Length(double d) {
this.length = d;
}
}Gerson SunyƩ gerson.sunye@univ-nantes.fr
General guidelines and best practices
Goal: improve maintainability, scalability, and efficiency
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
In this lecture, we use the terms Module and Operation to design programming language constructs that contain some behavior and some structural properties, and routines, respectively. Modules may be Classes in object-oriented programming, Units in procedural programming, or Components in component-oriented programming. Operations may be Methods in object-oriented programming, or Procedure and Functions in procedural programming. |
Complexity control by the amplification of the essential features and the suppression of the less important details.
Types of abstraction: functional, structural, control, etc.

public class Length {
protected final double length;
public Length(double d) {
this.length = d;
}
}public class fr.unantes.info.units.Length {
protected final double length;
public fr.unantes.info.units.Length(double);
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: dload_1
6: putfield #2 // Field length:D
9: return
}Abstraction allows designers to postpone design decisions.
Complexity control by the decomposition of problems into sub-problems.
Divide and conquer approach, common to all design techniques.
A type of Data Abstraction
AKA Information Hiding, Information Dissimulation
Important mean to achieve abstraction
Design decisions that are likely to change should be hidden behind interfaces.
Design decisions that are likely to change should be hidden behind interfaces.
Components should communicate only through well-defined interfaces.
Interface should be specified by as little information as possible.
If component internal decisions change, clients should not be affected.
Data representation
Data types, etc.
Algorithms
Data search and sorting
Input and output formats
Machine dependencies, e.g., byte-ordering, character codes
Lower-level interfaces
Ordering of low-level operations
Policy/Mechanism separation
Multiple policies for one mechanism.
Same policy for multiple mechanisms.
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
Cohesion is a measure of the degree to which the elements of a module are functionally related.
Cohesion should be increased where possible.
Types of cohesion: functional, layer, de communicational, sequential, procedural, temporal, coincidental.
All the code that performs a particular task (functional cohesion).
All the code that provides or uses a set of related services (layer cohesion).
All code that access or modify certain data (communicational cohesion).
A sequence of operations, in which one operation provides input to the next (sequential cohesion).
A set of operations that are used one after another (procedural cohesion).
Operations that are performed at the same execution phase (temporal cohesion).
Operations which cannot logically be placed in other cohesive units (coincidental cohesion).
Better readability and understandability: High cohesion results in clear, focused modules with a single, well-defined purpose, making it easier for developers to understand and maintain the code.
Better error isolation: High cohesion reduces the chances of a change in one part of a module affecting other parts, making it easier to locate errors.
Better reliability: High cohesion leads to modules that are less prone to errors and that function more consistently, leading to an overall improvement in the software’s reliability.
Increases code duplication: Low cohesion may lead to code duplication, as related elements are split into separate modules.
Reduces functionality: Low cohesion may lead to modules lacking a clear purpose, containing unrelated elements, reducing functionality, and making maintenance harder.
Reduces understandability: Low cohesion can make it difficult for developers to comprehend the purpose and behavior of a module, leading to errors and a lack of clarity.
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
Coupling is the measure of the degree of interdependence between the modules. A good software will have low coupling.
Coupling should be reduced where possible.
Interdependencies impacts maintainability, testability, and simplicity.

Data: when parameter types are primitive types.
Stamp (data-structured coupling): when a complete data structure is passed from one module to another.
Control: when a parameter controls the behavior of an operation (a what-to-do flag).

External: when a component depends on external artifacts: operating system, hardware, libraries, etc.
Common: when modules share global variables. Common coupling can lead to uncontrolled error propagation and unforeseen side-effects, after modifications.
Content: when a module modifies the content of another module.

Subclass: describes the relationship between a subclass and its superclass. The subclass is connected to its superclass, but not the opposite.
Temporal: when operations are bundled into one module because they occur at the same time.
Dynamic: when a module uses/imports another at run-time (static coupling metrics lose precision when using dynamic binding and inheritance).
Semantic: when the relationship between modules are based on their meaning or purpose, rather than their implementation.
Logical: when the relationship between modules is base on the software change history.
Better maintainability: Low coupling reduces the impact of changes in one module on other modules, making it easier to modify or replace individual components without affecting the entire software.
Better modularity: Low coupling allows modules to be developed and tested in isolation, improving the modularity and reusability of code.
Better scalability: Low coupling facilitates the addition of new modules and the removal of existing ones, making it easier to scale the system as needed.
Increases complexity: High coupling increases the interdependence between modules, making the system more complex and difficult to understand.
Decreases flexibility: High coupling makes it more difficult to modify or replace individual components without affecting the entire system.
Decreases modularity: High coupling makes it more difficult to develop and test modules in isolation, reducing the modularity and reusability of code.

Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
Reusability should be increased where possible.
Components should be designed to work on different contexts.
Generalize design as much as possible:
Use Frameworks, Patterns, and UML Collaborations.
Design the system to contain hooks.
Keep the design as simple as possible
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
Reuse Analysis, Design, and Code
Reuse existing artifacts when possible, to take advantage of existing investment.
Use Frameworks, Patterns, and UML Collaborations.
Complementary to the principle of reusability.
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
Avoid:
Immature technologies.
Undocumented features.
Software and Hardware without long-term support provision.
Plan technology changes and adopt technologies that are supported by different vendors.
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
Develop on and for different platforms.
Avoid platform-specific frameworks or libraries.
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
The internal state of a component should be accessible by external programs.
Design components to be used directly by external clients, without user interfaces.
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
The KISS principle [US Navy, 1960]:
Keep it simple, stupid!
Most systems work best if they are kept simple rather than made complicated
Simplicity should be a key goal in design and unnecessary complexity should be avoided.
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
A Component (class, module, etc.) must only depend on more stable components
The dependency between two components must follow the direction of stability (a component must always depend on a more stable one).
Basis
Cohesion
Couping
General principles
Object-oriented
Single Responsibility
Open/Closed
Liskov Substitution
Interface Segregation
Dependency Inversion
Indirection
Polymorphism
Responsibility
Information Expert
Creator
Controller
Pure Fabrication
Protected Variations
Acronym for Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion
A class should have one and only one responsibility (i.e. only one potential change in the software’s specification should be able to affect the specification of the class).
The classes are abstractions of the real and not the different roles played by an object.

Software entities should be open for extensions but closed for modification.
AbstractEList::equals() from EMF public boolean equals(Object object) {
// (...)
Iterator<?> objects = list.iterator();
if (useEquals()) {
// Compare with equals()
} else {
// Compare with "=="
}
}Class instances can be used throughout the superclass interface, without notifying its clients.
Many client-specific interfaces are better than one general-purpose interface.
A client should depend upon abstractions and not upon concretions.