Author Archives: Bill Havanki

About Bill Havanki

Software Engineer for Cloudera.

Remote Work Tip #1: Maintain separation


I am a full-time remote worker for my employer. I work from my home as part of a distributed team, spread literally from one side of the (continental) US to the other. I’ve been doing this for a few years now, after about a decade and a half of the usual office / cubicle work life.

I’ve come to realize that I am, perhaps, odd about this, in a good way. Usually when someone describes remote work, they say that there are the downsides of lack of social contact and feeling hemmed in at home and such, sometimes. NOT ME, MAN. I could stay at home forever and it’d be great. I can still go where I want to, but I feel connected enough with my coworkers that the occasional trip to see everyone in person is enough. For me, that social downside is barely there.

So, having been immersed happily in remote work for some time, I can anoint myself as a minor authority on the subject, if you don’t mind. As such, I’d love to talk about tips for being an effective remote worker and loving it.

I’m not going to try to convince anyone of the merits of remote working. There’s plenty of material out there about that: studies, and real-life stories, and all that. This is for the remote worker who wants to up their remote game. Of course, I could always use tips too, so if you have them, I’m all ears.

My tips will bend towards working at home, versus at a local coworking office, because I do the former. Still, some of what I talk about will apply no matter where you physically are.

With that out of the way, here’s my first tip.

With a classic (I’ll say “legacy” with a snicker) office work environment, you go to work to work, and then you go home when you are done with work. Well, except these days, apparently, people can’t stop working even when they’re home, and have to keep answering emails and writing reports and stuff for all hours. Setting that huge problem aside, the idea at least is that at the end of the work day you go home and do all those other things in your life, you know, like eating, sleeping, and perhaps relaxing if you won’t get fired for it.

When your home is where you work, that physical separation is gone. There’s no commute either, which is super great, but that also takes away that transition time when you are either mentally preparing for the day or coming down off the day. So the temporal separation also vanishes.


Without those separations, it’s really easy to “lose track of time” and keep working. Or, have the problem I fight, which is to check back on things at, say, 10 at night, you know, because it’s all right there and maybe somebody needs something so it’s quick. This, like taking work home with you in the classic environment, is bad, for all the same reasons as the classic environment.

It’s important, when working at home, to create a semi-artificial work/non-work separation. What this means is that when you are about to start work in the morning, you say to yourself, “I’m going to work. I’m at work. Work has started,” and when you are done (and you pick that moment when you are done), you say to yourself, “I’m done with work today and I’m heading home. I’m home now. Work is over.”

It’s silly, but that doesn’t mean it’s dumb. (I joke with my family that my commute home is walking down the stairs, and the only hazard in that commute is our cat.) It keeps work from seeping into the rest of your life. Those studies about eight hours being about as much as a person can work effectively in a day aren’t irrelevant just because your work area sits inside your home.

This may sound ironic to remote work haters who figure everyone who works at home is actually lazy / slacking off / eating bon-bons and watching Dr. Phil. Well, just because those haters would do that if they were working remote doesn’t mean everyone does it. Heh heh.

Part of enforcing this separation is having a defined space for work. Sure, it’s fine to chill on the couch once in a while, but having a dedicated proper spot, just for working, is crucial to confine your work time. I’ve got a desk, set up just as it would be in an office, optimized for me getting stuff done. It’s not for gaming, or doing the bills, or anything else. When I sit there, I’m working. When I’m home, I’m not sitting there.

Your family, friends, and anyone else you live with need to help here, too. If you were working in an office, your kids wouldn’t hang all over you, or your parents call you daily, or your friends pop in unexpectedly for a few hours. Working remotely is no different. You are “on the clock” doing your job. You understand that, and they need to as well. This doesn’t mean you can’t take a break to chat with your spouse, or talk with the ‘rents once in a while. Those are benefits of working at home. But they can’t be common distractions.

Besides the physical and social separations, there’s the temporal separation, but this is tough when your commute is zero. I find it’s helpful to let myself ramp up when I’m starting to work, and also give myself time to “decompress” once I’ve declared the end of my work day. Especially with the latter, I don’t always feel present mentally, which is interesting. I guess even if a physical commute is gone, the mental one remains. Others have to help you here too, and not leap on you once you emerge from your study in the evening. You’re physically at home, but your mind needs a few minutes to catch up.

