I hadn’t published anything for a few weeks and 2024 deserves an opening post, right? Well, here it is.
I started 2024 moving quite slowly with my next goal, which is Blender. In fact, I’ve hardly made any progress. But I have read a free Unity ebook on style guides for developing in C#.
The free ebook in question is ‘Create a C# Style Guide‘ which you can download from here or from the official Unity post.
It’s a short book but very concise and useful. Many things I already knew and have been applying for years, but I was surprised to learn several new things.
The book begins by emphasizing 2 principles that I like to repeat to myself. KISS and YAGNI. Keep it simple, stupid. You aren’t gonna need it. That is, keep things simple, don’t overcomplicate, and only do what we need now without thinking too much about future needs that may never occur or very rarely.
The premise of creating a style guide for development is to work more comfortably and efficiently both alone and in a team and both in the short and long term. Why? Because following a guide gives you control, a structure, the code is similar, it’s readable, your colleagues or your future self will understand your chunks of code better and vice versa.
But as they also indicate, Clean Code, or programming “clean”, is not a one-day thing. It’s something that costs. First, because one has to pick up some habits. Sometimes even get rid of bad habits. And both to get rid of bad habits and to adopt good ones, you have to hammer and hammer and hammer.
Once we have good habits, the work doesn’t end, we have to review code, make the rest of the team have the same interest, and not abandon the project. It’s very easy for the project to grow quickly and fill up with unrefactored code and without following any kind of guide and end up being chaos.
From here I could go into many details but I’m going to focus only on the parts of the style guide that in my particular case I already use and/or will adopt from now on.
Let’s start with the naming part. One of the most complicated since naming things is always difficult. From choosing between different Casing terminologies like Camel Case, Pascal Case, Snake Case, Kebab Case… to defining whether we use nouns for variables, verbs for booleans and methods, etc.
In the end, there are many options and if you’re in a development team, it’s normal to have documentation with the style guide being used and you have to start getting used to using things you didn’t use. If the team is newly created, you’ll be lucky to participate in the meetings where this style guide will be defined. Either way, my decision for my solo-projects is as follows:
- The default private access modifier is not omitted. Meaning writing always variables like this: “private string _myText;”
- Public member variables use Pascal Case
- Private member variables are camel case and use underscores (_) as a prefix
- Local variables and parameters use camel case with no prefix
- Public and private member variables are grouped together
- Use Pascal Case nouns for class names
- If you have a MonoBehaviour in a file, the source file name must match.
- Prefix interface names with a capital I.
- Start method names with a verb (example: GetDirection, FindTarget, …)
- Use camel case for parameters
- Methods returning bool should ask questions (example: IsGameOver, HasStartedTurn, …)
- Start using the K&R style for braces (each brace on a new line and not at the end of the line called Allman Style)
- Unified indentation. 4 spaces.
- Space between variables and symbols like = or ,.
- Keep classes as simple as possible following the Single-responsibility principle (we see it in this other ebook: game programming patterns)
- In general, but mostly in methods use the DRY principle (Don’t repeat yourself)
This example of code without real functionality would be a way to apply all of the above.
public class ExampleClass : Monobehaviour
{
public float DamageMultiplier = 1.5f;
public float MaxHealth;
public bool IsInvincible;
private bool _isDead;
private float _currentHealth;
// parameters
public void InflictDamage(float damage, bool isSpecialDamage)
{
// local variable
int totalDamage = damage;
// local variable versus public member variable
if (isSpecialDamage)
{
totalDamage *= DamageMultiplier;
}
// local variable versus private member variable
if (totalDamage > _currentHealth)
{
/// ...
}
}
public interface IKillable
{
void Kill();
}
public interface IDamageable<T>
{
void Damage(T damageTaken);
}
}
Other things I have learned are:
- You can group data in serializable classes or structs to clean up the inspector
- I’m not a big fan of using comments in code if the code explains itself. Only in extreme cases do I usually use them. But I’ve learned that using [Tooltip] we can add a comment for the inspector and at the same time it serves to explain a variable in code.
using System;
using UnityEngine;
public class Player : MonoBehaviour
{
[Tooltip("The amount of side-to-side friction.")]
public float Grip;
[Serializable]
public struct PlayerStats
{
public int MovementSpeed;
public int HitPoints;
public bool HasHealthPotion;
}
[SerializeField]
private PlayerStats _stats;
}
These are just a few examples and some of the guidelines that I, as a developer, follow and will continue to follow. But as I’ve mentioned, in each development team, you have to adapt and especially emphasize following a style guide and keeping control of the code to try to ensure that “Clean Code” is achieved. It doesn’t have to be perfect. Sometimes just keeping it in mind is enough.
Until next time!
Leave a Reply