melreams.com

Nerrrrd

Terrible ironies of programming: people

In my last post about the terrible ironies of programming, I foreshadowed the next terrible irony:

Plus being at a computer and away from people is pretty attractive for weird little nerds who aren’t good with people

So many people go into programming thinking they’ll be left alone to code then find out programming is fundamentally a team sport. Even I used to joke that I didn’t decide to work with computers because I like people so damn much (I’ve since knocked that shit off because it’s obnoxious). I’ve come a long way, but I was an extremely shy child. One of the things I love about computers is that they make sense to me in a way that people just don’t. While I eventually came around to the idea that getting people to work together is a really interesting problem, it took over a decade.

But that’s a separate blog post! Let’s talk about one of the reasons software is a team sport: software these days is just too big for one person to build the whole thing and hold it all in their head. I say “these days” like have things have changed since software engineering first became a thing, but the top performers have always been the people who can get their questions answered faster* – it’s just more of an issue now as systems become larger and larger.

You might think that the answer to systems being too large for one person to hold the whole thing in their head is to split them up into microservices, but that just makes the people problem worse. It’s incredibly common for two people (or teams) to have slightly different understandings of what they’re building, and the more interfaces you have with other systems the more likely you are to slam face-first into that problem. Oh and if your microservice only interfaces with one other system, you should be thinking about whether it really needs to be a separate service.

Anyway, the fun thing about people having slightly different understandings of what they’re building is that you think everything is fine until everything is merged and you try to use it and surprise! It’s broken! Wheee! Building to a spec is not that hard. Making sure everybody on both sides of the spec interpreted it in exactly the same way is that hard.

Also like I said in my last terrible irony post, humans just kinda suck at programming. We need each other’s help constantly. Even if you never speak to anyone outside of your dev team and manager, you’ll still have to talk with them constantly. The lone programmer in a basement office may have been a thing in, like, the 80s, but the 80s are over, man (in case that link stops working, it’s the scene from Formula 51 where the state trooper tells Samuel L Jackson’s character that “the 60s are over, man”).

Even then, programs were getting too big for one person to know everything and even then the top performing programmers were the ones who a) knew who to ask when they had a question and b) were nice/known enough that the person they needed an answer from would get back to them in a timely manner instead of whenever they damned well felt like it.

I’m not convinced there has ever been a time where programmers didn’t need to talk with other people, we just wish there was because a lot of us nerds fantasize about being left the hell alone to code. I’m not even saying I’m not one of them, one of my favourite coding days in recent memory was when I got to put my headphones on and spend a day banging out a Python script to parse a particularly uncooperative set of log files and not talking to anyone. The thing is, that’s the exception, not the rule. As uncooperative as those log files were, they were based on an extremely detailed spec and once my tech lead told me which characters should be parsed into which field, I was good to go. Normally software isn’t nearly so well defined.

And anyway, that’s just between devs. If you have a separate QA team you need to talk with them too, both to make sure they understand how to test any given ticket and to make sure you understand what’s wrong when a ticket fails QA and comes back to you. If you have a product owner or product manager you’ll need to talk with them a lot to make sure you’re actually on the same page.

One of my big fuckups at a previous job was getting together with another dev and our manager and deciding without the PO that integrating our project with a certain existing feature we knew a big client wanted the new feature to work with was just not going to happen. Yeah it turns out that feature was a massive part of that company’s business and there was no point building the new thing if it could never work with that particular existing thing. Our poor PO sure loved that surprise when she looked at my edits to the internal wiki page for that project. There’s plenty of blame to go around on that one but as the acting team lead on that project I should’ve known better than to make a decision that far-reaching without the PO.

If you’re doing any frontend work talk with your UI/UX/designer too! I haven’t done much UI lately but even I know it’s important to be on the same page as the designer. You need to make sure you understand what the design is meant to accomplish, not just what elements you see on the wireframes or mockups. And show your designer your progress as you work through the ticket, that can uncover misunderstandings you didn’t think to ask about.

Don’t forget showing your work to actual users too. Nothing you build matters if nobody can figure out how to use it if they even wanted to in the first place. Coast Capital’s old useless activity log, I’m looking at you. I promise you it’s okay to display table data in a fucking table, you don’t have to show me almost nothing and make me click on things over and over to get any details. Also if you’re going to display a small and largely useless subset of data that appears in another report, just add another filter option that report. Between design and implementation that activity log burned at least a week of time that neither the designer or developer is ever getting back.

Your application doing the wrong thing very quickly and accurately isn’t actually useful at all. It’s not useful either if everyone hates it so much they just won’t use it. Coast Capital’s old  nearly content-free activity log, I’m looking at you again. You really do have to talk to people to build anything meaningful! Even if you build a small app all on your own and can hold the code in your head, you still need to talk to your users.

