melreams.com

Nerrrrd

It doesn’t work unless it all works together

a dish of small red berries surrounded by more of the same berries
Unrelated image from pexels.com to make this post look nicer in social media shares.

Or, let’s talk about context some more!

So last week I talked about how you can’t know if code is good or bad without knowing the context, what you’re actually trying to accomplish with that code, what was most important when it was written (priorities change, that doesn’t mean that the way the code was written at the time wasn’t perfectly reasonable for the context it was written in).

But there’s more to context than that! You also can’t know whether your code is any good in isolation. In other words, unit tests are not enough and can never tell you whether your code actually works. No seriously, they can’t. That’s because your code doesn’t work unless the whole app works, and the only way you can tell whether the whole app works is with end-to-end testing.

It’s great if all the pieces work according to your unit tests, I’m not knocking those, but they can’t tell you the whole story. Only integration tests can do that.

If you haven’t run into integration issues yet, just wait, it’ll happen :) Maybe your controller doesn’t validate user input quite the same way as the service that handles business logic does. Maybe one layer tolerates nulls and another one flips out and throws NPEs. Maybe the front-end and the back-end disagree just slightly on the format of the JSON that gets passed back and forth. Maybe one layer doesn’t return the exact error codes another layer/object/service was expecting.

Hell, maybe everything is great except for some missing assets on the frontend. That’s not covered by an integration test but it’s not really unit test territory either. Some stuff just has to be looked at by a human. Yes, it’s possible to automate frontend testing but if your UI changes very often at all then it may not be worth the trouble of reworking your tests every time it changes. Plus computers are kind of terrible at stuff like “this text doesn’t line up nicely with this text box,” so you’re going to need a human to look at your UI anyway.

It would be great if unit tests were all you need, and if you have really comprehensive unit tests you will catch most of your problems, but in the real world things break not just within components but between them. An application isn’t just a collection of models, views, and controllers (assuming you went with a MVC architecture), it’s also the interactions between those components. If you aren’t testing those interactions, you just aren’t testing enough.

Of course, even integration tests have their limits. I once broke production by changing a part of the system that I thought was unrelated to the part that broke. It was not :( (also cache invalidation is the worst). Integration tests are great for things you know are related, but sometimes you just need a human to click around in the app and notice that when you change setting A, feature B that seems unrelated doesn’t see the update.

If you possibly can, learn from my mistakes: it doesn’t work unless it all works together.

Context!

a railway bridge supported by brick arches surrounded by lush green jungle
Unrelated image from pexels.com to make this post look nicer in social media shares.

So I was browsing workplace.stackexchange.com questions late one night, as you do, and came across an interesting one: How to explain business priorities to a programmer.

That one didn’t go at all the way I thought from the title. It turns out the business priorities actually did make sense (the business had this wild idea that queries, even especially complicated ones, should take less than 4 hours to run) and the programmer was being unreasonably rigid in following “best practices”.

But weirdly, one of the answers said that both parties were wrong – that the programmer shouldn’t have been so attached to having nice looking code and the manager shouldn’t have insisted on using an anti-pattern. What? The anti-pattern (using raw SQL instead of the ORM) improved performance by multiple orders of magnitude! If performance matters at all, you cannot possibly tell me that massively improving performance was the wrong thing to do.

Okay, there is some nuance there :) If your ORM performs that badly it’s likely not configured right for your situation, so it might be better in the long term to fix your config than to keep writing custom SQL for every query that’s the least bit complicated. On the other hand, if you don’t have an expert handy who can tune your ORM config, it might be easier to ditch it, at least for the more complicated queries, and just write some SQL. Or hey, how about a compromise? Use a stored procedure, that’s what they’re for! If it’s a query you run a lot, it might even make sense to make a view for it.

No matter what you end up doing, it’s still not wrong to use a supposed “anti-pattern” if you have a good reason to do it. It’s the context that makes something a bad idea, even the best idea can turn bad if you use it the wrong way. The only way to know whether your “anti-pattern” is actually a bad idea for your particular situation is…. to look at your particular situation! You can’t just say something is an anti-pattern without knowing what the person using that anti-pattern is trying to accomplish.

