melreams.com

Nerrrrd

What is good code anyway?

Unrelated goblin kitty image from pexels.com to make this post look nicer in social media shares.
Unrelated goblin kitty image from pexels.com to make this post look nicer in social media shares.

One of the many things that it took me a while to get a really solid handle on after college is what good code actually is. As a beginner, my idea of good versus bad code was solely based on whether it worked or not, it didn’t make sense to me that working code could be ‘bad.’ I was reading this blog post about writing good code (it’s really good, you should read it) the other day and thought I should talk about what good code actually is and why it matters.

First of all, a piece of code that works is always better than one that doesn’t. Credit where it’s due, I believe it was Deryk Barker who told us that back in college. Having an elegant, clear design for your application is great and all, but an application that actually does things is better than a perfectly designed application that doesn’t exist yet. Your design is never going to be perfect anyway, and if you want to accomplish anything eventually you need to write some code.

But once you have a working application, whether your code is bad or good matters a whole lot. Development is maintenance. That is, if anyone ever uses your code, it will eventually need to change, and if your code is bad making those changes will be much harder than it has to be.

Understanding what makes code difficult to change is something that just comes with experience, none of my projects in college were long term enough for me to really understand what makes code hard to change. In other words, you shouldn’t feel bad if you don’t understand what makes code good or bad right away, it’s a tough concept. It’s also a matter of taste. There are certainly some things that are near universally loathed, but there are many more things that are matters of personal preference.

Let’s start simple and work up to the more complicated stuff.

One of the simplest parts of good code is just formatting it consistently. One of the reasons I think python is a great first language is because it forces you to indent your code properly. It sounds pointlessly picky, but indenting is really, really important. Especially in HTML, I can’t tell you how many times I’ve failed to close a div because I didn’t indent my code nicely and didn’t see the problem. Consistent formatting not only helps you spot errors, it makes your code a lot easier to read. You know how your English teacher hounded you about proof-reading your essays until your spelling and grammar were perfect? That’s because it’s jarring to be happily reading along and suddenly hit something that looks wrong. Code is very similar, the more different each piece is the more time you spend trying to figure out what’s going on. Every fiddly little detail takes up more space in your brain, the more of them you can take for granted the more room you have left for what the code is actually doing.

Another formatting issue is taking advantage of language quirks like not always requiring curly braces for if statements. Java, the language I’ve used most, allows you to leave out the braces if the body of your if is only one line. I hate that a whole lot because it’s a trap: if you add another line to that if but you forget to add braces, that other line won’t actually be part of the if block and your code won’t do what you meant. You should always code to make it as difficult as possible to screw up, and leaving out braces makes it easy to screw up later.

Another big deal is having good variable and method/function names. I’ve talked about this before, but it’s worth repeating – variable names matter! Sure, you know what you mean right now, but will you remember why you named that variable that way in six months? You will not, so give your variables nice clear names. If that means your variable name has to be a bit longer, that’s fine. You’re going to read that code many more times than you write it, it’s really not worth worrying about making variable names easy to type.

Besides being descriptive, names need to be consistent too. If you name three methods handleNewOrder, handleCompletedOrder, and handleShippedOrder, your cancel method needs to be named handleCancelOrder. If you have an extremely small application it doesn’t matter so much, but in my experience most professional programming is done on applications much too large for anyone to just remember all the method names. If your method names are consistent, you can pretty much guess what they’re called and use another piece of code without having to dig through it to figure out what on earth the order cancelling method you’re sure exists somewhere is actually called. That’s a big waste of time

Methods/functions also need to do one thing and only one thing. This is one of those things that will make much more sense once you’ve worked on a larger project. Methods that do too much are a pain to update because you have to sort out which part of it does which thing and where you can safely make changes to one part without breaking the other one. They’re also a hassle if new code only needs part of the functionality of the megamethod, now you’ve got to either refactor it into more methods that only do one thing each or duplicate part of the functionality. Both of those are risky, especially if you don’t have automated tests.

Speaking of tests, opinions vary but I think they’re a really important part of good code. It’s really helpful to be able to make a change, run the test suite, and be reasonably sure (no test suite is perfect) that you didn’t break anything that used to work. Sometimes parts of your application will interact in ways you just didn’t think of, comprehensive tests can catch that before you migrate something to production that will ruin your support team’s day.

At a level up from methods, your objects should just be in charge of one thing and have reasonable names too. For example, if you have a simple todo list application, you probably want a user object and a list object, and you really don’t want the user object to mess with your list or your list object to update your user. The easier it is to guess where a particular function actually happens in your code (updating a user, for example), the less time you waste digging around trying to figure out where on earth users get updated.

