melreams.com

Nerrrrd

Be a better programmer while still having a life: part 10

a metal framework tower holding up power lines is silhouetted against a dark sky that appears to be photoshopped because it is purple
Unrelated image from pexels.com to make this post look nicer in social media shares.

A little bit of self-doubt is good for you! That might sound weird but hear me out. Doubting yourself just enough to accept the fact that you don’t know everything and will be wrong sometimes is incredibly useful in software development. So many projects have died when the thing that everyone assumed would be easy (or at least doable) turned out not to be. If you can accept that you could be wrong and do a little double checking, you can save yourself so much pain.

While we’re on the subject, if you ever hear the words “it’s done, we just need to integrate it” you should be very very afraid. Not only is the thing not done, but it’s not going to be done any time soon. I admit I’m generalizing from a small sample here, but I’ve never seen the assumption that integrating a new feature will be easy turn out to be accurate.

In general, if you’ve never used that API before, don’t assume it will be easy. Read the docs really thoroughly too – just because it sounds like that API does what you need doesn’t mean it actually does. I’ve been burned by that before and you probably will be too. Same thing for libraries you haven’t used before. Just because you think a library should work a certain way doesn’t mean it actually does. In case you weren’t already worried enough, don’t forget that sometimes the docs are outdated, missing, or just plain bad, too. There’s more than one reason building a very simple proof of concept first is such a good idea.

Like I said earlier, don’t assume you understand the problem either. Talk to people until you’re sure you understand why that feature should exist, not just what it should do. Talk to your team lead, talk to other departments, ideally talk to someone who is actually going to use the thing (I know this isn’t feasible for everyone but it’s really great if you can manage it). The assumption that you’re right about what people need kills projects too. You would think that would be an obvious thing to check, but judging by the horror stories in the news about massive government projects that turn out not to do what the front line staff actually need, it’s not obvious at all.

Seriously, I can’t stress enough how dangerous assumptions are to projects. That’s how projects end up months if not years late and massively over budget if they get delivered at all. Refusing to admit you could ever be wrong kills projects too. The real problem, underneath the assumption that integrating that API will be easy to integrate, is the assumption that you’re right and don’t need to check.

In addition to killing projects, failing to question your assumptions can also lead you to make a complete fool of yourself, a la google bro. If he had questioned any of his assumptions, if he could have faced the possibility he could ever be wrong about anything at any time ever, he would be a far better engineer. As it is he clearly can’t be trusted not to make wild assumptions that will doom his projects, and if you can’t trust someone to check their own assumptions you simply can’t trust them to work as a senior engineer. One simple definition of engineering levels is that junior developers need adult supervision, intermediate developers can work on their own, and senior developers are adult supervision. If you can’t bring yourself to accept that you could ever be wrong about anything, then you can’t competently supervise anyone.

Too much self doubt is obviously completely unproductive, and you can never know everything there is to know about your project before you build it, but a little self doubt is enormously useful and tremendously underrated. In tech we seem to place so much emphasis on always being perfectly sure of yourself but not only is that an unreasonable goal, it’s not even useful. What’s useful is understanding that the most brilliant writers still need editors, and the most brilliant programmers still need input from their teams. Nobody is right absolutely all of the time, the word for people who think they are is “delusional.”

Admit you could be wrong and you’ll end up with the right answer a lot more often.

Be a better programmer while still having a life: part 9

brown wooden wheel on an old cart with fallen leaves around it on the ground.
Vaguely related image from pexels.com to make this post look nicer in social media shares.

Don’t reinvent the wheel! I’ve touched on this before, but it definitely merits its own post.

A huge part of becoming a better developer is understanding when you don’t need to write new code to solve a problem. The more code you write, the more code you have to maintain, the more chances you have to screw it up, and the more time it takes to write it. So before you write new code, see if there’s a library, a plugin, a product, a design pattern, or a best practice that solves your problem. At least see if anyone wrote an article or blog post about a similar problem and learn from what they did.

To be fair, sometimes what you need really isn’t well served by an existing trustworthy product or library and you do need to write your own custom code, but that needs to be an informed choice, not a reflex.

What I think makes a product trustworthy is active development and a large userbase. The main advantages of using a library instead of writing your own code is that you don’t have to update it and that most of the bugs have been worked out already because so many people use it. By all means use a small library that isn’t maintained if it’s convenient and not a core part of your project, but for the love of god don’t depend on a framework/database/core part of your project that isn’t actively maintained and/or doesn’t have any users. That will just end in tears.

You also don’t want to import a library for every little thing, the more libraries you import the more bloated your project becomes and the more chances you have to run into a bug in one of them (and let’s not forget the left-pad debacle), but for stuff that would take more than a few hours to write, see if somebody else already wrote it.

