What advancements did we have in the field in last 10 years?
Learning from others in front-end development
Artūras Šlajus
2022
Lets take a look around
Games are user-facing products, known as front-end software.
There are also other front-end products:
- Websites
- Mobile applications
- Desktop applications
Can we learn anything from them?
Evolution of front-end development
Websites
- JQuery (released 2006) - imperative
- Angular 1 (2010) - imperative
- Angular 2 (2016) / React (2013) / Vue (2014) - imperative + functional
Mobile applications
- Android
- XML layouts (2008, imperative) →
JetPack Compose (2021, functional)
- XML layouts (2008, imperative) →
- iOS
- UIKit (2013, imperative) → SwiftUI (2019, functional)
- React Native (2015) / Flutter (2017): functional by default
Evolution of front-end development
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.
What is a programming paradigm?
It is a way we express the steps our program takes to achieve the desired result.
There are multiple ways to do that.
-
Imperative programming is about:
- having some data;
- having some statements that change that data.
-
Functional programming is about:
- having some data;
- having some expressions that transform that data.
What is a programming paradigm?
Lets look at a two examples.
We want to get the total age of all people in the room.
What is a programming paradigm?
Imperative instructions
static int totalAgeOfAllPeople(IEnumerable<Person> people) {
var totalAge = 0;
foreach (var person in people) {
totalAge += person.age;
}
return totalAge;
}
Functional instructions
static int totalAgeOfAllPeople(IEnumerable<Person> people) =>
people.Select(person => person.age).Sum();
What is a programming paradigm?
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.
What is a programming paradigm?
Imperative instructions
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();
What is a programming paradigm?
Functional instructions
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
);
Let's compare!
Imperative
Functional
- Primary goal is mutation.
- Which is achieved with statements.
- Code is about how to do.
- Primary goal is transformation.
- Which is achieved with expressions.
- Code is about what to do.
Where does functional programming shine?
Composability
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
)
No more runtime exceptions
Immutable data structures allow us to make invalid states irrepresentable, thus eliminating runtime exceptions.
For example: non-empty collections and taking a random element.
Local reasoning
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.
Tests are easy
Everything is just a pure function, with no need for mocks or brittle techniques to change the internal state of objects.
No more dirty checking in UI
Immutable data structures make change propagation very efficient.
If the reference matches - it's the same thing!
Nothing is perfect
- The performance is worse in a small scale compared to imperative code.
Thus if you need maximum performance, you must use imperative (although you can still apply functional techniques there!).
- Needs learning. But that is why you are here, right? 😉
Let's compare (pt. 2)!
Imperative
Functional
- Primary goal is mutation.
- Which is achieved with statements.
- Code is about how to do.
- Composition is about data.
- Usually less pressure on garbage collector.
- Maximal local performance.
- Large scale software becomes hard to comprehend.
- Primary goal is transformation.
- Which is achieved with expressions.
- Code is about what to do.
- Composition is about functions.
- Can put pressure on garbage collector (if done wrong).
- Not maximal local performance.
- Large scale software is still
easy to comprehend.
Suggested architecture
-
Imperative paradigm in the small scale.
- Gameplay code.
- Maximum performance.
- Fairly isolated, easy to understand.
-
Functional paradigm in the large scale.
- Application architecture / User Interface code
- No need for maximum performance.
- Usually interconnected and complex, large need for clarity.
- Perfect for writing and maintaining large-scale long-term projects.
Next stop
- To know how to use functional programming in our games we first have to learn the basic building blocks of the functional paradigm.
See you in the next video!
U2. Learning from others in front-end development
By Artūras Šlajus
U2. Learning from others in front-end development
Exploring what other camps of front-end development have been up to and what options does that give to us.
- 406