DaedTech

Stories about Software

By

Breaking Free of the Golden Handcuffs

In a comment on my post about how to resign from your company, I was asked about advice for a situation where you don’t like your job, but they’re paying more than any other competitors in the industry.  In other words, what to do when leaving the company would mean that you’d personally take a haircut, financially speaking, and have to go somewhere for a smaller paycheck.

I refer to this situation as “golden handcuffs,” though I Think that term applies more to firms specifically offering you financial incentives aimed at retention, such as delayed vesting in your 401K, lump sum bonuses for staying on, etc.  I personally think that a salary well above fair market value (which is, ipso facto, what we’re discussing here) is just another form of this — we’ll make you stay by offering you money you can only make by staying.

But regardless of terminology, the question is, “what do I do about this state of affairs?”  As I see it, there are a number of solutions.  I’ll briefly cover some common sense ones first, and then get to the more interesting solutions.

Obvious Solutions

First of all, you could always just leave and take a reduced salary.  You’d obviously need to set your affairs in order financially to accommodate for the lower paychecks that would be coming your way.  A good way to do this might be to estimate what you’d command on the market, ratchet down your budget accordingly, and put the surplus in savings for a bit to help smooth the transition when you do make the move.

Another obvious solution is that you could simply “suck it up” and keep at your current job.  It’s all well and good for people to say “money isn’t everything,” but money does have real world, practical uses, like medical bills, mortgages, and children’s tuition.  It might be that, however much you don’t enjoy what you’re doing at work, you need the money and will just have to grin and bear it (though this can be a reasonably temporary solution where you bide your time until you’re clear of some obligations).

Last up here is the Hail Mary, which is sort of a modified version of “suck it up,” wherein you go out looking and interviewing but with the stipulation that you receive pay comparable to what you currently get.  It could always be that you’re simply assuming that you’re overvalued but really you aren’t.  Honestly, the single biggest predictor of your next salary is your current salary.  You might be surprised at how readily a new firm will pay you what you’re making or a bit more.  But, if you’re accurate in your self-valuation, you wind up in “suck it up” mode indefinitely, but at least you’re constantly looking.

Now, with those out of the way, here are some interesting options.

Supplement Your Income

So, you have a job that you really don’t like and you’re there 40 hours per week (and not a minute more, amirite!?)  Perhaps you don’t even give them quite that many because of organizational inefficiency or unstructured-unstructured time and maybe that’s even why you want to leave.  Whatever the case may be, there’s a decent chance that you’re not exactly dedicating all of your spare brainpower to your current gig for as long as your golden handcuffs keep you and the company reluctantly married.

Take some of your spare time (or perhaps some of your unstructured-unstructured time at the office) and secure another line of income.  This could be something like moonlighting or consulting for money, but the reality here is that you’re tying up extra hours on top of (or in lieu of) current work hours.  So, even if this gets you extra income to make the jump to something lower paying, you might have to work 40+20=60 hours at the new gig to have the same income as just 40 at your current gig.

A better solution is to work on something that generates passive income for you.  It could be something like a rental property (I mean, you typically don’t wind up with golden handcuffs without a bit of gold in the mix), but it could be something more in line with your day-to-day.  For me, Pluralsight authorship has helped to give me a decent amount of career flexibility.  Perhaps you could monetize a blog, write a book, or something else along these lines.  This is not an overnight solution, but it’s a career option to consider over the long haul.

(Please note, I’m not encouraging you to misappropriate your company’s time to pursue your own financial interests.  If you choose to do that, it’s purely your own ethical conundrum — I’m encouraging you to economize downtime not otherwise accounted for, such as commutes, quiet home time, or cases where you literally have nothing to do at the office and couldn’t even be helping the organization with a side project)

Orchestrate a Non-Lateral Move

Speaking of what to do in your spare time that could help, how about brushing up or solidifying your credentials toward the next career step?  Are you a software developer?  Time to shoot for Senior Software Developer.  Already a Senior?  Shoot for Architect?  Already an Architect?  Dev Manager.  You get the idea.

This type of career jump can be somewhat hard to negotiate, but it comes with an expected increase, that, in the case of golden handcuffs, might translate to a lateral move from a salary perspective.  However, it’s anything but lateral for you as you’re now in a position to resume a career of growth and get COLAs and merit increases that pace the industry.

Admittedly, this can be difficult, but it can also be doable.  Identify the position title that you’re after, and then look at common job descriptions for it, focusing on the responsibilities.  Those are the things that you want to be able to tell people in an interview that you are currently doing.  So, if you’re gunning for Architect, ask to sit in on formal code reviews or architecture meetings or whatever the grand code poobahs at your company do.  Work your way into these types of responsibilities and then, in interviews for this career-advancing move, you can say, “well, it’s not official in my position title, but I have been doing the role of X for a while now.”  It’s not as much of a no-brainer as going from Architect at Acme Inc to Architect at Beta Inc, but it should get you a fighting chance.

Make Your Skill Set More Marketable

So, let’s say that you lack the spare time to secure passive/other income (perhaps you hate your job because they work you 60 thankless hours per week) and you don’t think you can swing a non-lateral promotion.  What you can do is identify why you’re comparably devalued on the market and then do something about that.

A common scenario might be that you’re using dated or obscure techs.  Your company pays you handsomely to maintain a maze of code written in Cobol and VB5 because there are like 4 other people in the world with that combination of skills and they refuse to lose you.  Meanwhile, you hate writing code in Cobol and VB5, but recruiters aren’t exactly knocking down your door and calling you a “A Full-Stack Ninja Rockstar.”  Well, your company is probably good and hosed no matter what, but there’s no need for you to keep sinking with that ship as they buy weird, old decommissioned machines capable of running a compiler that no longer exists.