For example, writing your own regex to validate email addresses is almost certainly a waste of time. Are you really going to write a better validator than the Apache Commons EmailValidator? No, you’re not. And do you want to have to maintain it forever even if you do write a great validator? No, you don’t. So use the library and move on with your day.

Yes, writing code is way more fun than integrating a library, but when you’re at work your job is to get results. If writing your own code gets the best result, do that, but if integrating a library gets the best result, do that instead. Of course, to understand what gets the best results, be it a library, a whole product, an API, a design pattern or whatever else, that means you have to understand what’s out there.

As a bit of an aside, that’s why the Google bro is an incompetent engineer – his ridiculous screed shows he either didn’t read or didn’t understand any of the existing research about personality differences between men and women (spoiler: there aren’t any statistically significant ones). While junior engineers get a pass on not searching for or not understanding existing libraries, senior engineers do not. If you can’t Google (see what I did there :D) existing research or existing libraries, you simply are not operating at a senior engineer level.

Sometimes it is useful to reinvent the wheel – modern wheels with inner tubes and shock absorbers make riding in a modern car a lot more comfortable than riding in the first cars with their solid wheels (Google bro’s wheel, on the other hand, is square and the axel is off center, which is just embarrassing). If you can’t do better than existing wheels, just use what’s already out there and save yourself some time.

Ironically, admitting that you aren’t the greatest developer who ever lived makes you a better developer. Accepting that actively maintained, well-used libraries are often better than what you would write on your own not only saves you a lot of time, but also makes your final product better.

Code smell: long parameter list

a set of train tracks in an overgrown field curves off into the distance
Unrelated image from pexels.com to make this post look nicer in social media shares.

Today’s code smell is long parameter lists. If you have lots and lots of parameters, something is likely going wrong.

Odds are good your method is just doing too much, which leads to confusing code that’s hard to understand and change. Another reason lots of parameters causes problems is that when you call that method, it’s very easy to accidentally get two parameters of the same type in the wrong order (not that that’s ever happened to me or anything).

How do you fix it?

Well, if you can break your method into separate methods that each do just one thing, do that. Not only does that solve the problem of a long, confusing, easy to mess up list of parameters, it also fixes the related problem of your method being confusing because it does too many things.

Another option if you can’t break up your method is to make a new object that holds all the parameters. Having named fields in the new object makes it a lot easier to keep track of which value goes where. If you already have an object that most or all of the parameters come from, it’s often simpler just to pass that along instead of pulling values out and passing those into the method you’re calling.

However, the more objects your caller and callee have in common, the more closely coupled they are. If your classes aren’t already closely coupled you’re probably fine to add another object they both use, but if they already have a lot in common then you should think about whether you really need that object. Of course, if your classes are extremely closely related they should maybe just be one class, but that’s a separate code smell.

And if breaking the big method into smaller ones means that the smaller ones absolutely always have to be called together, it’s probably better to leave it as one big method with lots of parameters. If you have to just remember what order to call the smaller methods in you’re asking for trouble, you will definitely mess that up sooner or later. A huge part of being a good programmer is accepting that it’s very very easy to mess it up and trying to avoid the most obvious pitfalls.

Like the other code smells, long parameter lists aren’t an absolute certainty you need to change your code, but I personally think they’re an especially strong sign that your design could be better. It’s just so easy to accidentally switch parameters, and even if you manage to keep them all straight it’s still a serious hassle to call a method with a huge list of parameters.

You know your codebase better than I do, though. Do what makes sense for your particular situation and don’t worry too much about my personal pet peeves :)

Code smell: feature envy

A large rock or very small island with a few green shrubs growing on it surrounded by greeny blue water and white surf.
Unrelated image from pexels.com to make this post look nicer in social media shares.

Today’s code smell is feature envy. Feature envy is when one class uses the methods of another class to excess. It’s called feature envy because classes that use methods from another class excessively look envious of that class’s features.

The problem with that, as usual, is the way your logic gets spread around between multiple classes. If you have one method that’s using another class so much that it’s hardly even separate from it, you’ll probably have to change things in both places when you need to fix a bug or add a new feature, but the compiler can’t tell you that you need to do that so you risk creating a shiny new bug by missing a spot.

Feature envy probably makes more sense with an example. Let’s say you have an address class and a customer class, and when you call customer.getMailingLabel() your customer class calls address.getStreetNumber(), address.getStreetName(), address.getCity() and so on to build a complete address string for printing a mailing label. Let’s imagine that policy changed and you’re now able to ship to rural mailboxes, so you need to add route and box numbers to your address and to use those instead of street number and street name if they’re present. If your code has feature envy, you have to change both the address object and the getMailingLabel method to support rural mailboxes. If you moved the getMailingLabel method into the address class, then you would only have to change one class when you wanted to change how you build mailing labels.