Application architecture is also an important part of good code, but this post is already quite long enough :) The TL;DR version of architecture is that your objects should be grouped in predictable ways just like your methods are grouped into objects in predictable ways. More on that later!

Git tip of the day

Git is more than a little intimidating when you’re first getting started. Fortunately my friend Jen Reiher made this excellent flow chart to help you. Also, tell me that URL isn’t awesome :)

The reason I like this flowchart so much is that it’s really clearly broken down into steps and doesn’t drown you in information you don’t need. A lot of git guides start talking about branching and merging right away, and while those are important concepts they’re not necessary if you just want to put a simple project up on github so other people can see your code.

Passion isn’t everything

Unrelated image from pexels.com to make this post look nicer in social media shares.
Unrelated image from pexels.com to make this post look nicer in social media shares.

This post is a bit of a counterpoint to my previous post about why I love programming even though it’s frustrating as hell sometimes. While I feel very lucky that I get to make a living doing something I love, I really don’t like my industry’s obsession with passion. It’s great if you feel passionate about programming, but it’s simply not necessary.

“But Mel,” you say “do you really want to work with some checked-out code monkey who half-asses everything, doesn’t give a shit about technical debt, and counts the minutes until it’s time to go home?” That’s a false dichotomy right there. There are many, many more choices than “passionate programmer” and “checked-out code monkey.” No, of course I don’t want to work with someone who doesn’t care about doing a good job. Fortunately, there are only about a zillion other points on the spectrum of “total passion” to “no passion at all.” Not being the most passionate programmer who ever lived in no way means you don’t care about doing a good job or want to improve. It just means you have other things going on in your life. Honestly, I think that’s healthier than being obsessed with just one thing.

Not to mention having other interests actually makes you a better coder. Seriously, go read that article it’s really good. Having just one obsession makes it much more likely that you approach problems from just one direction where having other interests allows you to come at problems from a different perspective. Take Adam Tornhill for example, he took ideas from forensic psychology and applied them to code analysis to get some really interesting results.

Obviously you can be passionate about more than one thing, but that still doesn’t mean passion is necessary to be a good programmer. You can take pride in your work even if you aren’t in love with what you’re working on. Using myself as an example, I stocked shelves at Wal-Mart before I moved to Victoria to go to Camosun. Was I passionate about taking things out of boxes and putting them on shelves? Of course not, but I still took pride in doing a good job. I went home every day knowing I made the department manger’s lives easier, not harder. Pro-tip: doing nothing is more helpful than leaving a mess someone else has to clean up.

Or to use a more relevant example, I don’t like doing front-end layout. The endless fiddling and wondering if that element would look better where it is or 5 pixels to the right isn’t satisfying for me, it’s just annoying. But if you give me a screen mockup, the end result will match it no matter how much swearing it takes. I don’t enjoy the process, but I do enjoy knowing I did a good job.

What’s really important is caring about the quality of your work, we just use “passion” as a proxy for that because we don’t know how to measure it. Unfortunately, we don’t really know how to measure passion, either. Sure, somebody who has side projects or contributes to open source is probably passionate about programming, but that doesn’t mean someone with no public git repos doesn’t give a shit. Simply having the time to work on side projects is an enormous privilege. People who have kids, or sick relatives they need to take care of, or who need to freelance to bring in extra cash, or who have disabilities or are neurodivergent, or would rather spend time with friends and family than do more work outside of work, or just have time-consuming hobbies may simply not have the time or energy to perform passion by working on publicly shareable side projects.

None of those things mean you don’t care deeply about programming, they just mean that you have other responsibilities or interests. Hint for employers: people who have responsibilities are more focused when they’re at work because they know they can’t put in a few extra hours later and they really hate changing jobs because it’s even more of a pain in the ass. That 20-something rockstar (ugh) dev who has no serious ties to the area might decide to move to San Francisco tomorrow. Your 30-something dev who has a mortgage and a kid is a lot less likely to randomly sell their house and uproot their family. Not that you shouldn’t trust single 20-somethings, but can we please stop pretending they’re the only worthwhile devs?

If you must look for passion, at least look for actual passion and not “free time and nothing better to do”. Ask candidates what they love about programming. Ask them if they have opinions about tools and languages and programming styles. Ask them what they would learn if their job gave them some free time and a resource budget.