Let’s look at another datebasey example. It’s generally considered a bad idea to denormalize your database, every database design course will tell you so. Normalizing your database ensures all of your data is always right by isolating everything that can change independently. Since you don’t usually bother to keep data at all if you don’t care if it’s all accurate, you almost always want your data nicely normalized.

But sometimes correctness isn’t the absolute most important thing. Let’s take browser or mobile games, for instance. If your game takes too long to load, your players will just go do something else and they might not ever come back. It’s much more important to be fast than it is to be perfect if you want to make money on a game like that. And if something does go wrong and a player gets mad because their data didn’t get saved correctly, you can just give them game currency until they’re happy again.

In a situation where performance is more important than correctness, normalization is the anti-pattern. Like I said, it’s all about context!

To be clear, there are some things that are just a terrible idea no matter what you’re doing. I don’t care how clever you think you are, your variable names need to make sense. And no matter how well it performs, if your system is so confusing than no one can make updates, then it’s a bad system. But for the most part whether or not something is an anti-pattern is about what you’re trying to accomplish more than it’s about the “anti-pattern” itself.

Everybody likes code that makes sense to them, and everybody likes to feel like they’re doing things the right way, but rigidly following “best practices” just isn’t good enough. If it doesn’t help you achieve your greater goals for your application (ie not just gold-plating your code, but providing value to your users or customers), it’s just not a good idea no matter how many experts call it a best practice.

And yes, that means you can’t know if your code is good or bad without knowing exactly what you’re trying to do. Welcome to professional programming!

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

a waxing moon a little over half full against a deep blue sky
Unrelated image from pexels.com to make this post look nicer in social media shares.

Keep it simple!

It sounds obvious, but I have wasted so much time debugging problems that turned out to be something ridiculously simple like my browser cache being outdated, having forgotten to deploy my code, having made my updates in my local database instead of the staging database, etc, etc. Better developers are more productive, and you know what instantly makes a person more productive? Wasting less time!

Double checking extremely simple obvious things can save you massive amounts of time. Like I said earlier, a little self-doubt is good for you. If you can’t ever doubt yourself at all, you’re going to waste a lot of time on silly mistakes you could have just double-checked.

This can be really really hard to remember as a dev, so don’t feel bad if you mess it up sometimes. My best guess is that’s a side effect of working with complicated problems all the time, so we assume the problem has to be more complicated than just having deployed the wrong code like a dope.

Another great way to keep things simple is to build the simplest possible solution for your problem. This is such a common problem that we have an acronym for it already: YAGNI (you ain’t gonna need it). Before you write more code ask yourself “Do I actually need this?” Protip: if you actually need the thing it will be obvious. If you don’t actually need it, don’t build it. Yes, things should be somewhat flexible, but there’s a limit.

Names are a great clue to whether you’ve built something so flexible that all it’s really doing is adding complexity. If you can’t guess what your object/function/module is for by looking at its name, it’s probably too vague. Using Java reflection is also a bad sign :P

Another way to check whether you’re building something too flexible is to try to explain it to someone else. If they can’t follow what on earth you’re doing, it’s definitely too vague. Even if they can follow your explanation, another person who isn’t attached to the terribly clever idea you came up with may be a lot more willing to say “No, we don’t actually need this, this, or this. That part is really cool, though.”

You can also try asking yourself if there’s anything you could possibly take out of your design. If you were doing the thing manually (just imagine your database lookups are done in a filing cabinet or giant binder instead), what would be different? Would there be fewer steps? Fewer people/processes/forms/approvals involved? This can be a tough one for programmers because for many of us, super complicated “solutions” make us feel smart and we love to feel smart.