If you have spare time, start writing some Ruby or C# or whatever in your spare time.  If you don’t (because they’re mercilessly working you 60 hours per week), start finding ways to bring the new stuff into your day-to-day.  Sell management on letting you write some new functionality in a more modern language.  Or just do it, reasoning that it’s better to beg forgiveness than ask permission.  Find a way to get some kind of modern tech plausibly onto your resume, and watch your options improve.

Change Your Company

I’m not sure who said it originally, but I first heard a quote that I love from the .NET Rocks guys.  “Change your company… or change your company.”  The context, as you might imagine is that if you’re unhappy, you should try to change the way your company does things and, failing that, you should leave for a more suitable company.  What I’m advising you, Golden Handcuffs, is actually the converse of that — quitting ain’t an option for you, so try changing your company.

Anarchist

A company offering you golden handcuffs presumably needs you around.  This gives you some bargaining leverage.  If you’re exhausted or miserable because of working conditions, talk to HR about it.  If it’s the techs or the fact that you’re surrounded by Expert Beginners, start a grassroots movement toward improvement.  Or, perhaps, secure an assignment where you’re more on your own and can have some creative freedom and autonomy.

The key here is to identify the things about the company that make you happy and develop actual strategies for addressing them.  Changing an organization can be exhausting and it’s often a long-play, but it’s doable.  In my career, at times, I’ve emerged from such efforts battered, tired, and war-torn, but ultimately successful to some degree.  You can do this too — the pay is already good, so make the rest of it good.

Time Is On Your Side

To wrap up, I’ll note that the one common thread here in your favor tends to be time, provided you’re not just twiddling your thumbs, running out the clock to retirement (and even then, you might argue that it’s on your side).  Most of these solutions take time to implement and will have a higher probability of success, the longer that you can stick out your current situation.  For instance, I’ve implemented organizational changes that only really took root after I’d left, and it took me years of blogging, writing, and mentoring before I turned any of my moonlighting activities into passive revenue streams.  Had I been desperate for a change but unable to secure a competitive paycheck, these things wouldn’t have been my game-changer by any means.

It may sound like cold comfort if you’re in this situation right now, but assuming you can’t simply take the income hit or continue to suffer indefinitely and check out, you’re going to have to strategize and bide your time.  But it’s my experience that once you lay out a plan and start acting on it, you’ll feel a renewed sense of purpose and see that proverbial (cliched) light at the end of the tunnel.  There’s a pretty good chance, in fact, that lacking a feeling of real purpose is at least part of what’s bumming you out about your job in the first place, since it’s clearly not money.  Here’s a chance to take it back.

By the way, if you liked this post and you're new here, check out this page as a good place to start for more content that you might enjoy.

By

Chess TDD 13: Moving On

In the last bunch of installments of this series, I’ve implemented methods for pieces to determine where they can move on a board and/or done some refactoring.  But I’ve ridden that train as far as I can, now having implemented all of the pieces, so it’s time to shake things up a bit.  Another thing that makes this post different is that I’m going to try a new way of structuring my test classes.

The other day, in response to a comment, I made a post about test initialize methods and Steve Smith commented and suggested an approach he described in detail in this post on his blog.  The gist of the idea is dispensing with the old stand by of having a test class for class Foo called FooTest and instead having the name of the test class describe the context of the test, BDD-style.  I found this idea immediately appealing and decided I’d try it out in “some project to be determined,” but what’s the fun in that?  Once an idea settles in my head, it’s hard for me to shake it, so instead of doing it later, I’ll do it here, now, publicly.  Apologies in advance (I’m typing this part before recording the coding) if it results in a bit more floundering, but I think it might be fun for us all to learn together.  If nothing else, you’ll get to see how easy or difficult it is to adapt to this convention.

Anyway, here is what I accomplished in this clip:

  • Got started on complete move calculation implementation.
  • Defined the setup of complete board for a lot of tests.
  • Established a new pattern for constructing tests.

And here are some lessons to take away.

  • When you are exposed to a new practice or way of doing things, there’s no time like the present.  While it may not always be practical to ram the new stuff into some time sensitive project, experiment and try it out to see how you like it.  Trying out different techniques keeps you sharp and helps you avoid falling into a rut.
  • When you haven’t looked at code in a long time, it’s easy to lose track of internal implementation of classes.  One of the real perks of TDD and having a test suite is that it’s easy to poke and experiment to see what’s going on without fear that you’re going to break something.
  • If kept concise and focused, a bit of yak-shaving in your implementations can be pretty productive.  Always be looking to improve on your code’s readability, elegance, and efficiency if you can.
  • It’s important to keep your test suite as communicative and descriptive as possible, and you should always be looking for ways to help you toward that end.

By

A Developer’s Guide to Recruiters

More and more of my posts these days are in response to reader questions, but this one actually isn’t. However, I’ve been asked about specific aspects of this general theme frequently enough that I figured this was a good subject to cover. I’ve dealt with a lot of recruiters in my career, both as a candidate and a candidate seeker, and this has put me in a position to at least have an informed opinion about the subject. It’s something that’s at times overwhelming and often counter-intuitive, so hang with me, and let’s take a tour through the subject. Even if you’re a savvy job-hopping veteran, maybe I can at least offer you a different technologists’s perspective.

First Up, Check Yourself

Okay, so there are a lot of recruiters out there, and you’ve probably seen a less than stellar display from some of them. “5 Years of Experience with Swift.” “Mad XML coding skills.” “C-Pound a plus.” It’s common for developers to laugh together at these antics. There are even (hilarious) twitter accounts lampooning this. It can also be annoying to get repetitive emails from some organization about jobs that are not fits for you or to have a guy call you three times in a day, saying things like, “I couldn’t help but notice you hadn’t returned my first two calls.” I get that.