The extra fun part is that even if you personally accept that you have to talk to people to get shit done, you’re probably working with people who haven’t accepted that yet and you’ll have to pull teeth to get them to tell you wtf they’re up to, wtf their problem is with your code (ask me how much of a disaster code review can be, I dare you), and why the hell they did it that way when you told them already what you were planning and now nothing works because their part doesn’t integrate with your part correctly.

And that’s assuming everyone you work directly with shares your goal of producing realiable software that makes users’ lives a little bit easier. I have another blog post coming about coworkers who couldn’t give less of a shit about users, the company, their coworkers, or anything except getting their way.

* The Psychology of Computer Programming, Gerald M Weinberg. I’m entirely too lazy to look up the page number but I swear it’s in there.

Management tip of the day

Decorative photo of slightly golden sunlight shining through a confirous forest.
Unrelated photo by Lorenzo Hamers on Unsplash to make this post look nicer in social media shares.

When you ask your team for an estimate for a project, don’t give them an estimate to start from. If you do, you’ll likely cause anchoring bias. If you’re right, no harm done, but what if you’re not? I mean, the point of asking your team for an estimate is to get another, likely better informed opinion on how long the project is likely to take. If you accidentally bias their estimate you’re kind of defeating the purpose of asking them in the first place.

The context here is that I’ve been slowly reading Dr. Jorge Aranda’s Master’s Thesis Anchoring and Adjustment in Software Estimation while I’ve been on vacation because a) I kinda suck at estimation so the title looked very relevant to my interests and b) I have issues and it’s easier to for me to relax if I “earn” it by doing something useful.

Anyway, what Jorge Aranda’s experiment proved is that anchoring bias does affect software estimations. I haven’t finished reading it yet so the actual conclusion may differ from what I’m saying here, but I’m pretty confident about saying that if you want an accurate estimate you should avoid doing things that will obviously hit your team’s natural cognitive biases, like giving them an anchor. I’ve done that tons of times myself, I thought I was being helpful by giving my team my best guess and asking for a quick yes or no. It turns out that’s a bad idea, especially for large projects. For small tasks the harm you can cause is pretty limited, if you guess two days and the change actually takes three, meh. But for larger projects, if you guess three months and it actually takes four or five, now your boss is probably going to ask you a bunch of uncomfortable questions. Spare yourself and your team some stress by trying not to bias their estimates.

PS: Happy new year!

Link of the day: Decision-making matrix

One of the problems that really interests me lately is decision-making. Specifically, how teams can make decisions without wasting a ton of time going back and forth about what they’re going to do, and how they can prevent time-thieves from re-opening decisions they weren’t happy with.

The simple matrix described in This Matrix Helps Growing Teams Make Great Decisions at First Round Review seems like a fantastic alternative to endless circular discussions. Granted, I’d also prefer a swift kick in the shins so that’s a low bar, but the matrix is probably more effective :)

If you just want to see the matrix, search for this paragraph

It starts with a basic chart, with the two (or more) options you’re deciding between at the top. Down the left-hand column, you have benefits, costs, and — uniquely — mitigations.

That’s the core of the idea, but seriously, go read the article, especially the examples. They do a great job of showing how that matrix can help with extremely contentious decisions like whether or not to have descriptive titles for developers or just have everyone have the same title, or whether to refactor a large application. Those are the exact kind of things that waste enormous amounts of time and end with everyone unhappy if they’re handled poorly.

Another handy thing about a matrix like that is it really lends itself to documentation, whether that’s a page on your internal wiki or just a text document in a shared drive. With documentation like that, you can point a wannabe time-thief to it and go on with your day, and it’s super helpful for new employees to be able to see the reasons decisions were made. If you’re extremely motivated, you could even collect a bunch of those matrixes from past decisions and do a retro on your team’s decision-making skills.

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.

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.

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.

Lastpass tip of the day

LastPass tries to be helpful by filling in form fields for you, but sometimes it gets it wrong. If you see it fill in the wrong data or if you just mysteriously struggle to sign into services that use 2FA (for me LastPass was helpfully inserting an old 2FA code when I tried to sign into AWS, which meant AWS thought my authenticator app was wildly out of sync and would make me resync it every time I tried to log in), follow these steps and see if it helps.

In case that link ever stops working, you’ve got to find the problem site in your vault, click the little wrench icon to edit that site, then click the little wrench icon again in the edit popup to edit form fields, then delete all the fields with bad values. There may be quite a few of these.

Credit where it’s due, one of my coworkers told me about this. Thanks Logan, I don’t know if I ever would have found that on my own!

JUnit tip of the day

Fun fact about JUnit tests: if something throws an exception that prevents your test from completing normally, it can’t clean up after itself. Normally this isn’t a big deal but if, for example, your setup method adds any test data to your database or creates a whole new database, you’re going to need to clean that up manually. Turns out extra databases eat up a lot of hard drive space if you don’t tidy them up for, uh, months. Just fyi :)