Program Analysis and Software design
Table of Contents
1. System modeling
Diagram formalizes model
Model composes view
View adresses requirements
Requirements are important to the stakeholder
1.1. C4 model
A “zooming” framework. You go deeper and deeper into things, based on what’s important. Eventually, you can arrive at the code itself.
Good example: it’s like a map. You start zoomed out, seeing the whole world. You can progressively zoom in until you’re on specific streets. Another beautiful example of this is the banking system example linked on the slides.
C4 models can be made by dragging boxes, or writing code.
C4 made out of 4 levels:
1.1.1. Context
Describes main parts of the system. This is extremely general.
This can be the system itself, the entities the system interacts with, external systems.
1.1.2. Containers
This explains how the system is composed, and can also describe how these parts of the system interact with the bigger systems.
This a description of system organization, no specific details on how everything works
In Java, like modules.
1.1.3. Components
How components interact with each other.
Describes the features of the program and how they interact with each other.
In Java, like packages.
1.1.4. Code
The code itself. Can be viewed as individual classes in Java.
*
2. Design metrics
2.1. WMC
Weighted Methods per Class. This finds the “complexity” of a class by summing the “complexities” of its methods.
How is a complexity calculated? It depends on the type of complexity The most basic one is just the number of operations or methods in a class.
Example: In a class with 10 methods which each have a complexity of 1, the WMC would be 10.
2.2. DIT
Depth of Inhertitance Tree. This measures how many levels there are to the root class.
Example: If a class C inherits from a class B which inherits from another superclass A, the DIT of C would be 2, DIT of B would be 1.
We don’t count superclasses.
2.3. NOC
Number of Children. Similar to DIT, this measures things from the superclass point of view. It counts how many children the superclass has.
Example: Iff 2 classes inherit from some superclass A, the the NOC of A is 2.
2.4. CBO
Coupling Between Object Classes. This measures the number of classes that some class is coupled to.
Example: If some class A uses methods or attributres of 5 other classes, its CBO is 5.
2.5. RFC
Response For a Class. The number of unique methods that can be executed in a response. To find RFC, sum the number of methodsin a class and the number of methods called within these methods.
Example: If some class A has 5 methods, and calls 3 other methods within its own methods, the RFC is \(5+3=0\).
2.6. LCOM
Lack of Cohesion in Methods. Ideally, you want to have a lack of cohesion in methods. This means that methods don’t share much of the same data. If classes have high cohesion, it means that they rely on each other (fact check) quite a bit which results in harder to understand and harder to maintain code.
3. Code smells
3.1. Abstraction smells
Smells that relate to the abstractation (simpilifcatio) of code. *
When something that is not needed to be abstracted is abstracted.
When an operation is turned into a class.
org.apache.shiro.tools.hasher.Hasher
*
3.1.1. Multifaceted Abstraction
When a single class or interface tries to represent too many things.
3.1.2. Unutilized Abstraction
WHen you create abstraction but you don’t use it or it’s not reachable.
3.2. Encapsulation smells
Self explanatory. Encapsulation smells.
3.2.1. Deficient encapsulation
Public methoids that are only used by the class that holds it or its children.
3.2.2. Unexploited encapsulation
When code uses if elses instead of fully exploiting encapsulation (?)
3.3. Modularization smells
Separation and dependecy type smells.
3.3.1. Cyclic-dependent modularization
Two or more abstractions depend on each other. Cyclic dependencies.
3.3.2. Hub-like modularization
An sbtraction having many dependencies, acting as a “hub.”
3.3.3. Broken modularization
Data and/or methods are separated into multiple abstractions when they really don’t need to be.
3.3.4. Insufficient modularization
The opposite of the above. Not enough abstraction, massive classes.
3.4. Hierarchy smells
Smells related to the hierarchy of code. Generally, subclass/superclass smells.
3.4.1. Wide hierarchy
Too many child classes inheriting from one superclass.
3.4.2. Cyclic Hierarchy
A supertype depends on any of its subtypes.
3.4.3. Deep hierarchy
Too much inheritance.
3.4.4. Missing hierarchy’s
Uses conditional logic where a hierarchy could have been created to encapsulate variations, for example, using switch statements instead of the strategy pattern.
3.4.5. Rebellious hierarchy
A subtype rejects methods given by its supertype. For example, when a class implements a method interface with an empty body.
3.4.6. Multipath hierarhchy
A subtype inherits both directly as well as inderatly from a supertype leading to unnecessary inheritance paths.