But if you’re realistic about what you need, I think you’ll agree that passion is a red herring and what actually matters is caring about doing a good job. Fortunately, that’s a lot easier to find.

Javascript tip of the day

If you write javascript, you probably use console.log() all the time. The other day I stumbled across this video (quite possible in javascript weekly, a newsletter I recommend if you work in javascript regularly) with a really great and very simple tip: if you’re logging an object that contains other objects, use console.table() instead. I didn’t know that was a thing! It gives you really nice easy to read output in the form of, you guessed it, a table :)

Here’s the video so you can see what I’m talking about:

Does it actually need to be optimized?

Unrelated image from pexels.com to make this post look nicer in social media shares.
Unrelated image from pexels.com to make this post look nicer in social media shares.

Learning to focus on one tiny part of your problem and ignore everything else is a really useful skill as a dev, but ironically it can also get you into trouble. It’s just as important to keep the bigger picture in mind as it is to break your problem down into little pieces and do them one at a time. Why yes, this is one of those posts that is as much for me as it is for you :)

Just because a process is slow doesn’t mean it needs to be optimized. If it hardly ever gets called, who cares if it’s slow? I know, I know, it feels wrong to see something that’s slow and leave it that way, but it’s not worth the dev time unless the process gets called often enough. Slow alone isn’t necessarily bad, it’s slow and called a lot that’s a problem. If you’re lucky you have metrics to look at and know for a certainty what gets called often, otherwise you’ll be making an educated guess. This is where understanding your application and thinking about how all the different pieces fit together comes in handy.

For example, anything you can do asynchronously is not going to be your first priority for optimization. If you can hide the processing time from the user, you may never need to optimize it. Initialization, while it is the user’s first impression of your app, also happens only once a session. First impressions are certainly important, but other actions in your app will happen much more often which makes them better targets for optimization. Assuming your load time is reasonable, of course :)

Of course, learning experiences are important too, so don’t worry about this too much if you’re a junior developer. The way you learn what isn’t worth spending time on is by messing up, it’s an unavoidable part of the process. If in doubt, talk it over with your team lead/dev lead/someone with more experience, learn as much as you can from other people’s mistakes. You’ll also learn more about programming by optimizing, so even if the end result isn’t exactly critical to your application, the practice you’ve gotten means it wasn’t a total waste of time.

One of the concepts I’m still mastering as a programmer is that nothing exists in a vacuum. Context is much more important than any individual piece of code – it’s not, “speed this thing up or let it suck” it’s “speed this thing up or do one of a dozen other things that could be more useful.” Remember, your time has a value. Speeding up one piece of code, as personally satisfying as that can be, may mean much less to your users and your bottom line than a bugfix or a new feature. Developer time is expensive, it just makes sense to spend it on the things with the greatest returns.

The next time you’re about to optimize something, ask yourself how often that code is going to be called. It might sound too simple to be useful, but trust me, it’s a very easy question to forget.

.NET JWT library tip of the day

If you use JWTs (JSON web tokens) and need to generate or consume them in .NET, you might get the idea that the Microsoft library listed on JWT.io is the way to go. It’s by Microsoft, that means it’s official and trustworthy, right?

Don’t be fooled! I mean, it is official and trustworthy, but I had a horrible time trying to use it. Save yourself the trouble and use jose-jwt if you need to handle JWTs in .NET. The readme alone is a thing of beauty, it has a shockingly comprehensive set of examples for pretty much everything you would ever want to do with a JWT. The library really is as easy to use as the examples make it look. I was able to generate a JWT with it in just a few minutes and as you might have guessed from my posts about switching to Linux, my .NET experience is extremely out of date :)

Learn from my mistakes, just use jose-jwt and pretend you never heard of the Microsoft library.

How does binary search work, anyway?

Unrelated photo by Matthew Weibe to make this post look nice in social media shares.
Unrelated photo by Matthew Weibe to make this post look nice in social media shares.

Or, yet another blog post idea I stole from that article about programming interview concepts. You can find the rest of those posts under the how does it work? tag.

Binary search is an extremely simple idea that’s useful for much more than finding an element in a sorted array. The way binary search works is you compare the item you want to find with the item in the middle of the array, then whichever “side” of the midpoint of the array your element falls on, you compare it to the midpoint of that half until you find the item you want.

According to wikipedia a binary search makes at worst O(log2n) comparisons, which is pretty great when you have a large array. Because the search halves the search space each iteration, the maximum number of iterations you’ll need is the number of times you can divide your array in half. For an array of 100 items, you should only need 7 searches, and for an array of 200 items, you only need 8, and for 1000 items, only 10 searches. See how slowly the number of searches grows as the array gets a lot larger? That’s just cool!

