Devil is in the details II: immutable collections

Inmmutability is good. Just yesterday, we were discussing how good it is. But just in case, here is another example.

Let’s assume we are building the software to manage a company’s payroll. We have only these requirements:

  • The Human Resources Department should be able to hire and fire people.
  • The Human Resources Department needs to validate that a Person has a valid id before hiring her (there are very strict immigration regulations in here).
  • The Human Resources Department should be able to produce an up-to-date list of employees at any moment in time.

The simplest thing that could possibly work

With those requirements in mind, this the simplest thing we can build. A Person would look like this:

And the Human Resources Department would look like this:

Notice how we do some fancy validation when hiring a new person, and throw an error if anything goes wrong. Also notice how the employees arrary is public, because HR need to produce it upon request.

The devil is in the details

We can hire someone:

We can try to hire someone without a valid Id, and HR would throw an error:

But, we can also bypass the ID validation by modifying the employees array directly:

Boom!

Public collections should be immutable

This is, obviously, a very convoluted example. But the thing is that when we do not enforce immutability, bad things may happen, either by distraction, by means of unexpected side effects, or just by means of malicious or misbehaving code.

One way, and it is not the only possible way, to enforce immutability in the precious example might be this:

Notice how we made the mutable collection private, and we provide a readonly property (employees) that returns an immutable collection, built upon request. But, remember, what matters here is not how we create that immutable collection, but the fact that the public API of the HR class provides only immutable data.

5 thoughts on “Devil is in the details II: immutable collections”

    1. I am afraid that’s not the case. You would still be able to append items to the employees array directly, which is precisely what we should want to avoid

      1. No you can’t unless you do from within the same Swift file.
        “private(set)” limits setting the variable to call sites from within the same file.

        If that’s what’s happening in your case then “internalEmployeesList” is also accessible.

        If done right then you’ll get the following error message:

        error: cannot use mutating member on immutable value: 'employees' setter is inaccessible
        hr.employees.append(anotherPersonWithoutValidID)

Leave a Reply

Your email address will not be published. Required fields are marked *