Shortcut to seniority

Home
Go to main page

Section level: Junior
A journey into the programming realm

Section level: Intermediate
The point of no return

Section level: Senior
Leaping into the unknown
Go to main page
A journey into the programming realm
The point of no return
Leaping into the unknown
It is very important to be able to represent our system visually, especially when it’s a complex one. Using a common language such as UML diagrams allows teams to collaborate for the quality of the project.
Modelling is a way to visualize the design of the application, and compare it against requirements before we start the actual coding. With UML diagrams, you can visualize and validate the architecture of the software before implementing it.
The Unified Modeling Language (UML) is a modeling language for designing systems. UML establishes a standard semantic and syntactic structure, that developers can use to model almost any type of application, regardless of the hardware, Operating System, or programming language.
Using diagrams to “read” the code provide a number of benefits, such as:
There are two types of diagrams:
Class diagrams show the structure of a system as classes and their relation with other classes within the system.
Composition is a strong association.
The life of the contained object totally depends on the container object.
Aggregation is a weak association.
The life of the contained object does not depend on the container object.
Inheritance occurs when one class inherits all the non-private properties (methods/variables) that the base class provides, in order to maximize the code reuse and reduce code duplication.
Based on the visibility level, the attributes and methods receive a sign, such as:
The diagram has been drawn by using the following code:
title Class Diagram
class BaseClass {
.. public access ..
+void public_method()
+int public_variable
.. protected access ..
#void protected_method()
#int protected_variable
.. private access ..
-void private_method()
-int private_variable
..
{abstract} void abstract_method()
{static} int static_method()
}
BaseClass <|-- DerivedClass : inherits
BaseClass *-- CompositionClass : composition
BaseClass o-- AggregationClass : aggregation
The title is what’s visible on top of the image.
Afterwards, we define a class and a few methods and variables.
These variables are separated in public, protected, and private access, so the diagram will draw a line above them, and display specific icons based on their current access level.
This is helpful as it's a fast way for everyone to know what variables are available and how we can access them.
Below the class, we have various ways of linking the classes, which changes how they are rendered.
Component diagrams show components and the dependencies between them.
A high-level view of a component is modeled with a rectangle, and can contain the component name, an icon, or text and icon.
Interfaces are of two types, provided and required.
Provided interfaces are those exposed by our component (We are the server side that receive requests from the clients and work on those requests, and notify the clients when something changes).
Required interfaces are those exposed by internal or external components to which we connect upon. (We are the client side that receive updates from the server and request information from it).
The diagram has been drawn by using the following code:
title Component Diagram
interface "External interface" as Ext
package "Package level" {
[Component Intern Server] -up-> InternalInterface : provides
[Component Intern Client] ..> InternalInterface : uses
}
[Component Intern Client] ..> Ext : uses
Ext - [Ext Component Server] : provides
The title is what’s visible on top of the image.
Afterwards, we define an interface of some name and provide an alias for it.
At the package level, one component provides an interface, while another one uses it.
The internal component we previously defined will also connect to an external interface. Up to now, we do not know who will be the provider of this interface.
We then define another component which provides the interface as external (the one we created and aliased before).
State machine diagrams show the states and state transitions of a system. The purpose of a state diagram is to display changes in the class state.
Initial state is drawn with a black filled circle, and represents the initial state of the system.
States are drawn as rectangles, and they are used to represent the state.Transitions are drawn as a solid arrow, representing the transition from one state to another.
At the top of the arrow, we write the event which caused the state change, and optionally, a method to call when the event is fired.
A self-transition is drawn as an arrow pointing back to the same state. We usually call an action when an event changes / triggers and we don’t want to change the state.
Final state is drawn with a black filled circle within a circle, and represents the final state of the system.
title State Diagram
[*] --> Startup Startup --> InitializingState : onEventInit
Startup --> Startup : onEventRetryInit / onInitAction()
InitializingState -right-> IdleState : StartupSuccess
InitializingState -right-> ErrorState : StartupFailed
ErrorState --> IdleState : StartupSuccess
IdleState --> ErrorState : OnError
IdleState --> [*] : onEventShutdown
ErrorState --> [*] : onEventShutdown
IdleState : --> onEntryAction
IdleState : <-- onExitAction
Sequence diagrams show how objects communicate with each other and the sequence of their messages.
Participants describe the way an object behaves. They are represented with a rectangle shape.
Messages are drawn as arrows that represent communication between objects. Filled arrows are used for synchronous messages, whereas half-arrowed lines are used to represent asynchronous messages.
A reply message is drawn with a dotted line and an open arrow.
Reflexive messages occur when an object sends a message to itself.
It is drawn as a message arrow that starts and ends at the same lifeline.
The alt (alternative) label refers to an if-else statement:
There’s no possibility of both messages to be sent.
title Sequence Diagram
participant Message_Sender
participant Message_Receiver
Message_Sender -> Message_Receiver : Synchronous request message
Message_Sender <- Message_Receiver : Synchronous reply message
Message_Sender --> Message_Receiver : Asynchronous request message
activate Message_Receiver
Message_Receiver -> Message_Receiver : Reflexive message
return done
||50||
Message_Sender -> Message_Receiver : Some Important Message
alt on success
Message_Sender <- Message_Receiver : Success Message
else on failure
Message_Sender <- Message_Receiver : Failure Message
end
Data race occurs when more than two threads access the same memory and one of them is a write.
Polymorphism – “poly” (many) + “morphe” (form)
Binary search: split the range in half and check it from there. Based on the result, you will reduce half of the work by knowing in which half is the problem contained.