Also cool: you can use that concept for more than just finding stuff in arrays. Back in college they taught us to narrow down where a bug in your code is using a binary search. Basically, comment out half of your code and see if the bug still happens. If it doesn’t, uncomment half of the commented half. If it does, comment out another half of the uncommented half. It always felt weird to do that, like I should’ve just been able to see the problem by reading the code, but it worked. If you’re new or just totally stumped, give it a try.

Of course, binary search isn’t the only way to find things. Hash maps can be even faster, but all they can tell you is whether your target item exists or not. If you want to return the next largest or smallest item in the event that you don’t find an exact match, hash maps are no help at all. There are binary search trees too (which I’ll go into more detail on in a future post), but ironically even though they’re named binary search trees, binary searching an array is usually faster. The problem with binary trees is it’s hard to keep them perfectly balanced, so you might have more “halves” on one side than the other which messes with your search efficiency. What binary trees are good for is quick updates – it can be a real hassle to add or remove an item from an array, trees are much easier to work with. There’s also plain old linear search, where you start at one end of your array and look at every item until you find the one you want. If you’re not going to search your array enough times for it to be worth sorting it, linear search is good enough.

That kind of tradeoff can actually make algorithm questions interesting. I still don’t care even a little bit whether you looked up how to reverse a binary tree before the interview, but I care a lot if you think to ask if you’re going to search that array enough times to recoup the cost of sorting it. Programmers, myself included, can be terrible about overengineering to solve problems that don’t actually exist. But more on that in another post!

Linux Mint Cinnamon tip of the day

If you happen to run the Cinnamon desktop on Linux Mint I highly recommend the System Tray Collapsible applet. If you don’t run that exact distro and desktop, this post is going to be really boring for you :)

System Tray Collapsible lets you hide icons in the system tray. It’s probably meant to reduce the space your system tray takes up, but what I use it for is hiding notifications from myself. Slack, for example, adds a little blue dot to it’s tray icon when you have an unread message no matter what your notification settings are. If you’re totally incapable of ignoring a notification like I am, that can get pretty distracting. System Tray Collapsible to the rescue! If you can’t see the icon at all, there’s no blue dot to distract you.

One caveat: it can be tough to get your pointer in just the right place to see the context menu for the applet (which is the only way to tell it which icons to hide) instead of the tray icons inside the applet. Keep trying, it is possible!

Why do it?

Unrelated image from pexels.com to make this post look nicer in social media shares.
Unrelated image from pexels.com to make this post look nicer in social media shares.

So last Monday I talked about how frustrating programming can be and how important sheer bloody-mindedness is if you want to be a programmer. If that made you wonder why on earth someone would choose to do this, I couldn’t blame you :)

I love programming because I love building things. It’s just fun to make stuff – who doesn’t love LEGO? But even better than LEGO, if you mess up when you’re programming you can just revert to an earlier version, and if you want to experiment with an idea that might not work out you can create a separate branch for it.

While programming can be frustrating, there’s no physical material I know of that’s anywhere near as easy to work with. Buildings, machines, and even sculptures need to obey the laws of physics where the biggest restriction on programmers is our own ability to design a system. There are certainly things that are likely to get you into trouble, but with code as with writing, you can break all sorts of rules if you’re good enough to get away with it.

Programming is also a lot like solving a puzzle, something else I’ve loved since I was a kid. One of my favourites was the IQ block – I had a plastic one that came in a little case and it was so satisfying to get all the pieces to fit back inside it. I get the exact same satisfaction out of fixing a bug or getting a new feature working, but even more so because programs have so many moving parts. If you enjoy puzzles, code is about as complicated of a puzzle as you can find.

I get bored pretty quickly if I feel like I’m doing the same thing over and over, so the constant learning when you’re programming is great for me. There’s always something new to learn whether it’s another language, a design technique, a new tool, a new technology, or just a new way to do something. If you go into programming, you may get frustrated but you’ll never get bored :)

While professional programming is a generally a team sport, it’s amazing how much one programmer can get done on their own. It takes a factory to build a car and a team to build a house, but one programmer can knock out app after app if they want to. It’s just cool to look at something that’s actually useful to other people and be able to say “I built that.”

And yes, if you’ve read The Mythical Man-Month, my post was indeed inspired by Fred Brooks’ explanation of the joys of the craft.