But here’s the thing. You’re incredibly, ridiculously fortunate to be in a position where so many people are saying, “hey, please come interview for this job for more pay” that you find it annoying. I’m not saying “you’re fortunate” in the sense that you lucked into it — I know this isn’t easy work — but that you’re fortunate the market is and remains so strong. It can be overwhelming at times, but imagine the alternative of being stuck in a dead end job and being thrilled when some company wants to schedule a phone interview after you’ve sent out 100 resumes through monster.com or something. You might not even know what monster.com is, and that’s because you don’t have to go looking for jobs like other people. That’s the reason that recruiters exist — because the only way to find software developers is to go prying them loose from other firms, and it’s not like CTOs are going to take it upon themselves to start cold-calling competitors’ developers to offer them interview opportunities (though some larger companies do have staff recruiters that do this).

Also to consider is that recruiters are humans, and often they are humans probably no more interested in cold calling you than you are in receiving cold calls from them. Their paycheck depends on calling up a bunch of people who are most likely to sigh angrily and tell them to lose their numbers. That’s not exactly the stuff dreams are made of, so you might extend them a touch of sympathy and understanding if they’ve built up a thick skin and don’t seem overly sensitive to your social signals. They’re out there trying to make a living by getting you job interviews.

The Nature of the Game

Alright, up front caveats aside, the next thing to understand is how the game actually works. Follow the money and understand everyone’s motivations. Understanding everyone’s motivations is the key to knowing whether you’re being fed a line or whether you should take what you’re being told at face value.

Recruiters are sales people. Their customers are companies that need software developers. Their product is mutually beneficial employment agreements, which really means that their product is you, developer. Recruiters sell you to companies. Kinda literally. Typically, their cut is 20% of your first year’s pay, give or take. So, if Devs’R’Us places you with Acme Inc for a starting salary of 100K, Acme Inc. writes Devs’R’Us a check for 20K, and the individual recruiter (typically) gets some kind of commission on this. (This obviously doesn’t apply to companies with internal recruiting staffs, except that I’d wager their recruiters are still incentivized with a commission structure.) If things blow up before an allotted time period (often 6 months) and you and the company part ways, recruiting firm has to cough back up their cut in the form of a refund.

So, you’re a “customer” of recruiters the same way that you’re a “customer” of Facebook or Google — you aren’t. You get a benefit for free by allowing something of yours to be sold to a bidder (your labor, in the case of recruiters, your ice bucket challenge videos in the case of Facebook, and everything short of your soul in the case of Google). Understanding this is the key to understanding recruiter behavior.

Amway

So Hot and then So Cold

This leads to sort of a weird arrangement. Typically, when you hear from a recruiter, you’re more than likely to ignore them or politely decline their invitations. But, if you don’t — if you show some interest — suddenly they’ll start blowing up your phone with interviews on which they want to send you. “Let’s pencil you in tomorrow morning for a phone call with Intertrode and how does your Thursday look for an in-person with Initech, and also my boss, the senior recruiter, would like to get on a call with you, and…” Wow. But then you say no thanks on Initech and Intertrode says no thanks on you, and suddenly you never hear from the recruiter again. Curious, you call and leave a message, and nothing. Maybe they get back to you halfheartedly.

Here’s the reason that this is happening. When you decide to stop ignoring the recruiters of the world, you suddenly become “fair game.” What the recruiter then does is evaluate every one of its clients that are seeking candidates and send you on a bunch of speed dates, trying to be the one to place you before anyone else snatches you up. But if none of those things works out, you’re yesterday’s news and not really worth revisiting until later when they’ve filled enough positions and taken on enough new openings that they can cross reference you against a bunch of new things.

Of course, not all recruiting firms are identical in their approach, but this is extremely common. I can’t tell you how many times I’ve heard from a recruiter that was extremely excited about a few gigs or even a single gig, and then radio silence for 3 or 6 months, only to have this repeated again and again. Recruiters’ clients are the companies, so they systematically go looking for people that would match that particular vacancy. Once they find you to match that one, they’ll economize by considering you for any others as well, but after that initial wave, it’s on to the next set of people.

If you can find a recruiter or a recruiting firm that is developer-focused — that is, one that gets your resume and talks to you, and then regularly checks in with you about potential positions — hang onto this one and partner with them on a long timeline. This is not common and it’s a nice resource for you.

They Say the Damndest Things

When you’re actively engaged in the interview process courtesy of a recruiter, the recruiter wants everything to go well. They want you to show up on time for the interview and make a good impression. They want the interview to go well and both sides to be impressed. They want things to sail along, resulting in offer, acceptance, and employment for at least six months. Cynically, that’s it, anyway. In reality, they probably want both sides pleased over the semi-long term so that companies keep giving them business (though they also depend on market fluidity, so they probably don’t want anyone sticking anywhere for too long). They want to pluck you from companies and put you in a new job as quickly as possible because higher churn rate means more money. Toward that end, they’ll say a lot of things, some of which are solid advice (such as their position on counter offers, described here), and some of which are nonsense.