As with just about all code smells, feature envy isn’t always a sign there’s a problem. Sometimes you want to separate your data from operations on it, especially if you’re using a strategy or visitor design pattern. If, for example, you want addresses formatted differently for different reports, the formatting is probably more the job of the reporting code than the address object. In that case it would make more sense for a visitor to contain the formatting code so the address object doesn’t have to care about all the different reports.

Link of the day

Jessica Kerr has a really interesting blog post about how code reuse is often overrated. Back in college I learned all about how important code reuse was and how duplicated code was the worst, but we never (probably because we had a lot of material to cover in a limited time) talked about how code reuse can cause problems. Jessica gives a great explanation of how bad code reuse can paint you into a corner, you should check it out.

 

 

Code smell: switch statements

a frying pan full of brightly coloured vegetables cut into small pieces
Unrelated image from pexels.com to make this post look nicer in social media shares.

Today’s code smell is switch statements. Long switch statements or complicated if statements often (but not always!) mean that something has gone wrong with your design. Objected oriented languages give you a lot of tools to avoid big complicated switches, if you aren’t using one of those there needs to be a good reason for it. If you’re not using an object oriented language, on the other hand, I’m honestly not sure if switch statements are a sign of a potential issue. If any of my readers could weigh in on that, that would be really helpful.

But why are switch statements a problem? Because you’re spreading around logic that should probably be in one place, and if you add a value to one switch statement you’re likely to need to hunt down all the other ones and change them too.

If, for example, you have a switch statement that does different calculations based on the type of the object passed in, that logic for how to do the calculation probably belongs inside the object passed in to the switch. If you change that object, you’ll have to hunt down every place it’s used and make sure nothing else needs to be changed, which is obviously asking for trouble :) If you give each object a doCalculation method and replace the switch statement with a simple call to doCalculation, then all of the logic for that object stays inside the object. With all your logic in one place, you don’t have to search for every thing you need to change and risk missing a spot, and your design just makes more sense when logic for one thing isn’t smeared across multiple objects.

Polymorphism isn’t the only way to fix a switchy smell, if your method switches on a parameter that’s passed in, you may want to change it to separate named methods to more directly do the thing. If you have a setProperty(String name, String value) method, you could replace it with named methods like setType, setModel, setYear, etc. You might end up with a lot of little methods, but it’s still clearer than one setProperty method with a giant switch. If you end up with a truly excessive number of methods, that’s another code smell that points to your object doing too much.

Just because switch statements are sometimes a problem doesn’t mean they always are. Sometimes what you’re doing is so simple that an interface and a set of objects that implement it (or changes to your existing interface and objects) makes your code more complicated rather than less. And sometimes there just isn’t a better way to do it: factory methods and abstract factories rely on switches or a series of ifs to figure out which implementation to return.

What’s a code smell, anyway?

a rugged metal tower, possibly a lighthouse, seen at low tide on a rocky beach with puddles all around
Unrelated image from pexels.com to make this post look nicer in social media shares.

Design is one of my favourite parts of programming, but I constantly run into the problem of how to tell whether my design is any good.

Before we go any further, I think we should define what makes a good design is. My definition is that if you can change it in the future without cursing your past self, it must have been good design. You may have noticed that using that definition makes it difficult to figure out whether a design is any good until potentially months after the fact when you need to change it. It would be nice to know ahead of time whether your design is going to lead to a lot of swearing in the future, and that’s where I have trouble.

To be fair, if I could definitively answer the question of whether a design was good without having to try to change it, I’d be a millionaire and I’d be writing this post from my own private island :) Whether a design that seems good now is going to continue to be helpful in the future is just a hard problem and there’s no getting around that.

That said, I think code smells can help a lot there. A code smell is, in the words of Martin Fowler, a surface indication that usually corresponds to a deeper problem in the system. The term was coined by Kent Beck while he helped Martin Fowler with his book Refactoring.

This whole concept would probably make more sense with an example. An especially designy code smell is a class that does too much. Ideally a class should have one responsibility – if it’s concerned with more than one thing that’s a strong sign it should be broken up into separate classes. The specific problem with a class that does too much is that it’s likely to lead to long, messy methods that do too many things and don’t make sense because of it, and it generally makes it hard to reason about your system. The more one class does, the more state it’s likely to need to keep track of, and the more state one class keeps track of, the more chances you have to completely mess it up. You may have gotten a hint here that software design is about accepting that humans are bad at it and trying to work around that basic fact :p

The thing with a code smell is that it’s not a hard and fast rule, it’s just a hint that something could be wrong. Sometimes it can be reasonable for a class to do “too much,” it depends on the exact thing you’re trying to accomplish and the context (i.e. the rest of your application) that your class is part of. Having a good design is more about the thing you’re trying to accomplish than it is about following all the rules whether or not they make sense in your particular situation.

