Posts UML class diagrams for busy mobile developers
Post
Cancel

UML class diagrams for busy mobile developers

Do I need to know that?

Yes, but the bare minimum will be just enough. I believe that every software engineer should know what an activity, state, and class diagrams are and know how to read them.

You may ask yourself right now: “Okay, but why do I need to know that?”

For better communication within your team and other teams.

I cannot count how many times I was discussing with other iOS Developers about structure and architecture of code using natural language. We spent hours to finally understand that we had the same idea since the beginning of the conversation.

However, we wasted so much time trying to communicate without any better formal language to model our code.

And then I had to explain the same things to Android guys… (What is a protocol in your Swift? You mean interface like in Kotlin? Uggghh…)

Essentials of UML class diagrams: relations

I’m not going to talk about modeling classes itself (properties, methods). I think the most interesting and important thing is to model how classes are coupled, where are the dependencies and what is abstraction layer and what is concrete implementation.

The UML standard classifies following kind of relations:

  • association (one data type is a property of another one)
    • aggregation (property can live outside of given data type)
    • composition (every property of data type is deallocated along with this data type)
  • dependency (for example passing as argument)
  • realization (implementation of abstractions of some sort - like interface in Java/Kotlin or protocol in Swift)
  • generalization (inheritance)

In the case of an association, I’d like to skip the detailed explanation of aggregation and composition in this write-up. It’s important for modeling in general but it may be not that important to communicate your architecture in general within your team (at least during initial phases of design).

Note \ The difference between aggregation and composition is quite simple yet hard for me to explain in plain English. Let’s say that you have data type A that has a property of type B. If you destroy the instance of object A but the instances of B are not deallocated - then its aggregation. If your property of type B is deallocated along with A then it’s composition.

Association

This is the easiest one to explain. It is a simple line from one class to another - but since we’re dealing with reference and value types, therefore not everything is a class - let’s say that it’s a line between some rectangles 🙂It models relation “who owns who”

Bicycle-Saddle

The most important thing here is the arrow. It tells us the direction on who owns what.

In this case it means: Data type Bicycle has property of type Saddle

Implementation in Swift:

1
2
3
4
5
6
7
struct Saddle {}

struct Bicycle {
    let saddle: Saddle // UML diagram didn't specify name for this property
}

let bicycle = Bicycle(saddle: Saddle())

Dependency

This relation is pictured as a dashed line. Like association, it can have arrows, cardinality, or names but the most important thing to remember is that it is the weak relation. It means that one data type can be an argument to method/function/constructor/whatever in another data type but there is no property for that.

It means: Some of my methods needs that data type as their parameter but I don’t need to own any of those data types as my properties.

CustomView-UIColor

1
2
3
4
5
6
class CustomView: UIView {
    //...
    func setBackgroundGradientColors(top: UIColor, bottom: UIColor) {
    //...
    }
}

CustomView depends on instances of UIColor but it doesn’t have to have properties such as top and bottom.

Realisation

It tells that something is implementing some sort of interface. Presenting associations and realizations is the key point to understand what are the “moving parts” of application, where to put dependency injection, what should be loosely coupled etc.

Person-FullyNamed

1
2
3
4
5
6
7
8
9
10
protocol FullyNamed {
    var fullName: String { get }
}

struct Person: Printable {
    //...
    var fullName: String {
        //...
    }
}

Generalisation

It’s a classic object-oriented inheritance. I think no extra explanation is needed 🙂

ViewController-UIViewController

1
2
3
class ViewController: UIViewController {
    //...
}

What are those arrows, numbers, and labels?

Arrows describe what particular data type owns. In the case of Bicycle-Saddle example, the arrows tell us that instance of type Bicycle has some sort of property of type Saddle and not the other way around.

There can be also a line without any arrows. It happens when there is a two-directional connection between two data types.

Numbers say the cardinality which you may already know from modeling persistent storage (CoreData, Realm). We can specify answers to the following questions:

  • Does it has a single instance of other data type or entire collection?
  • Is it allowed having none of them?

Labels give us extra clues on how to name properties on the particular data types. Some certified UML experts may cry while reading this but honestly, it’s just it in practice 🙂

MainView-TextView

1
2
3
4
5
6
7
8
9
10
11
12
13
struct TextView {
    var parent: MainView?
}

struct MainView {
    var textInputs: [TextView] = []
}

let mainView = MainView()
let topTextView = TextView(parent: mainView)
let bottomTextView = TextView(parent: mainView)

mainView.textInputs = [topTextView, bottomTextView]

Summary

We went through the most interesting parts of UML’s class diagrams just to get you started to draw your lines, arrows, and rectangles. I used enormous simplification and this is not a fully competent UML guide by any means. I think it’s just enough to understand how to visualize your sketches in code and vice versa.

I hope it will save you some time during the next meeting with other fellow developers!

This post is licensed under CC BY 4.0 by the author.