“Open highway road through the desert of Death Valley National Park” by salvatore ventura on Unsplash

An overview of my programming style guide

Roelof Jan Elsinga

--

I’m writing this style guide to make my own code more readable and maintainable. This guide attempts to cover all of the code I write and work with, so it will be expanded over time, as I find more things to document. So far, this guide covers Laravel (and PHP in general), JavaScript, and Git.

1. Laravel

Since I mainly work with Laravel, I’ll base the PHP section of this guide on this Framework. I’ll describe things like setting up routes, dealing with service providers, name spacing, unit tests, and exposing API endpoints here. I will not get into how these work, because that’s beside the point of this post. All I’m doing here is describing how they should be written and formatted.

1.1 Routes

The routes files will be split according to purpose. There will be name spaces for Web and Api routing. To keep clear overview for other developers, route groups will be used. An example can be found below.

This basic example shows that all API routes are grouped together. It also shows that URL’s with a similar pattern are grouped in a group with a prefix. When an URL prefix changes, another route group will be made. As you can see, both “inner” route groups have the same namespace. The namespace will not dictate whether or not a new group will be made.

All similar routes will share a controller. However, if routes are separated into different route groups, they will also be separated into different controllers. This is to keep the method mapping aligned between the routes and controllers, which ultimately will make it easier to find the correct methods quickly. The controller methods will be aligned with the default Laravel resource controller methods. These can be changed in case it is more confusing to use the default methods. For example, you can choose to use “LikeController@likes” instead of “LikeController@index”. These are both valid since this keeps the routes and controllers aligned better.

1.2 Unit tests

Every public method needs a test. This way we can ensure that the application works without error before deploying it. A simple rules goes as follows: “If it doesn’t have a test, it’s not going live”. There are some great resources for writing these tests. Some Laravel specific ones can be found here, and the official PHPUnit documentation can be found here.

1.3 Methods

Methods can only have a single purpose, no more, no less. This will probably result in many more methods than you’re used to, but it will be much easier to maintain and to read. Each method can be no longer than 15 lines long. Having 5 lines would be ideal, but sometimes this is just impossible, so 15 lines are the absolute maximum. This will force you to split up your code into smaller, manageable chunks.

When writing methods, start by making each method private. When there is no other way, use protected methods for inheritance purposes or public methods for use in other classes or routes. These method names should be written with camel case rather than underscores. Camel case will also be used for class names. Any functions that are not in a class will be written with underscores, not camel case. All variables will be written with underscores.

When formatting your methods, place the opening "{" on the same line as the function, followed by a blank line. Another blank line should be placed after the return statement. An example of the ideal formatting is shown below.

With this example, we can say something about naming conventions. Methods, variables, and really any other entity, should have a declarative name. This means that anyone should be able to tell what the entity stands for, by just looking at the name. Variable names like "$data" and "$response" are not allowed.

1.4 API endpoints

Data (read JSON) returned by API endpoints should have two formats. If the response data contains an object among a selection of properties, it should be returned in camel case. Properties of the objects should be returned as underscores. This way there is a clear separation between nested objects and properties.

2. JavaScript

JavaScript can become very confusing when no clear structure or rules have been applied from the very beginning. So that’s what we start with, for now, some ground rules.

2.1 Frameworks

First of all, to ensure that you’re not completely locked into a single framework from the beginning, keep your JavaScript as vanilla as you can. This means that unless you mean to change any DOM with the specific framework, use vanilla JavaScript syntax and API’s. For example, instead of using the built-in angular method forEach, use the vanilla Javascript method forEach. See the list below for a code example.

The main selling point of using the angular forEach method is that it accepts both objects and arrays. This can be easy to use, but I'd much rather know exactly what kind of data I'm working with. So adding validation to check if the variable is an object or an array is preferred in this situation.

2.2 ES2015 (or ES6)

All JavaScript should be written in ES2015. Let's take the example above and make this into the ES2015 syntax.

As you can see, this syntax makes the code much more concise. If you're unsure what's going on here, I suggest looking at this documentation. ES2015 makes writing classes, instead of a random collection of functions, much easier. By using the arrow functions, "this" will be available in your functions and classes (like you may have seen in Java).

When writing JavaScript, group functions together into a class. This way of organizing your application will be much easier. When writing these classes, place each in a separate file. Connect the classes (and files) by importing and exporting them. This helps your bundlers (Webpack, Gulp, Grunt, etc.) build your packages in an efficient way (tree shaking) and it keeps the proper references when minifying your JavaScript.

3. Git

There are a few simple rules that I use when working with Git. The following sections cover: branch names, Git flow, and pull requests

3.1 Branch names

First of all, having consistent branch names are important to keep track of changes. Just for formatting purposes: this-is-a-valid-branch-name, but this_is_not. I want to see dashes instead of underscores in the branch names.

Secondly, descriptive names. If you use branch names like: index-page-update, you may as well delete it again. I want to know what has been changed in the branch by reading the name. A better name would be: sidebar-layout-redesign. It’s still a bit vague, but it tells anyone that’s reading the name that the sidebar has been redesigned.

The third point is related to the section below, but a “namespace” for your branch names helps to specify what kind of action you have taken in the branch: “feature/added-homepage-sidebar”, “hotfix/fixed-sidebar-padding”, “release/version-1.0”. These namespaces tell you if something was added, fixed, or released.

3.2 Gitflow

When using Git, it’s helpful to use Gitflow. This is not necessary of course, but it makes working with Git much easier. This has personally helped me to avoid merge conflicts and managing release versions. Most Git programs have this pattern built-in, but you can also use it from the command line if you wish. I personally use Gitkraken for this, but Sourcetree also supports this.

3.3 Pull requests

When working with Gitflow, you “finish” features, hotfixes, and releases. This means that the branches you created will be merged with the “develop” or “master” branch. But this way, no one gets to look at your code before you merge it, which is not a great idea. Other people may catch mistakes you made before you push it. So what you do in the Gitflow workflow is push your feature, hotfix, or release branch to the remote and create a pull request. Make a pull request from the following to the following branch:

  • feature/** to develop
  • hotfix/** to master
  • release/** to master

Now let people review your code. Once they are done with reviewing, don’t merge the pull request, but let them “approve” it. This is one of the options on the reviewing system on Github. Once your pull request has been approved, you can finish your feature/hotfix/release on your local system. Then push your develop and/or master branch to remote. This will automatically close the pull request and the process is complete.

It's a work in progress

Photo by Sherman Yang on Unsplash

This style guide will get updated to keep track of my current coding styles and when a new part needs to be documented. In the mean time, if you have any questions, suggestions or additions, please let me know in the comments. That way I can learn from you, you can learn from me, and together we can make this guide better and more complete.

--

--

Roelof Jan Elsinga

I'm a web developer, working with Docker, Laravel, Go, Angular, and Solr. My posts can be found on my personal blog at roelofjanelsinga.com