The definition of readability of code can vary across teams and individuals but I found some simple rules that can help to increase readability of your code with comparatively less effort. Keep in mind these rules will give you a start but if you are looking for maximum control over the readability of your code, I suggest you read the “Best Practices” chapter from Professional JavaScript for Web Developers by Nicholas Zakas.
Here are four “easy to remember” steps (comes handy when you have very little time for documentation):
Self explaining variable and function names
Variable names should tell the reader what they are meant to store in the program as clearly as possible. For example, to store last names of my friends in an array I will probably name the array “lastNamesOfMyFriends”:
var lastNamesOfMyFriends = ["Mirza", "Kim", "Xue", "Khan", "Stang"];
The examples below may not be as clear to the readers compared to the one above:
// storing last names of my friends //... since my variable name is not self-explaining var lastNames = ["Mirza", "Kim", "Xue", "Khan", "Stang"]; var names = ["Mirza", "Kim", "Xue", "Khan", "Stang"]; var ln = ["Mirza", "Kim", "Xue", "Khan", "Stang"]; var potatoes = ["Mirza", "Kim", "Xue", "Khan", "Stang"];
Similarly function name should indicate not only the purpose of the function but preferably more related information that can differentiate them from other functions. For example, to email all my friends when a new Batman movie is released, I can name a function “emailMyFriendsWhenBatmanMovieReleases”
// let's assume there is no comment or documentation for this function function emailMyFriendsWhenBatmanMovieReleases() { var listOfMoviesReleasingToday = getListOfMoviesByReleaseDate(todaysDate); for each movie from the listOfMoviesReleasingToday { if(movie.isItBatmanMovie()) { emailMyFriendsWhoLoveBatman(movie); } } }
These variable and function names may seem too long but you can always minify code before sending to production.
Consistency with indentation
As long you have the same indentation rules all over your application, I believe you are already at a very good start. It can be very difficult to have consistency when many people are working on the same application. There are many tools available that you can use or integrate with your build process to reformat the code to a pre-set standard before submitting to repository.
Consistent naming rule
Its always nice to have consistent naming convention throughout the application. Here are rules that I follow but feel free to make your own convention and try to stick to the one:
- camel casing my variables, functions, class names as required
- all upper case for CONSTANTS.
- separating words with underscore (_) for database column names, HTML placeholders, etc. such as my_main_article_content, article_column_in_database
- starting private variables with an underscore such as _myPrivateVariable. (I try not to define a meaning for more than one underscore like this __iLookLikePrivateVariable
Meaningful structure and flow of control
Programmers are like writers. Our code can be a well written story that gives the reader a clear picture of the purpose of the application and its structure. Poorly written code can confuse the heck out of the readers. Its not difficult to achieve well structured code. First we need to have a clear picture of the modules, the decomposed parts of our application that makes sense, and how the modules share responsibilities to make the application work. Try not to spend too much time on the decomposition part. Class diagrams, flow charts, and other UML components can be big help at this stage.
Here is a quick example:
// this class renders and submits a form class formController { addFormItem(); removeFormItem(); renderForm(); submitForm(); }
I could decouple form rendering and processing into two separate classes:
// this class deals with form rendering only class formCreator { addFormItem(); removeFormItem(); renderForm(); destroyForm(); } // this class deals with all the activities // after the user clicks submit class formProcessor { validateForm(); handleErrorsInForm(); submitForm(); onSubmissionSuccess(); onSubmissionFailure(); }
Here is another example of code that has a story to tell to the readers.
var isFormValid = loginApplication.getLoginForm().validateForm(); if(isFormValid) { var hasSubmissionFailed = loginApplication.getLoginForm().submitForm(); if(hasSubmissionFailed !== true) { loginApplication.removeLoginWindow().displayBankAccountInformation(); } }
Let’s rewrite the same code to make it less readable.
var form = myApp.getForm(); var valid = form.validate(); if(valid) { var error = form.submit(); if(!error) { myApp.windows[0].destroy(); myApp.windows[0] = new mainWindow(); myApp.windows[0].display(); } }
I hope you got the idea here. The rewritten version of the code is not too bad, and most developers will easily figure out the purpose of the code but the former is a better story teller.