SE Book
title: User Stories layout: sebook —
User stories are the most commonly used format to specify requirements in a light-weight, informal way (particulalry in Agile projects). Each user story is a high-level description of a software feature written from the perspective of the end-user.
Format
User stories follow this format:
As a [user role],
I want [to perform an action]
so that [I can achieve a goal]
This structure makes the team to identify not just the “what”, but also the “who” and — most importantly — the “why”.
Acceptance Criteria
To make these descriptions actionable and testable, we pair them with acceptance criteria. Acceptance criteria define the scope of a user story.
They follow this format:
Given [pre-condition / initial state]
When [action]
Then [post-condition / outcome]
INVEST
Independent
Negotiable
Valuable
Estimable
Small
Testable
Limitations
User stories can struggle to capture non-functional requirements like performance, security, or reliability, and they are generally considered insufficient for safety-critical systems like spacecraft or medical devices
title: SOLID layout: sebook —
The SOLID principles are design principles for changeability in object-oriented systems.
Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
title: UML layout: sebook —
Class Diagrams
Class diagrams represent classes and their interactions.
Classes
Classes are displayed as rectangles with one to three different sections that are each separated by a horizontal line.
The top section is always the name of the class. If the class is abstract, the name is in italics.
The middle section indicates attributes of the class (i.e., member variables).
The bottom section should include all methods that are implemented in this class (i.e., for which the implementation of the class contains a method definition).
Inheritance is visualized using an arrow with an empty triage pointing to the super class.
Attributes and methods can be marked as public (+), private (-), or protected (#), to indicate the visibility.
Hint: Avoid public attributes, as this leads to bad design. (Public means every class has access, private means only this class has access, protected means this class and its sub classes have access)
When a class uses an association, the name and visibility of the attribute can be written either next to the association or in the attribute section, or both (but only if it is done consistently). Writing it on the Association is more common since it increases the readability of the diagram.
Please include types for arguments and a meaningful parameter name. Include return types in case the method returns something (e.g., + calculateTax(income: int): int)
Interfaces
Interfaces are classes that do not have any method definitions and no attributes. Interfaces only contain method declarations. Interfaces are visualized using the <<interface>> stereotype
To realize an interface, use then arrow with an empty triage pointing to the interface and a dashed line.
Sequence Diagrams
Sequence diagrams display the interaction between concrete objects (or component instances).
They show one particular example of interactions (potentially with optional, alternative, or looped behavior when necessary). Sequence diagrams are not intended to show ALL possible behaviors since this would become very complex and then hard to understand.
Objects / component instances are displayed in rectangles with the label following this pattern: objectName: ClassName. If the name of the object is irrelevant, then you can just write : Classname.
When showing interactions between objects then all arrows in the sequence diagram represent method calls being made between the two objects. So an arrow from the client object with the name handleInput to the state objects means that somewhere in the code of the class of which client is an instance of, there is a method call to the handleInput method on the object state. Important: These are interactions between particular objects, not just generally between classes. It’s always on concrete instance of this class.
The names shown on the arrows have to be consistent with the method names shown in the class diagram, including the number or arguments, order of arguments, and types of arguments. Whenever an arrow with method x and arguments of type Y and Z are received by an object o, then either the class of which o is an instance of or one of its super classes needs to have an implementation of x(Y,Z).
It is a modeling choice to decide whether you want to include concrete values (e.g., caclulateTax(1400)) or meaningful variable names (e.g., calculateTax(income)). If you reference a real variable that has been used before, please make sure to ensure it is the same one and it has the right type.
State Machine Diagrams
State machines model the transitions between different states. States are modeled either as oval, rectangles with rounded corners, or circles.
Transitions follow the patter [condition] trigger / action.
State machines always need an initial state but don’t always need a final state.
title: Design Patterns layout: sebook —
State Pattern
Problem
The core problem the State pattern addresses is when an object’s behavior needs to change dramatically based on its internal state, and this leads to code that is complex, difficult to maintain, and hard to extend.
If you try to manage state changes using traditional methods, the class containing the state often becomes polluted with large, complex if/else or switch statements that check the current state and execute the appropriate behavior. This results in cluttered code and a violation of the Separation of Concerns design principle, since the code different states is mixed together and it is hard to see what the behavior of the class is in different states. This also violates the Open/Closed principle, since adding additional states is very hard and requires changes in many different places in the code.
Context
An object’s behavior depends on its state, and it must change that behavior at runtime. You either have many states already or you might need to add more states later.
Solution
Create an Abstract State class that defines the interface that all states have. The Context class should not know any state methods besides the methods in the Abstract State so that it is not tempted to implement any state-dependent behavior itself. For each state-dependent method (i.e., for each method that should be implemented differently depending on which state the Context is in) we should define one abstract method in the Abstract State class.
Create Concrete State classes that inherit from the Abstract State and implement the remaining methods.
The only interactions that should be allows are interactions between the Context and Concrete States. There are no interaction among Concrete States objects.
Details / Design Decisions:
How to let the state make operations on the context object?
The state-dependent behavior often needs to make changes to the Context. To implement this, the state object can either store a reference to the Context (usually implemented in the Abstract State class) or the context object is passed into the state with every call to a state-dependent method.
How to represent a state in which the object is never doing anything (either at initialization time or as a “final” state)
Use the Null Object pattern to create a “null state”