A strong work/non-work separation keeps your work life and your home life healthy. It also fosters a inner feeling and an outward impression of being a responsible employee, as dedicated as anyone back in the office. This helps keep your team cohesive, no matter where each individual is, and tells your management that you are serious about cultivating a proper remote work ethic.

The Java versioning situation

It’s been quite a long time since I’ve blogged anything here, but I think I should pick back up again. I enjoy it. It’s not like I’ve been idle for a year plus, so I’ve got a few topics I could talk about here. One that’s sort of been vexing me lately is the new Java versioning cadence.

To be honest, it’s shifted so much over the past few months that I’m not 100% confident I understand it. Where it should stand now is as described in JEP 322, and there it seems as if the ill-advised date-based versioning proposal has been set aside, relegated to the “Alternatives” section. It lingers here and there in things I read, but I’ll just proceed assuming it’s gone.

So basically we’re now in a six-month “feature” (i.e., major) release cadence, and every third release is a long-term support (LTS) release. There are some benefits to having a regular release cadence; there’s always a train ready to leave the station that you can board new features onto. I think that helps motivate the introduction of new language features, because it does away with discussion about “is this worth a new release?” – instead, it flips the question to “which release is this ready for?”

Tokyo 3345

The date-based versioning scheme, yeah, though, wasn’t a fan. I tried not to look at it as a curmudgeon oldster or anything, but I just couldn’t get myself comfortable with it. Maybe I’m too much of a semver fan, although even that doesn’t say you can’t just use the year as the major version number. I just prefer having languages version themselves independently of when they happened to show up.

Even the new scheme has a bit of an issue because that first number in the version string isn’t tied strongly to the introduction of new features or breaking changes. It’s just a one-up counter, every six months. I suppose some Java release in the future won’t have any major changes in it, but that counter will have to bumped anyway. This runs counter to organizations’ expectations that when that first number changes, it’s a big deal.

From my experience, big organizations that doesn’t do tech as their main line of business don’t grok the intricacies of version numbering. Their security teams and IT organizations just devise straightforward rules to follow, and one of those that they learned over the past decades is that when that first version number changes, you have to do a lot more acceptance / security testing before you let it in, because that means there are significant changes to the software. It’s been learned as a message from the vendor that this new release is not just a run-of-the-mill update.

Java doesn’t play by those rules anymore. I can see a (reasonably) paranoid organization balking at this swift change in version numbering. A counterpoint, though, could be browsers like Firefox and Chrome, which bump their numbers up with abandon … and Firefox at least does LTS releases. Hopefully they have served as harbingers for this alternative take on versioning.

Another odd but somewhat logical consequence of this new cadence is that those non-LTS releases of Java go EOL in six months. This makes sense from the language point of view, to motivate customers to stay current, especially for security fixes. But it’s a PITA for a software vendor, such as my employer. When Java 9 came out, should we have embraced it and moved to it as a minimum version for our software? Definitely not. Why?

  • We were just moving up to Java 8 as a minimum, because our software had promised Java 7 as the minimum for our customers. We won’t bump up the minimum Java version without a major release of our own product. Ugh.
  • What could we have done for customers who hadn’t accepted Java 9 yet? It’s not unheard of to wait a year before considering adoption of a major language revision, and Java 9 hasn’t been out a year yet (as of right now).
  • When Java 9 went EOL, what would we do? Declare you need Java 10? We’d be in for another round of testing ourselves, and probably need to cut new (major) releases. And how about those customers, still reeling from the rush up to Java 9?

And that’s the kicker. At the time of this writing, Java 9 has already gone EOL. Today, to be using a supported Java, you should be using either Java 10 or Java 8. Java 9, we hardly knew you.

A root problem here is that the enterprise world, which my employer seeks to support, isn’t yet ready for this cadence. They want stability, and we want to give them stability, so that they can manage risk for operational systems. An end-user application like a browser has a different risk profile than a language running mission-critical applications. For the latter, if the Java version it runs on is working, then it’s best not to touch it except for bug fix releases.

The operating assumption I’m going with nowadays, then, is to essentially ignore the non-LTS releases, for our own sanity and those of our customers. Really, that’s the purpose of an LTS release. If you are in a really fast-moving environment, you can upgrade with the speed you crave; otherwise, stick with the LTS releases and don’t worry about it.