I’m not going to pretend I’m any sort of UI expert, but this definitely applies to UI too. Do you really need a setting for everything? No! Make a decision already, if you’re going to leave everything up to the user, what are you even for? At least provide a sensible default setting and hide the fiddly stuff no one cares about under an “advanced” tab or something.

You know who failed at keeping it simple? Yep, it’s Google bro. Hey, if he didn’t want to be used as a terrible example over and over he should have been a better engineer. Given the choice between ignoring all of the existing science about gender differences in humans and making up a ridiculous and complicated fairy tale about how even though sexism obviously exists that couldn’t possibly be the reason there are fewer women than men in tech (let’s just ignore the fact that programming started out as a job for women while the men physically built the computers), no it must be some bizarre feature of our silly ladybrains, and the simple and obvious explanation that sexism exists, dude went with the most complicated possible explanation.

The more complicated your idea, solution, or design is, the more chances it has to fail. That’s still true even if your argument wasn’t built on sand in the first place. Simplicity, on the other hand, tends to work a lot better. The fewer moving parts you have, the fewer things you have to worry about holding in your head while you build it. As a bit of an aside, if you’re ever wondered why even extremely expensive software produced by armies of highly paid contractors is so often terrible and buggy, it’s because there are too many moving parts for our poor fleshy brains to keep track of.

Simplicity is incredible timesaver, for both you and your team. Simplicity in your code reduces the number of bugs you create, and avoiding creating bugs is orders of magnitude faster than fixing them. It also makes it easier to fix your bugs when you do run into them. Simplicity in your design can be the difference between a project that actually goes into production and does something useful, and something that just never quite gets launched. Simplicity in your problem solving helps you catch silly mistakes that waste hours of your time, so keep it simple!

OnePlus 5 review

The OnePlus 5 in slate gray, from the OnePlus press photos page.

Because you definitely all care about my opinions on phones :)

The very short version is I really like this phone and recommend it for anyone who likes the Google Pixel but is put off by the price. Now for the details!

The hardware is really nice, it feels solid and well put-together. Fair warning, it is a phablet and the formfactor is very large – without a case the phone is 154.2 x 74.1 x 7.25 mm. As a bit of an aside, if you’re a woman and have any wild ideas about putting your phone in your pocket I highly recommend eShakti jeans with the deep pockets option.

I also highly recommend a case, the phone feels kind of naked without one, plus it’s expensive and smashing it would suck a lot. The Otterbox case is what I went with because I want my phone to be as well-protected as possible. That case also gives the phone a more satisfying heft in your hand, it’s almost too light without a case.

Performance wise it’s great, which is maybe not great for getting my tab habit under control. Yes, I have a problem even on mobile :) It opens demanding apps (like Tap Tap Fish, which I have a terrible obsession with) faster than my last phone, the Nexus 5x and it performs the same with one app or a dozen open. Often the only way I figure out how many apps I left open is when I hit the recent apps button looking for one of them and ending up scrolling, and scrolling, and scrolling, to find it.

The screen is really nice too, it’s huge (you know, like you would expect from a phablet) and sharp and bright. Reading on it is a much nicer experience than it was on the Nexus 5x if only because it’s bigger, but I think the colours are brighter too.

Battery life on this phone is fantastic, I’m guessing the bigger form factor allows a much bigger battery. Even running that huge bright screen for hours (say if you’re extremely bored in an airport) won’t kill the battery. And even if it does, dash charging really does charge your phone back up incredibly quickly.

I can’t condone actually taking calls on speakerphone, but if you want to use the speaker for more civilized pursuits like listening to podcasts while you get ready in the morning, it’s pretty decent. I mean, it’s a smartphone speaker, you can only expect so much, but I can hear it from across the room without turning it up as loud as it will go, so that’s handy.

All I can tell you about the camera is that it exists, I don’t take a lot of pictures so I don’t have anything useful to say about it.

Updates have come steadily since getting the phone, and even if OnePlus stops supporting the phone it’s popular enough that there’s a good chance of finding a custom ROM to put on it.

Now for the cons:

