My Software Development Principles

The following is an attempt to create a concise set of principles that will allow others to understand who I am (or perhaps aspire to be) as a software developer. These aren’t specific to any sort of software development methodology or paradigm and are in no particular order. These may be obvious to seasoned developers, but they are far from ubiquitous.

Write clear, readable code.
  • I want others (as well as myself) to be able to quickly and thoroughly understand the code I’ve written. Code is not only communication with a machine or program but also with other developers.
// This
var byActiveDevice = item => item.device && item.device.active;
var activeUsers = users.filter(byActiveDevice);
// Not this
var activeusrs =usrs.filter((usr)=> {
if(usr.device && usr.device.active){ return true }
});
Follow a style guide.
  • Having a codebase with a consistent style makes it easier to read; kind of like punctuation and sentence structures in literature. Airbnb has created a great one for JavaScript here and Mark Otto has created one for HTML and CSS here. Tools like jshint make this easier.
Use semantic versioning and keep a changelog.
  • When used properly, semantic versioning (semver) is really helpful at quickly understanding the difference between versions at a high level. It might be difficult at first to understand the difference between a major, minor, and patch change but after some practice it’ll become second nature.
  • Changelogs are so important in helping people understand your software. Keep one and read them especially if you’re trying to understand an issue you are facing with someone else’s software.
Write concise code.
  • The less code there is in a codebase the easier it is to maintain. Avoid duplicating code (DRY) and building something before you need it (over-engineering).
// This
return user.active || device.active;
// Not this
if (user.active) {
return true;
} else if (device.active) {
return true;
} else {
return false;
}
Reduce complexity.
  • As the level of complexity goes up so does the opportunity for creating bugs. Sometimes it can’t be avoided, but often thinking about the problem again after a first pass will expose opportunities to simplify the solution.
Use comments sparingly.
  • Let the code speak for itself, but use comments for the logic surrounding the code if a competent developer wouldn’t be able to understand it.
// This
const offlineStatusCode = 1001;
if (response.device.status_code === offlineStatusCode) {
createPushNotification(response.device);
}
// Not this
// Device in response is offline
if (r.device.status_code === 1001) {
// Have to make another API request here to create a push
// notification
createPushNotification(r.device);
}
Use tests to hedge your human limitations.
  • It’s hard for us to keep the layout of even simple APIs in our head, not to mention the implications of changing that API multiple times. Unit and integration tests are really good at helping us keep track of APIs and that’s why I like to write them at the onset of a software project.
  • Would anyone argue that it’s far more efficient to automate the testing of code than to do it manually? Then why is there so little end-to-end testing? I like to add these during the beta phase of a software project and for new features. Selenium kind of sucks but it’s much better than nothing!
  • Regressions are demoralizing. They’re a catalyst in burnout and we’re realizing as a community that burnout has more and more of an impact on the software development process. Tests are a safeguard and as mama used to say: it’s better to be safe than sorry.
Embrace open source.
  • Using open source software is a no brainer: some of the most useful and reliable software has emerged from the open source community. Minimizing the footprint that you or your team has on the code decreases risk, increases maintainability, and can often reduce development time.
  • Modularizing your code and open sourcing modules are beneficial for the same reasons. It may take some more time in the short-term, but is often worth it in the long-term.
Use the right tool for the job.
  • Usually the right tool is one with a solid community behind it and that you have experience with. Try to stick to that, but if you really can’t see something working without a new technology, try to minimize the footprint of the new technology. If you can support them, microservices may be an option here.
  • Minimize the inherent risk associated with using new technologies by limiting how many are used. Don’t allow yourself to be tempted by a technology’s sudden popularity or feature set if it doesn’t pertain to the project. Sure, MEAN may sound cool but chances are you probably shouldn’t be using MongoDB.