That means that Java 11, coming out in September, is what we care about next, and we’d better gear up soon to test it, for when Java 8 gets yanked away. This will still cause some hand-wringing and fretting. In a way, though, we could use a little motivation to update more quickly. Not so much for the language features (which I’d like to play with), but for the security features.

Thinking about Firefox in particular, I remember it was a big deal when they switched to the Chrome-like versioning cadence. However, their seamless upgrade experience makes it work. The Java language could use something like that, but it needs to bring along with it the experience that moving from one major version to the next is no longer A Big Deal. Hopefully, after a year or two of enterprises being hitched to the new release train, that happens.

How to Kill It on a Phone Screen


Louvre-Lens Indian window screen 1605 CE. CC BY-NC 2.0, by damian entwistle (

I have been doing a lot of technical (coding) phone screens lately for my employer. For those not up on the jargon, that’s an interview over the phone with a candidate, vs. in person. It’s a “screen” because its primary purpose is to sift out the great candidates from the rest up front in a way that is inexpensive (versus, say, flying them somewhere or taking up hours of many interviewers’ time).

My schedule lately has been, on average, one screen per day. This is too many, but I guess we need people. Still, I’ve done enough now that I feel I can recommend ways that you, dear reader, can do well on a phone screen, provided that you have good enough skills. If you don’t have the necessary background and skill, though, none of these tips will help, so work on that stuff first, and use this to stand out.

Be clear and crisp

A fortunate aspect of voice transmission is that people can understand each other even on low quality connections. However, telephony providers are happy to operate as far down on that quality spectrum as they can, so it’s important to make up for that by speaking clearly. When I’m talking in person with someone, there are so many non-vocal cues I can pick up to understand you, but over the phone it’s only sound.

So, expand into that as much as you can to communicate. Enunciate a little, don’t speak too quickly, speak at a good volume. It’s OK if it sounds weird to you; remember, I’ve never met you so I won’t know the difference.

Ensuring that you are easy to understand also reduces my cognitive load. Instead of having to concentrate on understanding your words, I can concentrate on all the valuable things you are talking about.

Don’t let Verizon or AT&T determine how well you come across over the phone.

Organize your thoughts

In person, we could bandy back and forth about topics and in general have a much more natural conversational flow. That’s much harder on the phone. So, instead, take the time to be orderly and organized in how you, say, describe the cool project you’re working on, or answer a technical question.

I think conversing like this is unnatural for most people. It’s totally fine to take a moment to think before replying, to consider what you’d like to highlight, or internally plan out an answer. Just say you want to organize your thoughts. Believe me, you won’t sound dumb, especially when your answers are so much better.

Remember, a phone screen is separating the wheat from the chaff, so to speak. It’s great if you can really blow me away, but it’s even more important to make sure you can deliver solid answers and prove that you know your stuff. Well thought out answers and descriptions take care of that.

Offer opinions and personality

A secondary goal of phone screens is to see what sort of person you are. Every organization has a wide spectrum of personalities, and while a phone screener is mainly interested in checking your knowledge and qualifications, another aspect is seeing where someone like you might fit. What do we do that you might be comfortable starting with? That you might like? That your attitude fits just perfectly?

The way I can answer that as a phone screener is by hearing more than just facts. If you are oddly obsessed with unit tests; if you like making fun of people who use emacs; if you really despise statically typed languages; if you like Windows no matter what other people think; these are all great opinions to share. It opens up another dimension to your technical profile, and gives me as a screener other avenues to explore to really understand what you know.

Have a conversation and relax

It’s hard and uncomfortable to do a phone screen. Some random dude (that’s me) from a company you’d like to work for is calling you out of nowhere to test your mettle, and you can’t even see me. You probably haven’t done many phone screens before, or any phone screens for that matter. You might have thought you should dress up, just in case, even though I can’t see you. You’re nervous, and excited.

I get it. I try to help candidates relax when I start a phone screen by introducing myself and setting the stage a little, and make little funny or side comments now and again. That means it’s OK for you to loosen up a little, too. This is no doubt a serious effort for you, and I appreciate that, but you can demonstrate that you know your stuff in a less than formal way. If we wanted a deposition, we’d have you submit a report in triplicate. A phone screen means we want to chat, to get to know you and what you do.

My employer is picky, like, really picky. Odds are you won’t be hired. Despite all that, I approach each screen with an open mind, hoping to find the next awesome person. You have that chance, so let yourself come through. (It’s even more important over the phone to concentrate on that, since I’ve got no other sensory data coming in about you.) If you are hired, you’ll certainly be yourself in the workplace, so go ahead and be that in the screen. You’re nice, right?

Particulars for Coding Screens

Part of my employer’s phone screens is a coding exercise. Yeah, something like those stock interview questions, although we try to invent our own. I understand that some folks may think they are a waste of time, or that they are unfair because some people can’t just whip up code on the spot. But, a big reason we do them is to see, right there in front of us, whether a candidate can code at all. I’ve seen several sources that claim that more than half of their coding candidates can’t actually code. So, we’ve gotta check.

The goal of a coding exercise isn’t to get the “right” answer (you can guess that there isn’t one right answer – this isn’t homework). It doesn’t even need to compile. It just needs to show that you can take an uncomplicated problem statement and gin up some sort of algorithm to solve it. Maybe it involves data structures, or bit manipulation, or high-school level math. I’ll even give you pointers and help you along the way, although (like schoolwork) I can’t tell you the answer.

Given all that, here are more tips for killing it on a coding exercise.

Say something

I always emphasize this: Don’t go silent for umpteen minutes while you work. Even though we are looking at a shared editor, the main communication method is still the phone, and this is still a phone screen. Think out loud, ask questions, seek clarifications. I can’t help you if you won’t describe your ideas.

One thing you can bother not asking is whether your plan will work or not. That’d be giving you the answer, and I can’t do that. Just describe your plan and start with it. While I can’t say if something is right or wrong, I can point out where maybe there’s an issue to think about (or not, heh heh).

Type something

Seriously, type something. I understand that some candidates need a few minutes to think, plan out a design, maybe sketch out some stuff on paper before jumping in. But, I can only judge you based on what you type in, so don’t spend a lot of time before the first keystrokes.

Don’t have the loop conditions quite worked out yet? Write the loop anyway, then come back to it. Can’t remember the exact API? Put down something close to it and keep moving. Need a helper method? Declare something empty for it and use it, then if you get time implement it. Stuck? Write a comment there and attack some other piece of the problem.

This really favors people who can plan out and act fast, versus the more thoughtful bunch. I try to mitigate that by setting up a template for the problem, defined as precisely as I can, and with example executions of a “correct” implementation, to get you to the place where you really can just start rolling. In the worst case scenario, I’d rather you go with a half-baked plan, and correct it later on after we chat about it, than have nothing to look at for more than ten minutes and then see you’re off course. It’s maybe not your preferred mode of working, but a phone screen can’t last a super long time to be effective.

Get interested

There’s an old trick I learned about the SAT. The reading comprehension section of the test (I assume it’s still there) would intentionally pick the most boring-ass passages for you to read and answer questions about, because that makes things harder. You’re reading three paragraphs of Tolstoy and your eyes glaze over, and then you can’t answer the questions.

The trick is to get artificially pumped up about the paragraphs. “I am so psyched about 19th century Russian politics right now!” It’s amazing how that self-delusion will carry you through. Your retention soars, and the questions become just as easy – well, almost as easy – as those about your favorite topic.

While I hope the exercises I present aren’t that boring, I think it still helps to imagine it as a neat technical challenge that you get to play with and get into. You might be surprised at the facets of the problem that you come across, that you didn’t expect to be there. Still, since the exercises have to be small, they tend toward being more like grunt work, but doing grunt work sometimes is an inevitability of working on a coding team, so it’s best to buckle down and crank on it for the short amount of time and show what you’ve got.

The goal

To be honest, phone screens sort of stink. They cannot give me, as a screener, a full picture of who you are and what you know. They are a blunt tool used to cheaply narrow down a candidate pool, necessitated by practical limits on how much time we can devote to interviewing. It’s almost silly, because of how vital it is to hire the best you can, to use a flawed method like phone screens, but there are few lightweight alternatives.

On the plus side, though, this means that the bar for “getting past” a phone screen is lower than a full interview. The point you need to get me to isn’t “I want us to hire you” – although if you can, hey, great – but it’s “I want to learn more about you because we might want to hire you”. If things go well for you during phone screens, only then you’ll need to work at clearing the higher bar, so don’t sweat that challenge until you succeed in winning the privilege to try.

My deepest fear with phone screens is that I get you on a bad day, or I’m off my game, or we have trouble communicating, and I decide to pass on you when, really, you’d be awesome. This can happen with in-person interviews, sure, but I think it’s much more likely with a phone screen. So, I encourage you to use these tips, or other (better!) ones to minimize the odds of that happening. Let’s have my decision, and your decision too, not be warped by the limitations of phone screening.

Don’t build your tests when you run your tests

You’ve got a Jenkins job set up to run your tests automatically, like you should! Good job. 5 points to Ravenclaw.

git clone
cd awesome-test-framework
mvn -DskipTests install
java awesome-test-framework/awesome-test.jar -d where-my-tests-at run

Wait, what have you done. I’m very disappointed. 10 points from Ravenclaw.

The purpose of your test is to … run your test, not build the tools needed to run the test. You can do that anytime. When you build testing tools as part of the test:

  • you waste time – the build of the test tool will come out the same every time
  • you add an extra source of failure – if building the test tool fails, the test fails, but not because of anything wrong in what you want to test
  • you make the test more difficult to run – because the test run also needs the requirements for building the test tool
  • you make the test longer
  • you reduce test stability – if you build from a branch subject to change, like, say, master
  • kittens die

What should you do instead? You should treat the tool like the project it is, and that means creating builds for it, tagging those builds as releases, and publishing them for download. Then, tests can simply install the tool and use it. This runs quicker, has less prerequisities, and is more stable.

curl -O http://repo/awesome-test-1.2.3.jar # BOOM
java awesome-test-1.2.3.jar -d where-my-tests-at run

The obvious counter to this is that it’s an awful lot of work to devote to a test tool that isn’t going to be released to anybody; by always building from source, you always get the latest version of the tool! I’m sorry, but this doesn’t hold up under scrutiny.

  • If you build from source every time, how do you know what the tool is doing? If someone inadvertently breaks the tool, your test will fail on you and it won’t be your fault. If someone changes how the tool is used, your test will fail on you and it won’t be your fault.
  • By now, we all now refactoring is a vital part of software development. If every test is building a tool, that work must be refactored into one build pass, which means it should just be built ahead of any test. DRY.
  • You work in an organization with lots of other people, and when they use the tool, they are the customers of those who wrote the tool. Don’t those customers, your colleagues, deserve the same respect and devotion of effort that you’d give to others? Wouldn’t you love it if someone gave you a one-line installation of a cool tool?
  • Calculate the time that it takes to build a tool. Say it’s one minute. If you run a test hourly that uses the tool but builds it itself, you waste over 15 days of compute time per year that you could use for actually running tests.
  • Test tools need to be rock solid, or else you can’t be sure that your test results are valid. Did everything pass legitimately or is the tool busted and passes when it shouldn’t. You need to work from known good states of the tool, and that’s what releases are for.

Don’t give in to laziness. Set up binary releases for test tools and install them during tests like Maven, Git, or any other utility you need to run a test.

Protecting the master branch from you

An ounce of prevention is worth a pound of cure. – Benjamin Franklin

Eighteen new commits on master with questionable commit messages. Yay.

One of the most critical things you do when working with remote git repositories is pushing your changes to master. Once that is done, everyone else can see what you’ve done. And, if you mess that up, everyone sees your mistakes, and fixing it swiftly becomes a trial requiring team-wide coordination and the ugly push --force command. A couple of months ago finally messed that up one too many times, so I decided to use Git’s pre-push hook to protect the master branch from my own mistakes.

Essentially, I wanted Git to put up roadblocks to me pushing to master. The pre-push hook can perform checks and reject a push attempt purely on the client side, so it’s a perfect spot for implementing those roadblocks. I took a hook from this useful page and augmented it. While the original hook merely asks if you’re sure you want to push, I added two more checks, neither of which can be overridden interactively.

  1. A file named “ok-to-push” must exist. If it doesn’t, the hook rejects the push. This forces me to stop for a moment and not sweep right into pushing.
  2. No more than one commit can be pushed. Pushing multiple commits at once is a dead giveaway that I merged in a work-in-progress branch, instead of the polished and tested final branch that should be distributed. There is no way around this check except to do one commit at a time.

I posted the hook as a gist.

Everyone makes mistakes, but this is one mistake I’m happy to make less often. The hook is enforcing a higher level of discipline, and hopefully, in the end, will become obsolete as I adopt better habits.