Programming: OOP, ECS, Functional, And You

Programming: OOP, ECS, Functional, And You

Just a foreword: I used to have a really good tutorial here on what OOP was and why it was useful, but it got nuked when our database got erased. So, instead, this will be the beginning of a series of posts about games programming, tailored towards the adult games industry. Sorry for the mess.

Also I tried to have a clinical tone at first but I’m tired and have stopped caring. Sorry.

A frequent topic that comes up in game development threads and chats is how to program your game, and in particular, what programming practices and techniques to use. There are a selection of different programming paradigms that have developed over the years, and a competitive culture has grown around them, asking a simple question: Which one is best?

While such questions are certainly subjective, they have been broken down into more serious technical, methodical inquiries by computer scientists (the ones with PhDs, anyway) and departmental commissions trying to find ways of making software better. Which is one is fastest (more CPU-efficient)? Which one is more memory efficient? Which are more maintainable?

Instead of answering this right away, let’s first give a brief introduction to each of these paradigms, for those of us who are unfamiliar.

What the Fuck is a Paradigm

Before we get too carried away: When I studied in college, these were not called paradigms. They were simply introduced to us, we used them, then moved on to the next section. I don’t know who the Hell came up with the name paradigm, but it reeks of early-2000s corporate buzzwords. It appears to have stuck, unfortunately, but if I get this wrong: Fuck you I ain’t rewriting this.

With that out of the way, paradigms are simply methods of organizing code. While the most simple paradigm (functional programming) is defined by its lack of such organization, other paradigms are defined by how a programmer would arrange code into logical units, and how such units are used.

The reason for these paradigms is complicated, and dependent upon each paradigm, but the primary reason is maintainability: How the hell are you going to keep track of that one method in 100,000 methods beyond its name? Sure, you could group them into files, but after a while, those files can still become gigantic and difficult to search through.

Another reason is efficiency: If you can reduce the amount of redundant code by re-using it somehow, you can reduce the size of the project, which feeds back into improved maintainability. In addition, once data becomes structured, it becomes easier to track and maintain.

So, let’s dive in to the big names.

Functional Programming

Functional programming is the purest form of programming: the highest-level reusable structure is a method. When you first learn programming, this is often what is focused upon first.

Object-Oriented Programming

One of the earliest revolutions in programming was the introduction of Object-Oriented Programming (OOP). While many programmers curse its name and throw chairs at the mere mention of it, it’s an important addition to the programming ecosystem. In fact, many of the following paradigms are merely variations of OOP, or are a a higher-level paradigm built upon OOP.

The basics of OOP are actually simple: Code and data are built around the concepts of entities, which can be anything: physical, logical, and/or abstract. An application is an entity. A user is an entity. A file is an entity. A networking connection can be an entity. These entities have properties: A descriptive element that holds a value. For instance, John is a Human entity with a property called “Name” with a value of “John”. Finally, entities can inherit properties from one another. Consider that a Human is a Mammal: A Human entity might inherit the properties from the Mammal entity.

There is a lot more to entities, but I want this section to just give you a general idea of what OOP is, so we’ll leave it there. There’s all sorts of interesting things to learn from OOP if you’re new, so we’ll write a new post for that.

Entity Component Systems

Entity Component Systems (ECS) is a paradigm that was the result of years of programmers dealing with OOP and realizing something was missing: Mixing.

Let’s look at the example of an animal: An animal can contain lots of parts. An animal requires something to pump blood, it needs a nervous system of some type, it needs a way to move around, a way to eat food, and something to contain its organs and muscles. A traditional OOP approach would be to make a property for a heart, a property for the nervous system, one for ambulation, one for ingestion, and a final one for the skin.

However, animals in real life can get really, really weird! Insects and arthropods can have tons of legs (of varying types, so an array won’t work), and multiple hearts. Worms can move with their body, or with bristles, or both. Octopi have multiple brains… On and on it goes. Animals can also have other organs that other species just don’t have. How the fuck do we handle this nightmare?