Bear in mind their goal and the fact that they don’t mind a bit of reality distortion to achieve that goal, and it’ll be easier to understand why they say what they do and whether you should believe it. Here are some things that I’ve heard multiple times from different sources that you shouldn’t let fool you:

  • “Why don’t you come in for an in person interview with us?”  Nah, don’t do that.  It’s not a good use of your time.  They basically want to make sure that you’re not going to embarrass them and cause them to look silly to their clients, so they’d prefer to make sure you can dress and act like a human.  You can offer to do a chat over Skype, and they’ll usually be fine with that.  I personally just decline outright with no offer of anything because there are plenty of fish in the sea.  Almost invariable they say, “oh, yeah, that’s okay.”  If you’re employed, you don’t get that many absence excuses — don’t waste the ones you have going to meet with recruiters.  A lot of the savvier recruiters will often ask to meet you 20 minutes before your interview, so you could even suggest something like that.
  • “It’s okay for you to call in sick again, people do it all the time.”  No, that’s not true.  People don’t call in sick on a Monday morning and then again on a Wednesday afternoon “all the time.”  To be clear, the recruiter doesn’t care a lick if you get in trouble or jeopardize your current role — in fact, they’d probably prefer it because it would make you more likely to accept an offer, should one be made.  Do not ever listen to recruiter ‘advice’ about how to handle your job search when it comes to your current employer.
  • “We really need to get you over there today or tomorrow because they’re probably going to fill this role soon.”  Don’t rearrange your schedule as part of a pressure sale.  One of two things is happening here.  The first is that the recruiter is trying to light a fire under you to move quickly, in which case, who cares.  Schedule things when they make sense for you, not to let the recruiter squeeze in a commission before month’s end.  The other case is that the company is really scrambling to fill a role, and if that’s the case, you’re probably better off moving on anyway.  I mean, can you picture a company like Amazon, Facebook or Google saying “we really need a warm body in here in the next few days, so even though your resume is impressive, if you’re not here by Wednesday we can’t use you?”  That sort of reeks of desperation and I would consider it a red flag.
  • “Yeah, it’s not technically a senior title, if that’s the kind of thing that matters to you, but this is a great opportunity that you should take.”  Senior title.  Certain pay grade.  Certain benefits/perks, whatever.  If you have requirements you’ve made clear up front, don’t let them wheedle/coax/beg/manipulate/browbeat/guilt you into thinking that you’re being silly or overly picky.  Your requirements are requirements for a reason, but the recruiters don’t care at all about that reason or your ambitions.  If you want to leave your current role to become a “Senior Software Engineer” somewhere, don’t let them cause you to doubt your goals.  They want their placement fee, no matter what your title/pay/benefits/etc.
  • “Look, I make more money if you make more money, so I want to get you as high a salary as possible, but you really should take this offer as-is.”  Yeah, well, let’s talk expected value.  If there’s a 100% chance of offer acceptance of a 100K offer, there’s a 100% chance of the recruiter getting 20K for an expected value of 20K.  If there’s a 50/50 chance of an offer acceptance at 110K, the negotiated wage, the recruiter has an expected value of only 11K (50% chance of 22K and 50% chance of zero-Ks).  And they know it.  Like real estate agents, they don’t want you to have the highest wage — they want you to sign the offer.
  • “This is really a great opportunity and you should take it.  I’ve helped place billions of developers just like you and I know a little something about this industry.  Think of how much it will benefit your career and your personal life and everything else to blah, blah, blah….”   You don’t need life coaching from a recruiter.  This ‘advice’ when there’s an offer in hand is something you should utterly and completely ignore.  Think of the conflict of interest.  It’s like a car salesman telling you how important car ownership is when you’re contemplating a purchase.  Of course they’re going to say it, whether or not it’s true.  So it’s literally just noise.  Tune out the recruiter and make your decision.

You may hear these exact things, variants thereof, or even arguments I haven’t encountered, but the important thing is always to keep in mind how they make their money and what their motivations are.  Their goals are mostly aligned with yours — you both want you to be placed in a new role that makes you happy.  But to you “makes you happy” is most important and to them “placed in a new role” is most important.

Working Effectively with Recruiters

With your goal and their goal being pretty similar, it’s not terribly hard for your relationship with them to be a beneficial one.  Here are some tips that I’ll offer for getting the most out of working with recruiter:

  • Decide your requirements for changing jobs ahead of time and be crystal clear about them when talking to any recruiter.  In fact, state up front that you’ll immediately shut down the interview process if at any point you discover one of them won’t be met.  If they believe you on this count, they’ll have no incentive to try to shoe-horn you into something with the hopes that they’ll figure out how to persuade you to take it.
  • Be firm about things, but be polite.  Sales pitches of any sort can be annoying, but keep your cool.  Stick to your guns, make your position clear, but resist the temptation to get worked up in any way.  They are, after all, trying to help you in general.
  • Screen your phone calls.  If you’re actively engaged with a number of recruiters in a job search, you’ll probably get a lot of calls that might be awkward to take during the day.  They might also be pinging you with needless status updates or check-ins.  Your mileage may vary, but I’ve generally found it helpful to let them leave messages and call them back later.
  • In advance of dealing with recruiters, decide on your preferred times of day/week for phone interviews and recruiter calls and also decide on your preferred medium of communication, such as email, text, phone call, whatever.  Make this clear to the recruiter up front.
  • Let them address and cover your mistakes.  Just like they’re trying to sell you on the company, they’re trying to sell the company on you.  If you had a brain fart and thought your phone interview was tomorrow morning instead of this morning, call the recruiter and ask what to do.  Most likely, they’ll apologize to the company and say it was their miscommunication.  Smoothing over logistical snafus is something they’re good at and usually willing to do.
  • Let them help you negotiate and do things like thank you notes.  I know I said that they’ll want you to accept offers as is, but once it’s clear that you won’t be deterred from negotiating, they’ll turn right around and apply the same shtick to the company about you.  Having this intermediary is nice because it defrays conflict between you and someone who is about to be your employer.  In general, the recruiting firm is good at maintaining the best face of both you and the company to the other party.
  • Avoid giving recruiters specifics of leads/offers you’ve obtained through other recruiters.  They’re clearly just going to try to talk you out of whatever it is, so there’s really no need to have the conversation.
  • Whatever happens, don’t take it personally.  Ideally, you land a job, and the company, recruiter and you are all happy.  But maybe you get two offers and then decide to take the other one.  Maybe you even accept an offer and then quickly switch to taking a better one (or decide to stay put).  Maybe you pass on an offer.  There are a lot of end-games where recruiters might resort to more desperate techniques: lecturing you, affecting anger, sadness or disappointment, telling you that you’ll never get a better offer, even vaguely threatening you.  It’s all part of the game.  I promise you that no matter what they might say to you and how you might react, they’ll call you in three months about a new full stack senior role as if nothing ever happened.  It might be offensive to you, but it’s just part of the game.

