If the devs on my team remember anything, I want them to remember these fundamental programming guidelines. 🎩
(examples are based on a Javascript environment, but many can be extrapolated to other environments)
Don't let anything fail silently! You will thank me when you have to debug some random error on Production that does not occur locally.
On the client-side, you'll want to flash the error to the screen in whatever framework you are using:
this.props.dispatch({ type: 'flash-error', data: "Specific error message." })
On the server-side, you'll want to print to the console and either rethrow or send a 500 response (if you are in a route):
someAsyncThing
.then(...)
.catch(err) {
console.error('Specific description of where we are in the code.', err)
throw new Error(err)
// make sure to send a 500 to the client if in a route!
// res.status(500).send('Specific description of where we are in the code.')
})
Make sure you print the actual err object as seen above, not just the error message, so that you print the full stack trace! Do NOT do console.log('ERROR: ' + err) as the error will be converted to a string and the stack trace will be lost!
State (mutable values) is the source of all evil. More seriously, it is a messy construct that introduces time as an implicit variable. More simply, it makes your code more error-prone and harder to debug.
var or let, use const. This one will set you on the right path 95% of the time. If you find yourself reaching for something other than const, ask yourself if you really need a mutable value. It's far better to create a brand new value most of the time than reusing an existing value. The reason this is so important is not that you are going to realistically mess up var every time. It is that writing var forces other developers to search the entire file to make sure the value is not being modified in any other sneaky ways. const communicates loud and clear: this is guaranteed to be the only place this value is set. This communicates clear intentions and saves other programmers lots of time.for loop and pushing items onto an array, do an arr.map(...).arr.reduce(...) (you can really do a lot with reduce).Object.assign to copy an object with a new value.Code bunnies everywhere will rejoice! 🐰
If you write a function that does some asynchronous processing, return a promise that resolves when it completes! This is a good practice even if you are not using the return value. Without it, there is no way to catch errors, no way to tell how long something took, and no way to serialize other operations. Always returning a promise for asynchronous functions gives you flexibility in the future to chain asynchronous options together and handle errors consistently.
What?!? I know. This one is hard to explain. Probably the most important one to help you level up as a programmer though. Write code that does one thing and does it well. Write functions/modules that hide their implementation, only exposing the minimum interface required. Make decisions about what functions/modules are responsible for, and don't let that bleed into other areas!
Saying the job of a programmer is to "just get it to work" is like saying the job of mountaineer is to put their left leg in front of their right. That's the easy part. The job of a programmer is to manage complexity. (Complexity != Learning Curve!!!) Good code hides implementation details while exposing a clean, intuitive interface to other modules. Much of programming is making judgment calls about possible tradeoffs. Optimize for low complexity and surface area and you will be in good shape 99% of the time.
"echo \"Looking for extraneous dependencies...\" && ! (npm ls --depth 0 2>/dev/null | grep extraneous && echo \"Extraneous dependencies detected. Please use \"npm install --save\" for wanted packages and \"npm prune\" to remove all unwanted packages.\")". Yay!I hope these tips help you and your team level up your skills and maintain a clean and maintainable codebase!
Raine Revere
clarityofheart.com