What advancements did we have in the field in last 10 years?
Artūras Šlajus
2022
Games are user-facing products, known as front-end software.
There are also other front-end products:
Can we learn anything from them?
The pattern is that all of the front-end development technologies that started with imperative programming have moved to declarative / functional programming.
There is a good reason for that.
Imperative programming is hard to get right.
It is a way we express the steps our program takes to achieve the desired result.
There are multiple ways to do that.
Lets look at a two examples.
We want to get the total age of all people in the room.
static int totalAgeOfAllPeople(IEnumerable<Person> people) {
var totalAge = 0;
foreach (var person in people) {
totalAge += person.age;
}
return totalAge;
}
static int totalAgeOfAllPeople(IEnumerable<Person> people) =>
people.Select(person => person.age).Sum();
Lets look at another example.
We want to make a cake by taking butter, flour, eggs, sugar and baking powder, mixing them in a bowl, then putting it to an oven for 15 minutes at 200°C.
Bowl bowl = new Bowl();
bowl.add(new Butter());
bowl.add(new Flour());
bowl.add(new Eggs());
bowl.add(new Sugar());
bowl.add(new BakingPowder());
bowl.mix();
Oven oven = new Oven();
oven.put(bowl);
oven.setTemperature(200);
oven.bakeFor(TimeSpan.Minutes(15));
Cake cake = (Cake) bowl.takeOut();
MixedBowl bowl =
new Bowl(ingredients: NonEmpty.array(
new Butter(), new Flour(), new Eggs(),
new Sugar(), new BakingPowder()
))
.mix();
Cake cake = Oven.bake(
bowl, bakeFor: TimeSpan.Minutes(15), temperature: 200
);
Functions are great - they always always compose.
You can always take Func<A, B>
and Func<B, C>
and compose them into Func<A, C>
.
(
Bowl
=>
MixedBowl
) + (
MixedBowl
=>
Cake
)
=
(
Bowl
=>
Cake
)
Immutable data structures allow us to make invalid states irrepresentable, thus eliminating runtime exceptions.
For example: non-empty collections and taking a random element.
Easy to reason about - the function does not care about the origins of values it is getting.
Thus there is less need to know the rest of the system when refactoring.
Everything is just a pure function, with no need for mocks or brittle techniques to change the internal state of objects.
Immutable data structures make change propagation very efficient.
If the reference matches - it's the same thing!