Getting the phone was seriously painful. I ordered mine about 10 minutes after a coworker and got it days after he did. The OnePlus site just doesn’t like some credit cards for no particular reason, you may want to make sure your PayPal is setup to charge directly to your credit card so you still have some protection and use that to pay for the phone.

If you order anything from OnePlus, you need to resign yourself to the fact that they will ship your order when they damn well feel like it and not a second before. If you have a workable phone then the wait isn’t so bad, but if your primary phone died weeks ago and you’re using a ~5 year old phone it’s really painful to wait and wait and wait for your phone to finally show up. In other words, don’t order from OnePlus if you’re in a hurry to get your phone, especially if they’re running a launch event.

This is probably the meanest thing I will ever say on this blog, so brace yourself :) OnePlus support is LESS USEFUL THAN DHL SUPPORT. LESS USEFUL. To be worse than DHL at delivering packages, you would have to open the package and defile it before throwing it in the garbage, and yet somehow DHL support was able to tell me what was happening with my package and where to put my tracking number when OnePlus support had absolutely no idea what was going on. If you’re going to sell a phone comparable to the Pixel for around $250 less you’re going to have to cut corners somewhere, but seriously, OnePlus support is amazingly terrible. As in, so terrible I feel perfectly safe sassing them like this because it’s not going to make them noticeably less useful.

All that said, if you can stand to wait and wait and wait for it to show up, the phone really is excellent.

Back to basics: Classes

a macbook sits on a desk surrounded by black and white plans for a house
Loosely related image from pexels.com to make this post look nicer in social media shares.

Let’s talk about classes! Classes in Java are super weird (okay they’re weird in any language), and I really struggled with them when I was learning Java, so don’t feel bad if classes/objects are hard for you.

When you write simple code where everything is in main and runs immediately, it’s way easier. With classes you can’t just write it and call it, you have to create an instance first. What’s even going on there?

A class in Java is just a blueprint, it doesn’t do anything until you create an object using the blueprint (there are exceptions but let’s go with that for now). That’s a big part of the weirdness, you write all this code and it just kinda sits there until you write even more code, and here’s the kicker: that code has to be somewhere else.

In a small project your probably have a Main class somewhere that has a main() method, that’s where you need to call your other class from. Why? Because Java says so, that’s why :) Or more precisely, when you run a Java project you have to tell the JVM where to start. Something, somewhere, has to have a main method no matter how you run your project. Even if you create an archive that you drop into a servlet container like Tomcat or Jetty, that servlet container has a main method somewhere that gets called when you start it up. It may be very stealthily called by a script that calls a script that starts a service, but there’s definitely a main method in there somewhere. No matter how complicated an application seems, it’s really just a much larger version of the tiny little projects you do in school. Programs get larger and larger but the basic principles always stay the same.

Back at basic principles, you create actual objects you can interact with using the class/blueprint. In Java you do that with the new keyword. new YourClassName() creates an object using the blueprint, you can assign that to a variable like any other value and then do what you like with it. Once you create an object it’s separate from any other object you create even if you use the same blueprint (class) again. Again, there are exceptions, but I’m trying to keep this simple.

It’s like building two houses from the same set of plans, they’re separate houses even if they start out the same. You can put completely different furniture in each of them, paint them different colours, make a bedroom into a home office, but whatever you do to one house doesn’t affect the other one. And you can put objects inside other objects, like a house object could contain a fridge object or a couch object or a CNC router object if you have an especially interesting garage.

You could also have an array of house objects – pretend you’re keeping track of one of those subdivisions where all the houses are the same :) Those houses could have a method like closeWindows (pretend it’s an automated house), so you could loop through your array of suspiciously similar houses and close all the windows if the weather report said it was likely to rain. But you would need to call the closeWindows method on every single house, if you close the windows of one house it doesn’t affect the others.