The great thing about code smells and design patterns and all that is that they let you take advantage of other people’s experience. Can you imagine how long it would take to get good at software design if you had to make all the mistakes yourself? I love hearing what other people have messed up so I can maybe avoid that particular problem. And from the other side, I’d love it if anything I’ve told another dev helped them avoid a problem. It’s all well and good if I solve a problem for myself, but if I can help a couple of people avoid the problem in the first place and if those people help a couple other people avoid that problem, then I’ve done much more good than if I quietly fixed my own code and moved on.

Stay tuned for more posts about code smells, there are plenty of them to get through :)

Javascript tip of the day

Javascript has a delete operator! Okay maybe that’s not news for people who do more frontend work than I do, but I was surprised to learn that. If you have a javascript object and want to remove one of its properties, it’s really easy. All you need to do is delete object.property. There’s more detail here if you’re interested. Now if only it wasn’t such a hassle to iterate over an object’s properties…

Ember tip of the day

Lately I’ve been working with Ember components, which are really pretty cool. For anyone who doesn’t know, in Ember components let you encapsulate layout and functionality neatly together so you can reuse things all over your app without making a huge mess.

Ember components have a lifecycle you should know about and a set of lifecycle hooks you can call. Those hooks are really handy, they let you do all kinds of things at different points in the component’s lifecycle. Be warned, though: you MUST call

this.super()

at the beginning of your lifecycle hook or your component will break in deeply weird ways. When you implement a lifecycle hook in your code, you’re actually overriding a method in the base Ember component. If you don’t call this.super(), the original function doesn’t get called and shockingly enough, it does a bunch of things that are necessary to make your component work right :)

Because Ember is open source, you can go have a look at what the base lifecycle functions do. Here’s the init function, which calls this.super() itself before it does the rest of its setup. Reading the code yourself totally isn’t necessary, but it’s interesting and might help you remember why it’s so important to call this.super().

What is technical debt anyway?

A server room full of very messy wiring. There are so many cables connecting devices together that you can't see the devices themselves,
Actually relevant image by Happy Tinfoil Cat

Technical debt is one of those things that you completely understand when you run into it, but is really hard to explain to someone who has never worked on a large application. That picture on the left of the messy server room is probably the best illustration of technical debt I’ve ever seen, and you should definitely use it the next time you need to explain technical debt to someone.

You can guess exactly how it happened, can’t you? “I know this is the wrong way to do it but we’ve got to get this server back up NOW so just string a cable over to that other switch and we’ll tidy it up later.” FYI, that never happens just once. “Later” when it’s time to tidy it up never comes either. There’s always something more important than going back and fixing something that technically works.

Even when you have the time to make a change the right way, it’s a huge hassle because the server room is already such a mess. Eventually, it gets so bad it’s just impossible to change anything without first tidying the whole thing up. That’s what technical debt is like in code, it’s just harder to see.

Every time you cut corners to get something out the door quickly, you build up technical debt. You make a little bit more of a mess, and as the mess gets worse and worse, it gets harder and harder to make more changes, just like in the messy server room.

Just like financial debt, sometimes it’s worth taking on technical debt. And just like financial debt, you need to think carefully about it before you take on that debt and you need to have a plan to pay it off. Ignoring the fact that you have technical debt is like ignoring the fact that you’ve maxed out your credit card, it just gets worse if you don’t deal with it. Unlike financial debt you don’t directly get charged interest on technical debt, but every piece of new development you do has to work around your existing debt. If your project is dead and you don’t have to change anything then your technical debt doesn’t matter, but on a project that’s still being updated you’ll eventually have to work around the corners you cut. Every time you do that without tidying up the original mess, you make more and more of a mess until you end up with something like that server room above.

All of this is completely obvious if you’re a developer who has worked on a large project, but technical debt can be really hard to explain to non-technical people because they aren’t programmers. That photo is a fantastic visual metaphor for technical debt, which is why I think it’s so great. Once you have a metaphor like that, you can have a productive conversation about technical debt with a non-programmer because they now have the slightest idea what you’re talking about :)

It would be great if management would just trust the dev team when they say they need time to pay down technical debt instead of continuously pumping out new features, and it’s definitely an issue if different parts of the company don’t trust each other, but even when they do I think it’s reasonable for managers to want to understand what’s going on. As a programmer I certainly understand the urge to yell and stomp your feet about people who don’t understand technical debt (or why sometimes things take way longer than you expected or why adding people to a late project makes it later or why you need to make time for documentation, etc, etc), but you know, it’s a lot more productive to find a way to explain it.