With components.

Instead of rigidly-defined properties for each part, we turn each animal into, effectively, a bucket of parts called a container. Next, to allow each part to communicate, we give parts the ability to send signals to each other. Hearts pump, legs move, brains think, skins sense, etc. Each part can handle the signals they receive and act upon the data each signal they contain, either adding more signals or acting upon the world.

Game engines like Unity and Godot make heavy use of ECS, as various game behaviours can be mixed and matched as in-game components. For instance, a player could have a wind component blowing their hair, a gravity component handling gravity calculations, clothing, etc.

Model-View-ViewModel

It used to be that it was common for even Fortune 500 business applications to be an absolute mess. They’d have code that would read value from the database, format it, and then throw it into the UI directly. Pushing a button to submit a transaction would freeze the application while the UI connected to the database, sent a query, and dealt with the reply.

Then someone smacked their head on a toilet while they were snorting crack, realized this entire arrangement was fucking stupid, and developed the concept of MVVM: Breaking your program up into layers so that the user-interface logic was separate from back-room business.

What each layer does is dependent upon what framework you’re using and what school you follow, but most people are familiar with the following general concepts.

The view layer is what the user interacts with. The only concern of this layer is to draw the UI and to format text and numbers appropriately. When a button is pressed, an event or command is passed to a deeper layer. When data is needed, it is requested by a deeper layer and sent to the view layer for formatting.

The model layer is the deepest layer and contains business logic and data. This is where things like how to calculate a test score, the method for getting the data behind those test scores, and the actual data behind said test scores are located.

Between these two layers is the view-model layer, and this is where things get contentious. Sometimes, all this layer consists of is an automated third-party framework system that reads special properties from the UI and uses that to perform data binding between the view and model layers. Other times, you have to write this yourself. In other frameworks, the binding part is considered part of the UI layer and this layer just handles commands from the UI.

Yeah, MVVM is confusing sometimes, but the general concept of a separation of front- and back-ends has become a universal concept.

The Best?

As with many things, what paradigm works best has become a topic that invokes violent arguments on the Internet. Also like many things, the answer is not a simple one, as many graduates who have moved into actual programming jobs have discovered.

Programming paradigms grew not out of competition, but out of necessity. Large companies have large groups of people working on the same large projects, often on large sets of data. Keeping things organized wasn’t just a managerial masturbation exercise: It was the only way to stay sane and keep things coherent.

OOP grew out of a need to organize large units of code into neat logical units that could be re-used. While there is some notable overhead, it’s generally considered small enough to be acceptable for most use-cases.

ECS came out of a need to make OOP even more efficient and reusable in high-performance applications such as gaming. Again, while there is even more overhead, it still fits the needs of those that use it.

MVVM was developed after businesses saw a need for a separation between display and back-end code, particularly for security and usability requirements.

The Point

What you may be noticing here is a pattern of saying that each of these fits a set of use-cases. Functional programming can be efficient and fast for small, high-performance projects. OOP is a way of pigeonholing code into discrete, atomic units that are reusable for larger projects. ECS can be useful in certain circumstances where even more reusability and modularity is needed. MVVM is just a way of keeping UI logic detached from your other logic.

Each project has different needs. Every project manager has to examine those needs and decide what practices and paradigms will work best for their project, and often, one project can make use of multiple paradigms. For example, I have Unity games on Steam that people are playing right now that use OOP, ECS, and MVVM.

The project I’m working on right now uses OOP for almost everything, ECS (and OOP by nature) for creatures, and MVVM practices to keep UI decoupled from the backend. It’s also written in Python because I like listening to nerds scream in anguish.

Use what your game needs. Don’t listen to some idiot in /v/, /g/, or /dgg/ who screams about how everything needs to use FUNCTIONAL because PURITY and FAST.

Have a good one.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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