This gets much more complicated when you start thinking about multithreading, static methods, and static fields, but those are another blog post. For now all I want to get at is that Java needs you to spell out exactly where to start and that programs all work pretty much the same way no matter how complicated they are. Frameworks like Spring or Struts and containers like Tomcat and Jetty will hide details from you, but no matter how many other programs or libraries you use, the computer always needs to know where to start.

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

an alarm clock with a weathered, rusty face sits on a rustic wooden table
Loosely related image from pexels.com to make this post look nicer in social media shares.

Don’t be a time thief. More precisely, if a decision has been made let it stay made.

This tip won’t necessarily change your personal output a whole lot, although you will have more time for your own work if you don’t waste it rehashing old decisions, but it will be fantastic for your team’s productivity. Being a better programmer isn’t just about how much you personally get done, it’s also about how much your whole team gets done. If you make your team better then congrats, you’re a better developer!

You will have to deal with decisions you don’t like as a developer. I’m not saying that’s a good time, but that’s not just life as a developer, it’s life in general. You can either accept those decisions like a grownup, or you can waste everyone’s time by fighting the same battles over and over.

Now, if something has substantially changed, like a new tool has been released or there has been an announcement that an open source library is no longer being actively developed, then it may make sense to reopen a closed discussion. But if you just don’t like the decision, you’re wasting everyone’s time. Even if you are technically right it’s generally faster to rework your codebase to recover from a decision that didn’t pan out than to have the same meeting over and over. It’s not just about the single decision, it’s about how you use your time.

It’s also about morale. It’s incredibly frustrating when you have meeting after meeting and finally decide something, only to have someone drag it all back up again a few weeks later. What was the point of all the earlier meetings if a decision that’s been made doesn’t stay made? If you want people to stop bothering to share their opinions, that’s the way to do it. Like I said last time, you have to be open to the idea that you could be wrong. You need your team’s ideas to make the best decision you can, and you can’t possibly get anyone’s real ideas when you convince them that it doesn’t matter what they say.

Arguing about things that are purely a matter of opinion is time-theft too. Curly brace on the same line as the method declaration vs the next line? tabs vs spaces? line width? No professionals bother to argue about that at work (the bar is a different story, however :) ), we pick a coding standard, set our IDEs to autoformat our code correctly and move on with our lives. Some arguments simply are not worth the time it takes to have them.

Speaking of arguments that have been had over and over and are a profound waste of everyone’s time, biology simply does not and never has explained the lack of women in computer science. We seem to drag this argument back up every few years in tech and every time it’s as foolish as it was last time. Google bro is simply the latest to waste thousands of hours of everyone’s time with ideas that have been debunked over and over. A grownup, not to mention a competent developer, would never have wasted everyone’s time with an argument that’s been hashed out dozens if not hundreds of times already. You simply can’t have someone like that on your team if you ever want to get anything done – even a competent developer, which Google bro certainly is not, couldn’t offset the collective productivity lost to rehashing well understood decisions over and over.

It’s perfectly normal to want to undo a decision you don’t like, just like it’s perfectly normal to want to stay in bed on a cold, wet morning and it’s perfectly normal to want to buy lunch and skip packing one. Wanting, however, is different from doing if you’re a grownup and you just can’t be a good developer without being a grownup. Even a lone hobbyist faces frustration and disappointment, you can either let those stop you in your tracks or you can set them down and make yourself useful.

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.

Tip of the day

Remember how great Authenticator Plus is? Recently a coworker told me about another great thing it can do – categories!

If you have 2FA set up for many accounts like I do, it gets to be a pain scrolling through that list to find the one you want. Categories to the rescue! From the settings menu go to manage categories, from there you can create new categories and put authenticators in them. Categories in Authenticator Plus work more like tags than folders, you can put one authenticator in as many categories as you want. Sorry readers, that was a lie. The interface is kind of confusing, so I thought categories worked like tags, but they are actually folders. Either way they’re still really useful. Once you have your categories set up, you can switch between them from the hamburger menu. The categories list is at the top where it’s easy to find.

Now that I have my authenticators sorted into work and personal categories, it’s so much easier to find the one I want.

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 :)