Development Best Practices
“Always code as if the person who ends up maintaining your code is
a violent psychopath who knows where you live.”
Repository Best Practices
We use GitHub to host our Repository, which uses Git.
General
● Do not modify the history if it can be avoided!
● Perform frequent cleans:
git fsck //Scans for dangling blobs/commits
git gc //Cleans up dangling blobs/commits
git remote update –prune //Removes deleted upstream branches
git stash list //Lists stashed changes
git pull --rebase
If you merged since you last pushed use:
git fetch; git rebase -p @{u}
● Keep up to date:
●
Branches
Production (main, release)
● One per production version.
● Contains no further revisions or changes*.
● *No changes are to be made to production branches without confirmation from Sahil or Craig.
Development (develop)
● Used to synchronise development branches between team members, in the goal of delivering a
sprints worth of work.
● Staging branches should contain no further revisions or changes unless they come from merges
with development branches.
Feature(s) (develop_vibrantvillage_mesh, develop_candyland_vehicles)
● Whenever performing work on a sprint, that work should be captured in a development branch.
● Pushes should capture as few tickets worth of work as possible and contain references to the
tickets the work performed was for (the Jira code for the ticket: GW-19).
Automation
Bug Tracking
We use GitHub Projects, which is integrated with the repository.
Naming
Branches
● release_[classifier]
● develop_[feature/hotfix (spaces -> underscores)]
Coding Best Practices
Good Reads
● Dependency Injection: [Link]
● Patterns:
Good Questions
● Is there a correct output for each possible input? (Is it bug free)
● Is the project on schedule and within budget?
● Can the program adapt to changing requirements?
● Is the program efficient enough for the environment in which it is used?
Good Objectives
● Clear definition of purpose.
● Simple is best.
● Ruggedness (Difficult to cause error, errors fail kindly).
● Reliability.
● Extensibility in the light of experience.
● Efficiency, not for its own sake, but where needed.
● Minimum cost to develop.
● Conform to relevant standards.
● Create clear and accurate user documentation.
● Write as little code as possible.
● Make code correct first and fast second.
● Pure functions are your friend.
Documentation (Comments/Wiki)
● Every method should be commented on.
o Parameters should be explained.
o Returns should be explained.
● Complex components of a method should be commented, explaining the process.
● Document the intent of code, not the function of it.
Testing
● Unit tests should test 100% of the code paths exposed publicly.
● Fix intermittent test failures as they present themselves.
o Intermittent test failures undermine the value of unit testing.
● Always make sure a test fails at least once, even if it requires purposefully doing so.
● Smaller, tighter scoped unit tests give more valuable information when they fail.
DRY - Do not Repeat Yourself
“Every piece of knowledge must have a single unambiguous, authoritative
representation within a system.”
● Write code with the goal of never having to repeat yourself.
o Make use of Interfaces to capture common contracts.
o Make use of Abstraction to capture common logic patterns.
● The third time you write the same piece of code, it probably wants to be isolated in a helper
function or needs abstraction.
YAGNI – You Ain’t Gonna Need It
● Do not write code that you might need in the future, that is writing code for a hypothetical
future use case.
● This does not mean don’t future proof code, as that is a different process, one of writing code
that is generalised enough that it can be specialised later if needed, but still achieves what we
need it to now.
Refactoring
Refactoring is modifying the internal logic of a specific contract of use (API/class/etc) without changing
the overlying API/contract.
● Refactor whenever you see the need and have the chance.
o Such as when it would relieve a bottleneck
Naming
Namespaces
● LuvBug.[system/domain].[class]
Objects/Classes/Variables
● Consider Apps Hungarian notation: [Link]
● Use camel case for class names.
o The first letter is always capitalised.
● Interfaces must start with an I:
o BAD – Spline
o GOOD – ISpline
● Purely abstract classes must start with an A:
o BAD – Spline
o GOOD – ASpline
● Use camel case for variable names.
● Name variables descriptively:
o BAD – trkWeight
o GOOD – truckWeight/truckWeightKilogramsIndentation
Temporary Names
● For loops that are iterating over collections should be named i, j, k, …
● Temporary variables should still be named with an eye for understandability.
BAD GOOD
string str = [Link] string userInput = [Link](
(); );
Indentation
● Braces are placed on the line before and after their scope:
BAD GOOD
if (...) { if (...)
[Link]();
} {
[Link]();
}
Peer Review
● Do not be afraid to ask for help.
● Do seek out other opinions on the best approach to a given problem.
● Do get others to verify your code before it goes live.
Code Grouping
● Code that works to achieve the same sub-task within any method or class should be grouped,
such that a blank line separates the sub-task from surrounding code.
public void Set(string name)
{
if ([Link] == name)
return;
[Link]();
activeState = [Link](s => [Link] == name);
[Link]();
Avoid Long Lines
BAD
[Link]().AdditionalMethod(someArgument, anotherArgument,
anoth…
GOOD
[Link]().AdditionalMethod(someArgument,
anotherArgument,
anotherNotherArgument,
yetAnotherArgument);
File and Folder Organisation
● Parity between namespaces and folder structures should be maintained.
Avoid Hard Coding
● When making use of strings they should always be considered from a localisation standpoint.
● When making use of numericals they should always consider whether they would be dictated by
difficulty/age tables.
● Make use of static helper classes to define commonly used variables.
● Make use of player preferences to store settings/preferences.
Avoid Deep Nesting
● Wherever possible break deeply nested logic into methods, or un-nested logic:
BAD GOOD
if(a==b) if (a==b)
{ {
if (b==c)
{ }
if (c==d) else
{ return false;
if (d==e)
{ if (b==c)
... {
}
else }
return false; else
} return false;
else
return false; if (c==d)
} {
else
return false; }
} else
else return false;
return false;
if (d==e)
{
...
}
else
return false;