Recruiters provide a service that matters to our industry where job hopping is common and demand is through the roof.  They grease the skids for us to be able to move fluidly between gigs.  The paradigm isn’t ideal, but it’s the best we have for now, so you might as well get used to the idea that you’re going to be playing this game and then, and enlist their help to play it well.

Recruiters are really just sales people, and the relationship between developers and sales people is generally a somewhat reluctant ones.  We’re makers that want to build things so well crafted that adoption is a no-brainer and requires no selling.  Sales people are relationship-oriented and deal mainly in people.  Within organizations, these groups often have natural friction, so the friction only increases when the software people are the product being sold.  But if you can get past the intense weirdness of this arrangement and work effectively with recruiters, it will only benefit your career.  Work with a lot, find firms that you like and work well with, and remember them for next time you’re on the market.  You won’t regret it.

By

In Defense of Test Setup Methods

This post started out as a response to a comment on this post, but it started to get rather long for that venue, so I’m making it its own post. The comment concerns my habit of pulling instantiation logic for the class under test into a common setup method executed by the test runner prior to each test. Here are the main points that I’m writing this to address:

  • Why do I dislike code duplication in tests?
  • Extracting logic to a common setup method creates performance problems.
  • The indirection in pulling part of the setup out of a test method hurts readability.

Back Story and Explanations

I wrote this post a little under two years ago. It’s germane here because I explain in it my progression from not using the setup method to doing so. For those not explicitly familiar with the concept and perhaps following along with my Chess TDD series, what I’m referring to is a common pattern (or anti-pattern, I suppose, depending on your opinion) in unit testing across many languages and frameworks. Most test runners allow you to specify a unique method that will be called before each test is run and also after each test is run. In the case of my series, using C# and MSTest, the setup happens on a per class basis. Here’s some code to clarify. First, the class under test:

public class Gravity
{
    public decimal GetVelocityAfter(int seconds)
    {
        return 9.8M * seconds;
    }
}

And, now, the plain, “before,” test class:

[TestClass]
public class GravityTest
{
    [TestMethod]
    public void GetVelocityAfter_Returns_Zero_When_Passed_Zero()
    {
        var gravity = new Gravity();

        var velocityAfterZeroSeconds = gravity.GetVelocityAfter(0);

        Assert.AreEqual(0, velocityAfterZeroSeconds);
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_Nine_Point_Eight_After_1_Second()
    {
        var gravity = new Gravity();

        var velocityAfterOneSecond = gravity.GetVelocityAfter(1);

        Assert.AreEqual(9.8M, velocityAfterOneSecond);
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_NinetyEight_After_10_Seconds()
    {
        var gravity = new Gravity();

        var velocityAfterTenSeconds = gravity.GetVelocityAfter(10);

        Assert.AreEqual(98, velocityAfterTenSeconds);
    }       
}

And finally, what MS Test allows me to do:

[TestClass]
public class GravityTest
{
    private Gravity _gravity;

    [TestInitialize]
    public void BeforeEachTest()
    {
        _gravity = new Gravity();
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_Zero_When_Passed_Zero()
    {
        var velocityAfterZeroSeconds = _gravity.GetVelocityAfter(0);

        Assert.AreEqual(0, velocityAfterZeroSeconds);
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_Nine_Point_Eight_After_1_Second()
    {
        var velocityAfterOneSecond = _gravity.GetVelocityAfter(1);

        Assert.AreEqual(9.8M, velocityAfterOneSecond);
    }

    [TestMethod]
    public void GetVelocityAfter_Returns_NinetyEight_After_10_Seconds()
    {
        var velocityAfterTenSeconds = _gravity.GetVelocityAfter(10);

        Assert.AreEqual(98, velocityAfterTenSeconds);
    }       
}

Okay, so what’s going on here? Well, the way that MS Test works is that for each test method, it creates a new instance of the test class and executes the method. So, in the case of our original gravity test class, three instances are created. There is no instance state whatsoever, so this really doesn’t matter, but nonetheless, it’s what happens. In the second version, this actually does matter. Three instances get created, and for each of those instances, the _gravity instance is initialized. The “BeforeEachTest” method, by virtue of its “TestInitialize” attribute, is invoked prior to the test method that will be executed as part of that test.

Conceptually, both pieces of code have the same effect. Three instances are created, three Gravity are instantiated, three invocations of GetVelocityAfter occur, and three asserts are executed. The difference here is that there are three gravity variables of method level scope in the first case, and one instance variable of class scope in the second case.

Okay, so why do I choose the second over the first? Well, as I explained in my old post, I didn’t, initially. For a long, long time, I preferred the first option with no test setup, but I eventually came to prefer the second. I mention this strictly to say that I’ve seen merits of both approaches and that this is actually something to which I’ve given a lot of thought. It’s not to engage the subtle but infuriating logical fallacy in which an opponent in an argument says something like “I used to think like you, but I came to realize I was wrong,” thus in one fell swoop establishing himself as more of an authority and invalidating your position without ever making so much as a single cogent point. And, in the end, it’s really a matter of personal preference.

Why I Don’t Like Duplication

So, before I move on to a bit more rigor with an explanation of how I philosophically approach structuring my unit tests, let me address the first point from the comment about why I don’t like duplication. I think perhaps the most powerful thing I can do is provide an example using this code I already have here. And this example isn’t just a “here’s something annoying that could happen,” but rather the actual reason I eventually got away from the “complete setup and teardown in each test” approach. Let’s say that I like my Gravity class, but what I don’t like is the fact that I’ve hard-coded Earth’s gravity into the GetVelocityAfter method (and, for physics buffs out there, I realize that I should, technically, use the mass of the falling object, gravitational constant, and the distance from center of mass, but that’s the benefit of being a professional programmer and not a physicist — I can fudge it). So, let’s change it to this, instead:

public class Gravity
{
    private Planet _planet;

    public Gravity(Planet planet)
    {
        _planet = planet;
    }

    public decimal GetVelocityAfter(int seconds)
    {
        return _planet.GetGravitationalFactor() * seconds;
    }
}

Now, I have some test refactoring to do. With the first approach, I have six things to do. I have to declare a new Planet instance with Earth’s specifications, and then I have to pass that to the Gravity constructor. And then, I have to do that exact same thing twice more. With the second approach, I declare the new Planet instance and add it to the Gravity constructor once and I’m done. For three tests, no big deal. But how about thirty? Ugh.

I suppose you could do some find and replace magic to make it less of a chore, but that can get surprisingly onerous as well. After all, perhaps you’ve named the instance variable different things in different places. Perhaps you’ve placed the instantiation logic in a different order or interleaving in some of your tests. These things and more can happen, and you have have an error prone chore on your hands in your tests the same way that you do in production code when you have duplicate/copy-paste logic. And, I don’t think you’d find too many people that would stump for duplication in production code as a good thing. I guess by my way of thinking, test code shouldn’t be a second class citizen.

But, again, this is a matter of taste and preference. Here’s an interesting stack overflow question that addresses the tradeoff I’m discussing here. In the accepted answer, spiv says:

Duplicated code is a smell in unit test code just as much as in other code. If you have duplicated code in tests, it makes it harder to refactor the implementation code because you have a disproportionate number of tests to update. Tests should help you refactor with confidence, rather than be a large burden that impedes your work on the code being tested.

If the duplication is in fixture set up, consider making more use of the setUp method or providing more (or more flexible) Creation Methods.

He goes on to stress that readability is important, but he takes a stance more like mine, which is a hard-line one against duplication. The highest voted answer, however, says this:

Readability is more important for tests. If a test fails, you want the problem to be obvious. The developer shouldn’t have to wade through a lot of heavily factored test code to determine exactly what failed. You don’t want your test code to become so complex that you need to write unit-test-tests.

However, eliminating duplication is usually a good thing, as long as it doesn’t obscure anything. Just make sure you don’t go past the point of diminishing returns.

In reading this, it seems that the two answers agree on the idea that readability is important and duplication is sub-optimal, but where they differ is that one seems to lean toward, “avoiding duplication is most important even if readability must suffer” and the other leans toward, “readability is most important, so if the only way to get there is duplication, then so be it.” (I’m not trying to put words in either poster’s mouth — just offering my take on their attitudes)

But I think, “why choose?” I’m of the opinion that if redundancy is aiding in readability then some kind of local maximum has been hit and its time to revisit some broader assumptions or at least some conventions. I mean why would redundant information ever be clearer? At best, I think that redundancy is an instructional device used for emphasis. I mean, think of reading a pamphlet on driving safety. It probably tells you to wear your seatbelt 20 or 30 times. This is to beat you over the head with it — not make it a better read.

So, in the end, my approach is one designed to avoid duplication without sacrificing readability. But, of course, readability is somewhat subjective, so it’s really your decision whether or not I succeed as much as it is mine. But, here’s what I do.

My Test Structure

Let’s amend the Gravity class slightly to have it use an IPlanet interface instead of a Planet and also to barf if passed a null planet (more on that shortly):

public class Gravity
{
    private IPlanet _planet;

    public Gravity(IPlanet planet)
    {
        if(planet == null)
            throw new ArgumentException("planet");

        _planet = planet;
    }

    public decimal GetVelocityAfter(int seconds)
    {
        return _planet.GetGravitationalFactor() * seconds;
    }
}

Let’s then take a look at how I would structure my test class:

[TestClass]
public class GravityTest
{
    private const decimal EarthFactor = 9.8M;
    private IPlanet Planet { get; set; }
    private Gravity Target { get; set; }

    [TestInitialize]
    public void BeforeEachTest()
    {
        Planet = Mock.Create();
        Target = new Gravity(Planet);
    }

    [TestClass]
    public class GetVelocityAfter : GravityTest
    {
        [TestMethod]
        public void Returns_Zero_When_Passed_Zero()
        {
            var velocityAfterZeroSeconds = Target.GetVelocityAfter(0);

            Assert.AreEqual(0, velocityAfterZeroSeconds);
        }

        [TestMethod]
        public void Returns_Nine_Point_Eight_After_1_Second_On_Earth()
        {
            Planet.Arrange(p => p.GetGravitationalFactor()).Returns(EarthFactor);

            var velocityAfterOneSecond = Target.GetVelocityAfter(1);

            Assert.AreEqual(9.8M, velocityAfterOneSecond);
        }

        [TestMethod]
        public void Returns_NinetyEight_After_10_Seconds_On_Earth()
        {
            Planet.Arrange(p => p.GetGravitationalFactor()).Returns(EarthFactor);

            var velocityAfterTenSeconds = Target.GetVelocityAfter(10);

            Assert.AreEqual(98, velocityAfterTenSeconds);
        }
    }
}

Alright, there’s a lot for me to comment on here, so I’ll highlight some things to pay attention to:

  • Instance of class under test is named “Target” to be clear what is being tested at all times.
  • Planet instance is just named “Planet” (rather than “MockPlanet”) because this seems to read better to me.
  • Nested class has name of method being tested (eliminates duplication and brings focus only to what it does).
  • Test initialize method does only the minimum required to create an instance that meets instance preconditions.
  • There’s not much going on in the setup method — just instantiating the class fields that any method can modify.
  • The second two test methods still have some duplication (duplicate setup).

Now that you’ve processed these, let me extrapolate a bit to my general approach to test readability:

  • The class nesting convention helps me keep test names as short as possible while retaining descriptiveness.
  • Only precondition-satisfying logic goes in the initialize method (e.g. instantiating the class under test (CUT) and passing a constructor parameter that won’t crash it)
  • Setting up state in the class under test and arranging the mock objects is left to the test methods in the context of “Given” for those asserts (e.g. in the second test method, the “Given” is “On_Earth” so it’s up to that test method to arrange the mock planet to behave like Earth).
  • I use dependency injection extensively and avoid global state like the plague, so class under test and its depdenencies are all you’ll need and all you’ll see.
  • Once you’re used to the Target/Mocks convention, it’s (in my opinion) as readable, if not more so, than a method variable. As a plus, you can always identify the CUT at a glance in my test code. To a lesser degree, this is true of mocks and constants (in C#, these have Pascal Casing)
  • I suppose (with a sigh) that I’m not quite 100% on the maturity model of eliminating duplication since I don’t currently see a duplication-eliminating alternative to setting up Earth Gravity in two of the test methods. I think it’s not appropriate to pull that into the test initialize since it isn’t universal and adding a method call would just make the duplication more terse and add needless indirection. To be clear, I think I’m failing rather than my methodology is failing — there’s probably a good approach that I simply have not yet figured out. Another important point here is that sometimes the duplication smell is less about how you structure your tests and more about which tests you write. What I mean is… is that “Returns_NineyEight_After_10_Seconds_On_Earth” test even necessary? The duplicate setup and similar outcome is, perhaps, telling me that it’s not… But, I digress.

Addressing the Original Concerns

So, after a meandering tour through my approach to unit testing, I’ll address the second and third original points, having already addressed the question of why I don’t like duplication. Regarding performance, the additional lines of code that are executed with my approach are generally quite minimal and sometimes none (such as a case where there are no constructor-injected dependencies or when every unit test needs a mock). I suspect that if you examined code bases in which I’ve written extensive tests and did a time trial of the test suite my way versus with the instantiation logic inlined into each test, the difference would not be significant. Anecdotally, I have not worked in a code base in a long, long time where test suite execution time was a problem and, even thinking back to code bases where test suite performance was a problem, this was caused by other people writing sketchy unit tests involving file I/O, web service calls, and other no-nos. It’s not to say that you couldn’t shave some time off, but I think the pickings would be pretty lean, at least with my approach of minimal setup overhead.

Regarding readability, as I’ve outlined above, I certainly take steps to address readability. Quite frankly, readability is probably the thing most frequently on my mind when I’m programming. When it comes to test readability, there’s going to be inevitable disagreement according to personal tastes. Is my “Target” and initialization convention more readable than an inline method variable also with the convention of being named “Target”? Wow — eye of the beholder. I think so because I think of the instantiation line as distracting noise. You may not, valuing the clarity of seeing the instantiation right there in the method. Truth is with something like that, what’s readable to you is probably mainly a question of what you’re used to.

But one thing that I think quite strongly about test readability is that it is most heavily tied in with compactness of the test methods. When I pick up a book about TDD or see some kind of “how to” instructional about unit tests, the tests always seem to be about three lines long or so. Arrange, act, assert. Setup, poke, verify (as I said in that old post of mine). Whatever — point is, the pattern is clear. Establish a precondition, run an experiment, measure the outcome. As the setup grows, the test’s readability diminishes very quickly. I try to create designs that are minimal, decoupled, compatible with the Single Responsibility Principle, and intuitive. When I do this, test methods tend to remain compact. Eliminating the instantiation line from every test method, to me, is another way of ruthlessly throttling the non-essential logic inside those test methods, so that what’s actually being tested holds center stage.

So, in the end, I don’t know that I’ve made a persuasive case — that’s also “eye of the beholder.” But I do feel as though I’ve done a relatively thorough job of explaining my rationale. And, my mind is always open to being changed. There was a time when I had no test setup method at all, so it’s not like it would be unfamiliar ground to return there.

By the way, if you liked this post and you're new here, check out this page as a good place to start for more content that you might enjoy.

By

Walk a Mile in Their Shoes

It’s easy enough to look back and chuckle at your own foolishness in your younger days, but sometimes I have the weird, sadistic (masochistic?) thought that I’d like to rip a little hole in space-time so that I could get my money’s worth. I’d go back and actually belly laugh and point at 12 or 13 year old Erik. Then I’d settle down and tell me to trust me because we’d be better off for it in the long run, lest you think that I’m cruel.

But I Have So Much To Offer!

What’s so funny? I have this memory of being convinced that some girl or another couldn’t possibly help but be interested in me if only she could see me how good I was at knocking aluminum cans over from 6 or 7 feet away with a bull whip. You tell me that isn’t funny — I think it’d be like laughing at Ralphie after shooting his glasses with his Red Ryder BB Gun.

ChristmasStory

So the back story was that my father, at some point, had gone to Australia or some far off land on business and brought back an Indiana Jones-style bull whip as a souvenir. Over the course of my childhood I became quite accurate with this thing, able to hit small targets and take impressive chunks out of them when I did. In my early teenage years, at the crossroads between wanting to be Indiana Jones and wanting to find young women to take on dates, this odd juxtaposition took place. As kids, we sat in school all day, confined to relatively run-of-the-mill social interactions and activities, and the lone hope you might have for standing out in such an environment was to create some sort of ruckus by misbehaving. There was no chance for anyone, least of all girls that I wanted to impress, to see the unique and clearly very appealing set of skills that I had, such as knocking over cans with a bull whip.

One of the iconic things that you hear children utter, at least in movies of the “16 Candles” genre, is “s/he doesn’t even know I exist.” That wasn’t my problem; I went to a small enough junior high school that pretty much everyone in the grade was aware of one another. My problem was that people knew I existed but didn’t particularly care. But it was a problem that could be solved if I could just devise some way that the entire school was threatened and only someone who was pretty accurate with a bull whip could save it. Or something.

I Can Guess What Interests You

I wised up. Certainly not all at once, and I make no claim to have figured out, even at the age of 34, a foolproof plan to make someone sympathetic to my cause. But I did learn that no girl in my junior high would be interested in watching me shred cans with a bull whip unless she were already interested in me for some other reason. I kind of had to wise up, earlier than some and later than others, or else I would have been the socially stunted Napolean Dynamite character who, at the age or 17 or 18, thinks that girls liked guys with “Bo skills, nun-chuck skills…”

There’s a spectrum of ages at which people come to understand this social lesson. And, I’m not talking about figuring out what attracts girlfriends or boyfriends at an age when bodies and minds are changing on a weekly basis, but rather I’m talking about the lesson of recognizing alien approaches to and outlooks on life. Children have a simple and rather solipsistic view of the world, even as they tend to have a high amount of empathy. The child will be genuinely flummoxed that you could enjoy the taste of brussel sprouts when he cannot, but is also liable to start crying if you start crying. In a way, this empathy is part of the simplicity — all for one and one for all, with the all and the one being external clones of the child.

But at some point, I figured out that me thinking it was cool to whip cans did not cause the various girl-crush of the week to agree with me. I learned that she did not empathize. Together as aging children, in fits and starts, we shed both our empathy and our belief in our opinions and values being shared by all. Budding psychopaths probably get there quicker than others. After all, they never had any empathy to start with and glib social chameleons tend to be the best at manipulating social situations to get reactions that they want. A psychopath would be entirely too busy running a series of social experiments to have private emo moments and thoughts of, “if she only knew how awesome I was.” Psychopath would think, “tricking her into thinking I’m awesome will be fun.”

I mention this because it’s not really matter of “EQ,” exactly, to adapt to the alien outlooks of others — it’s pretty much a feedback loop with the slowest to adapt being among the more introverted and leery of spending social capital on potentially doomed experiments. And so it went, and so it went. I learned, slowly but profoundly, that a lot of people wouldn’t be impressed with me, wouldn’t value what I valued, wouldn’t necessarily approve of me, and perhaps flat out wouldn’t like me. It wouldn’t necessarily be any fault of my own — it could be a matter of circumstance or misunderstanding.

What I learned from this, particularly as an introverted sort, was to spend a lot of time trying on masks of other people’s outlooks on life. Please don’t confuse this with empathy — I’m not particularly empathetic. I just got good over the years at putting myself in the shoes of others to understand their motivations and predict their behavior.

You Have Nothing that I want

In case it wasn’t entirely apparent, I’ve drifted away from talking about love interests and am just talking about life interactions. That is, I didn’t go to singles nights and try some kind of Sherlock Holmes shtick to deduce what would endear me to women. But I did carry my bullwhip and its valuable life lesson with me to adult social interactions, jobs, engagements, etc.

Why does Steve in accounting give me dirty looks whenever I pass by? I’ve never done anything to him. Well, rather than just chalk it up to Steve being a scumbag, maybe I do a bit of listening and a thought exercise. Maybe I learn that one of Steve’s big initiatives had been pushing to have the software group write a series of extensions onto Quick Books that could, ideally, be parlayed into a side business venture for the company and thus into impressive resume fodder for himself. Maybe I also learn that this initiative had died on the vine when they brought me in to overhaul the company’s software practices and that, as a result, Steve’s stock had dipped some with the company. Maybe I also learn that Steve is sort of paranoid, so he perceives this mild dip as an existential threat to his livelihood. So maybe, I am a threat to Steve earning a living. This makes no sense to me, and it would probably make no sense to most people, but none of us is Steve.

I was a pretty weird kid with pretty weird interests, so the profound lesson that I learned had a lot of reinforcement. It was unusual for others to share my outlook, and this gave me a whole lot of practice figuring out theirs for the sake of relatability. When I was younger, this skill was needed for me to form friendships and romantic relationships, but having squared those things away and as an increasingly reclusive adult, it no longer helps me attain things that I want; it helps me maneuver deftly through professional situations. I don’t want anything from people, except, by and large, pleasant professional collaboration. I’m a maker and builder and I’m comfortable with the square I’ve carved out for myself, so my days of using the skill of walking miles in others’ shoes to get things are long past. I just want peace.

So what to do about Steve? Well, the natural thing to do would be to approach him and ask him if, given his expertise, he might have some ideas for software initiatives and that I was thinking of asking some higher-ups if we could give him more of a challenge, given how marketable he is. He most likely wouldn’t assume that I’ve quietly assimilated information and made an effort to understand what life is like looking out from Steve’s brain. He’ll no doubt be distrustful and skeptical, but he’ll also probably start to adopt a different attitude toward me, if subtly. And what does any of this cost me, whether or not I follow through with any of it? Nothing, really.

I’ve come full circle. Steve is out whipping cans and feeling spiteful toward anyone who doesn’t agree with him that this is a wonderful skill. I think his skill is silly and I’d laugh at him for this privately, the way I laugh at 13 year old Erik, but I don’t want his spite. So I’ll watch him do his thing stoically and then offer some praise when he’s done.

What’s the lesson in all this? Why am I posting about it? Why did I spent so much time on narrative and so little time relating it to your life? Well, the point is pretty simple. When you have conflicts with people in a work environment — when you distrust, dislike, or even despise a colleague — fight the urge to categorize others as adversaries or enemies. Almost without exception their behavior, however capricious, childish or cruel it may seem to you, will make some kind of sense if you really get inside their head and understand how they look at the world. It may even be that you have to preface this to yourself, “if I were a petty, sadistic person…” So be it. However alien, you need to understand it. And I say this not to heal the world or advocate that you seek understanding and turn the other cheek, but to counsel you toward simple pragmatism. If you understand those around you, then you’ll understand what it is they want, and how you can steer interactions with them toward favorable outcomes.

So, take a few deep breaths and try to understand what makes those around you tick. It’s not the empathetic thing to do, but rather the practical thing to do.