Engineers, Hours, Perks, and Pride

This started as a Google+ post about an article on getting top engineering talent and got way too long, so I’m posting here instead.

I wholeheartedly agree that 18-hour days are just not sustainable. It might work for a brand-new startup cranking out an initial release, understaffed and desperate to be first to market. But, at that stage, you can expect the kind of passion and dedication from a small team to put in those hours and give up their lives to build something new.

Once you’ve built it, though, the hours become an issue, and the playpen becomes a nuisance. You can’t expect people to work 18-hour days forever, or even 12-hour days. People far smarter than I have posited that the most productive time an intellectual worker can put in on a regular basis is 4 to 6 hours per day; after that, productivity and effectiveness plummet, and it only gets worse the longer it goes on.

Foosball isn’t a magical sigil protecting engineers from burn-out. Paintball with your coworkers isn’t a substitute for drinks with your friends or a night in with your family. An in-house chef sounds great on paper, until you realize that the only reason they’d need to provide breakfast and dinner is if you’re expected to be there basically every waking moment of your day.

Burn-out isn’t the only concern, either. Engineering is both an art and a science, and like any art, it requires inspiration. Inspiration, in turn, requires experience. The same experience, day-in, day-out – interacting with the same people, in the same place, doing the same things – leaves one’s mind stale, devoid of inspiration. Developers get tunnel-vision, and stop bringing new ideas to the table, because they have no source for them. Thinking outside the box isn’t possible if you haven’t been outside the box in months.

Give your people free coffee. Give them lunch. Give them great benefits. Pay them well. Treat them with dignity and respect. Let them go home and have lives. Let them get the most out of their day, both at work and at home. You’ll keep people longer, and those people will be more productive while they’re there. And you’ll attract more mature engineers, who are more likely to stick around rather than hopping to the next hip startup as soon as the mood strikes them.

There’s a certain pride in being up until sunrise cranking out code. There’s a certain macho attitude, a one-upmanship, a competition to see who worked the longest and got the least sleep and still came back the next morning. I worked from 8am until 4am yesterday, and I’m here, see how tough I am? It’s the geek’s equivalent to fitness nuts talking about their morning 10-mile run. The human ego balloons when given the opportunity to endure self-inflicted tortures.

But I’m inclined to prefer an engineer who takes pride in the output, not the struggle to achieve it. I want someone who is stoked that they achieved so much progress, and still left the office at four in the afternoon. Are they slackers, compared to the guy who stayed another twelve hours, glued to his desk? Not if the output is there. It’s the product that matters, and if the product is good, and gets done in time, then I’d rather have the engineer that can get it done without killing themselves in the process.

“I did this really cool thing! I had to work late into the night, but caffeine is all I need to keep me going. I kept having to put in hacks and work-arounds, but the important thing is that it’s done and it works. I’m a coding GOD!” Your typical young, proud engineer. They’re proud of the battle, not the victory; they’re proud of how difficult it was.

“I did this really cool thing! Because I had set myself up well with past code, it was a breeze. I was amazed how little time it took. I’m a coding GOD!” That’s my kind of developer. That’s pride I can agree with. They’re proud because of how easy it was.

This might sound like an unfair comparison at first, but think about it. When you’re on a 20-hour coding bender, you aren’t writing your best code. You’re frantically trying to write working code, because you’re trying to get it done as fast as you can. Every cut corner, every hack, every workaround makes the next task take that much longer. Long hours breed technical debt, and technical debt slows development, and slow development demands longer hours. It’s a vicious cycle that can be extremely difficult to escape, especially once it’s been institutionalized and turned into a badge of honor.

My Personal Project Workflow/Toolset

I do a lot of side projects, and my personal workflow and tooling is something that’s constantly evolving. Right now, it looks something like this:

  • Prognosticator for tracking features/improvements, measuring the iceberg, and tracking progress
  • WorkFlowy for tracking non-development tasks (the most recent addition to the toolset)
  • Trac for project documentation, and theoretically for defect tracking, though I’ve not been good about entering defects in Trac recently; it doesn’t seem worth the effort on a one-person project, though with multiple people I think it would be a must
  • Trello for cross-cutting all the above and indicating what’s next/in progress/recently completed, and for quickly jotting down ideas/defects. Most of the defect tracking actually goes in here on one-man projects right now. This is a lot of duplication and the main source of waste in my current process.
  • Bitbucket for source control (I also use Atlassian’s excellent SourceTree as a Git/Hg client.)
It’s been working well for me, the only issue I have is duplication between the tools, and failing to consistently use Trac for defect tracking. What keeps me in Trello is how quick and easy it is to add items to it, and the fact that I’m using it as a catch-all – I can put a defect or an idea or a task into it in a couple of seconds; I just have to replicate it to the appropriate place later, which is the problem.
I think the issue boils down to being torn between having a centralized repository for “stuff to be done” (Trello) and having dedicated repositories catered to each type of thing to be done (Prognosticator, Trac, and WorkFlowy); and convenience. Trello is excellent for jotting something down quickly, but lacks the additional specific utility of the other tools for specific purposes.
I think what I’ll end up doing is creating a “whiteboard” list in WorkFlowy, and using that instead of Trello to jot down quick notes when I don’t have the time to use the individual tools; then I can copy from there to the other tools when I need to. That will allow me to cut Trello down to basically being a Kanban board.

Behold, My Newest Creation!

I’m entirely too proud too announce my latest creation, Rogue Prognosticator. This is a web-based application for doing project estimation and schedule for software development. I’ve written about these topics before, and rest assured I will again; you can count on the concepts you see discussed here being taken into account in the software.

Right now the site is in open beta, free for public use. As features are added, some may be subscriber-only, or may start out being subscriber-only.

This project breaks a lot of new ground for me, and I’ve learned a lot already.

  • It’s my first project from scratch using ASP.NET MVC or Entity Framework.
  • It’s my first personal project in production using C# or .NET.
  • It’s the first time I’ve used Windows Azure.
  • It’s the first time I’ve used UserVoice.
  • It’s the first time I’ve used continuous deployment from Git on a personal project in production.
  • It’s the first time I’ve used SQL Server on a personal project in production.
  • It’s the first time I’ve used WordPress in production.
This project was, as you may have guessed, the source for my post on entity framework model queries, as well as my post on value-based prioritization.
I’ve been using the project as I’ve been building it, and it’s already been an excellent tool for me. Prioritizing features by estimated return was a particularly enlightening experience; it really helped me to get an objective look at the near-term plan and organize development more effectively.
I’ll still talk here about the nitty-gritty of development but official product announcements will be coming through the product blog, Rogue Prognostications. I hope that others will find this project as useful as I have. Please feel free to drop any comments, questions, suggestions, or other feedback on the Rogue UserVoice.
More to come – watch this space!

Simple Entity Framework Model Structure

I’ll say right up front, I don’t have a lot of experience with Entity Framework, and this could either be a well-known solution or a completely foolish one. All I know is that, so far, it has worked extremely well for my purposes.

Coming from the Java world, I’m used to using DAO’s to serve as an abstraction layer between the controllers and the database, with the basic CRUD methods, plus additional methods for any specific queries needed for a given entity type.

Conveniently, entity framework provides a fairly complete DAO in the form of DbSet. DbSet is very easy to work with, and provides full CRUD functionality, and acts as a proxy for more complex queries. I wanted to keep queries out of my logic, however, and in the model.

Looking at it, I didn’t want to have to write an entire wrapper for DbSet, and subclassing it seemed like asking for trouble. That’s when it occurred to me to use extension methods for queries. It turns out you can define extension types against a generic type with a type argument specified (e.g. this IEnumerable). This not only allowed me to abstract out the queries and keep them in the model, without having to wrap or subclass anything; but by defining the extensions on IEnumerable instead of DbSet, I have access to my queries on any collection of the appropriate entity type, not just DbSet. I can then chain my custom queries in a very intuitive and fluid way, keeping all of the code clean, simple, and separate.

For example, I have a table of tags. I’ve created extension methods on IEnumerable to filter to tags used by a given user, and to filter by tags starting with a given string. I can chain these to get tags used by a given user and starting with a given string. I can also use these queries on the list of tags associated with another entity, as IList implements IEnumerable, and thus inherits my query extension methods.

I don’t know if this is the best way – or even a good way – but it’s worked for me so far. I do see some possible shortcomings; mainly, the extensions don’t have access to the context, so they can’t query any other DbSets, only the collection it’s called against. This means that only explicit relationships can be queried against, which hasn’t been a roadblock so far in my (admittedly simple) application. I’m not sure this is really a drawback though – you can still add a parameter to pass in an IEnumerable to query against, which again offers the flexibility to pass a DbSet or anything else.

Pragmatic Prioritization

The typical release scheduling process works something like this:

  1. Stakeholders build a backlog of features they’d like to see in the product eventually.
  2. The stakeholders decide among themselves the relative priority of the features in the backlog.
  3. The development team estimates the development time for each feature.
  4. The stakeholders set a target feature list and ship date based on the priorities and estimates.
The problem here is primarily in step 2; this step tends to involve a lot of discussion bordering on arguing bordering on in-fighting. Priorities are set at best based on a sense of relative importance, at worst based on emotional attachment. Business value is a vague and nebulous consideration at most.
I propose a new way of looking at feature priorities:

  1. Stakeholders build a backlog of features they’d like to see in the product eventually.
  2. The stakeholders estimate the business value of each feature in the backlog.
  3. The development team estimates the development time for each feature.
  4. The stakeholders set a target feature list and ship date based on the projected return of each feature – i.e., the estimated business value divided by the estimated development time.
This turns a subjective assessment of relative priorities into an objective estimate of business value, which is used to determine a projected return on investment for each feature. This can then be used to objectively prioritize features and schedule releases.
I’ve been using this workflow recently for one of my upcoming projects, and I feel like it’s helped me to more objectively determine feature priorities, and takes a lot of the fuzziness and hand-waving out of the equation.

Shameless self-promotion: Pragmatic prioritization is a feature of my project scheduling and estimation tool, Rogue Prognosticator

JComboBox with Custom ComboBoxModel Not Updating Value on setSelectedItem()

I wrestled with this issue for some time before figuring out the cause, so I hope this helps someone out there. I had a JComboBox with a custom ComboBoxModel. Everything was working fine, except a call to setSelectedItem would do everything it should (fire events, update the selected item property) except it wasn’t updating the displayed value in the JComboBox itself. Clicking the drop-down would even show the correct item selected, and getSelectedItem() returned the correct result; it was just the box itself that was wrong.

Apparently the displayed value in the JComboBox isn’t based on getSelectedItem(), but rather on the top item in the list. I don’t know how or why this is, or if it’s due to some intricacies of my GUI code, but bringing the selected item to the top of the ComboBoxModel‘s item list when calling setSelectedItem fixed the issue. Go figure.

If anyone has any insight into what causes this, please drop a comment!

Qaudropus Rampage

I’ve taken up the excellent indie mobile title (and product of the 7-day roguelike challenge) Quadropus Rampage. It’s an all-around excellent title, with some hilarious content, solid gameplay, and excellent replayability. It’s free to play, with in-app purchases, and one of few cases where I’ve made an IAP in order to support the developers.

I haven’t been playing long, and I haven’t beaten it, but I thought I’d toss out a few tips, tricks, and strategies I’ve learned along the way.

Mechanics:

  • Attack has longer range than you think, and different weapons have different ranges.
  • Hold down attack to get a spin attack, that damages all enemies around you. You’ll end up turned about 60 degrees counter-clockwise from the direction you were facing when you started the spin. 
  • Note that the spin attack deals less damage than your normal attack. Note also that you still get the normal attack triggered by pressing the attack button, in order to charge up the attack. This means you can strike, holding down the button, then release, to get a quick one-two combo. Practice the timing of holding down the attack button, it can make a huge difference in crowded maps.
  • Smash attack does a ton of damage in a radius similar to the spin attack (farther with upgrades & masteries), as well as knocking enemies back (and possibly off ledges.)
  • Dodge lets you move over empty spaces and even off the edges of the map. You can hold down the dodge button to continue flying around the map until you release it.
  • Bubble gives you a temporary shield that blocks all damage until it expires.
  • Bingo flings himself toward a random nearby enemy every few seconds. If there are enemies grouped together, or in a line, he will damage every enemy he passes through. He does a lot of damage, and can crit.
  • The Rage meter (top of the screen) fills up as you deal damage to enemies, and rapidly depletes over time. If it gets to full, you enter a Rampage, dealing bonus damage and taking reduced damage from enemies. In order to enter a rampage, you’ll have to continuously dish out damage long enough to fill the meter before it starts to fall. This gets easier with more upgrades, and at lower depths (when there are more enemies to work with.)
Techniques:
  • Most levels I start by dodging into the middle of the map, trying to lure as many enemies as possible into a central area, then I smash attack to take out as many as I can at once, and knock the rest away from me to get some breathing room.
  • Dodging toward an enemy and then attacking is an excellent way to deal damage without taking any yourself. You can dodge in, attack, and dodge back out if the attack isn’t enough to kill.
  • Against large enemies, you can always run up, bubble, and hack away at them continuously until the bubble expires, then dodge away.
  • Heartfish move pretty slowly, but they do follow you. If you’re in trouble, dodge toward them to grab them, or bubble then dodge so you can grab them without dying on the way. If you’re at or near full health, dodge away from them toward your enemies, to avoid picking them up until you actually need them.
  • The most important weapon stats are health and damage; everything else is nice, but not nearly as important. Weapon size also plays a part, but generally speaking, just look for weapons where the top two stats (damage and health) are green (better than what you have now.) Learn to swap weapons quickly in the midst of a melee when you find  a better weapon.
  • Depth charges are excellent tools, but can be difficult to use properly. They always appear at the edges/corners of the map, so often the best technique is to dodge off the edge of the map, come at the depth charge from the far side, then smack it toward your enemies. The same basic techniques for the depth charges apply to Bingo’s ball as well.
  • If you smash attack off the edge or through a hole, you’ll land in the next depth with a smash attack. If you have the mastery upgrade that refreshes your smash attack cooldown on each depth, you’ll land with a smash attack and no cooldown. This makes it a viable strategy, if you end a level with full health and full smash, to smash off the edge of the map, destroy what you can when you land, dodge off toward another group of enemies, and smash attack again. At later depths, this is almost certain to trigger a rampage, letting you clean up the level in no time.

Upgrades:

  • Strength, Vitality, and Smash are the most important skills; invest in these first. I did it round-robin in that order (Strength 1, Vitality 1, Smash 1, Strength 2, etc.) and it worked well for me.
  • Next most important are probably Bingo and Bubble, in that order.
  • Rampage isn’t the least important, however, it doesn’t really come into play until the lower depths, and until you’ve got the other skills levelled up enough.
  • Keep in mind what upgrade you want next and how much it costs; you can pause mid-game and buy the upgrade as soon as you can afford it. You aren’t limited to purchasing upgrades between games.
Masteries:
  • Masteries are a combination of upgrade and achievement. When you hit a certain goal, the mastery will be unlocked, and you’ll get the option of two upgrades for each mastery, which you can switch between at any time (including mid-game).
  • Any time you get an achievement while playing, it’s a good idea to pause, go into the character screen, and choose an upgrade for that mastery, to gain the bonus as soon as possible (neither option is selected by default, you must select one yourself to gain any benefit.)
  • Keep in mind that you can switch mastery bonuses mid-game as well if you need to. I’ve not run into a situation where this would be needed.
  • Many of the masteries will happen when they happen, but most can be achieved with considered action. I strongly recommend picking a mastery and focusing on it during your gameplay; for example, focus on using your smash attack as often as possible until you get that mastery, or focus on dodging over and over and over until you get that mastery, and so on.
  • None of the mastery bonuses are game-changing, but many are very good, and the combination of a few of them, plus some upgrades, quickly make the first few depths a cakewalk.
Pets:
  • You can have two pets active at a time, not including Bingo. Bingo is always active, and does not count as a pet. Likewise, the Bingo upgrades don’t affect your other pets.
  • I’ve only used Cy and Saww, but both have been very effective for me, though I’m considering swapping Cy for Smiles.
  • It doesn’t seem like there’s a significant imbalance between them, I think it’s mainly a matter of personal preference and play style.
Artifacts/Grubby:
  • Don’t bother purchasing anything from Grubby until you’ve maxed out all the upgrades. Your orbs are better spent there. You’re very unlikely to beat the game without maxed upgrades, no matter how many fancy items you pick up from Grubby.
  • Many of the artifacts just give a 20% increase to damage to a particular type of enemy. These are nice, but not worth paying orbs for to buy them from Grubby.
  • The best artifacts, in my experience, are Heartfish Food, Fountain Pen, Bingarang, Forn Orb, Third Eye, Bermuda Triangle, Bingo Unchained, Spiked Collar, Star Biscuit, Embiggener, Urchin Spines, Gorgo’s Shovel, and particularly Lucky Coin (free resurrection!).
  • Don’t waste your orbs on buying weapons from Grubby unless a) it’s ridiculously better than anything you’ve seen at your current depth, and/or b) you’re within two depths of facing off against Pete. The rest of the time, it’s just not worthwhile unless you have so many orbs you don’t care any more.

Purchases:
  • You can purchase orbs (for buying upgrades and buying items from Grubby in game) and dubloons (for buying pets and resurrections) in the in-app store. These are relatively cheap compared to most games with similar freemium models.
  • Any purchase will earn you a new starting weapon that’s significantly better than the starting tennis racket; in fact, if you make a purchase, your new starting weapon will last you the first several depths easily.
  • Don’t waste your dubloons on unlocking masteries; they generally aren’t worth what they cost in dubloons, especially since you can earn them through playing anyway.
Synergies: some things just work particularly well in combination. For example:
  • All Dodge upgrades, Saww, Flurry upgrade from Quick mastery, Inksplosion upgrade from Nimble mastery, and Fountain Pen: dodge to kill. You cause an explosion (dealing damage and causing knockback) when you start a dodge, you get bonus damage when you end a dodge, and both you and your pet deal damage during a dodge.
  • All Rampage upgrades, either upgrade from the Brawler mastery, Supple Crits upgrade from the Hulk mastery, Bingarang, Forn Orb, Eye Patch, and Third Eye: ultimate rampage. You shoot lasers out of your face. Bingo shoots lasers out of his face. He does this while spinning continuously around the map until the rampage ends. And you rampage more often.What’s not to love? If you take Pain Tolerance from Brawler, and have some or all of the above dodge stuff, you can indiscriminately fly around the map lasering everything in sight while taking reduced damage. Alternatively, take the I’m Always Angry upgrade to rampage more often.
  • Saww, Smiles, Bingarang, Forn Orb, Bingo Unchained, Spiked Collar, Star Biscuit, and Urchin Spines: let the pets do the work. Park yourself in an urchin for safety, dodging briefly to keep Saww going.

Assumptions and Unit Tests

I’ve written previously on assumptions and how they affect software development. Taking this as a foundation, the value proposition of unit testing becomes much more apparent: it offers a subjective reassurance that certain assumptions are valid. By mechanically testing components for correctness, you’re allowing yourself the freedom to safely assume that code which passes its tests is highly unlikely to be the cause of an issue, so long as there is a test in place for the behavior you’re using.

This can be a double-edged sword: it’s important to remember that a passing test is not a guarantee. Tests are written by developers, and developers are fallible. Test cases may not exercise the behavior in precisely the same way as the code you’re troubleshooting. Test cases may even be missing for the particular scenario you’re operating under.
By offering a solid foundation of trustworthy assumptions, along with empirical proof as to their validity, you can eliminate many possible points of failure while troubleshooting, allowing you to focus on what remains. You must still take steps to verify that you do have test coverage for the situation you’re looking at, in order to have confidence in the test results. If you find missing coverage, you can add a test to fill the gap; this will either pass, eliminating another possible point of failure, or it will fail, indicating a probable source of the issue.
Just don’t take unit test results as gospel; tests must be maintained just like any other code, and just like any other code, they’re capable of containing errors and oversights. Trust the results, but not the tests, and learn the difference between the two: results will reliably tell you whether the test you’ve written passed or failed. It is the test, however, that executes the code and judges passing or failing. The execution may not cover everything you need, and the judgement may be incorrect, or not checking all factors of the result.

Feature Disparity Between Web, Mobile, and Desktop

I understand that mobile is new territory, and that web applications have certain restrictions on them (though less and less so with modern standards and modern browsers), but it seems very strange to me that there are still such glaring disparities between the web, mobile, and desktop versions of some products – even products designed with mobile in mind.

Take Evernote as an example. It’s been out for Android for ages, with regular new releases offering new features and functionality. Yet there are still basic features that are not available in the mobile client, including strike-through text, horizontal rules, alignment, and font face/size changes. If you have a note with these features, and you edit the note in the Android app, you get a friendly warning that the note contains unsupported features, and the editor forces you to edit paragraph-by-paragraph, like the old and irritating Google Docs app for Android. I find this more than a little bit ridiculous; why are you adding new, nice-to-have features when basic functionality is still unsupported?

Look at Google Keep for the opposite example. The mobile app allows reordering the items in a checklist with drag-and-drop. The web app doesn’t allow you to reorder items. The only way to reorder items is using cut and paste. This is something you can absolutely achieve in a web app, and they’ve done it before, but for some reason that one, basic, important feature is just somehow missing.

The Mint mobile app allows changing budgets, but not changing whether or not the budget surplus/deficit should roll over month-to-month, which you can do in the web app. It’s most of the feature, just missing one little part that can cause frustration because if most of the feature is there, you expect the whole feature to be there.

The GitHub web app doesn’t even include a git client – the closest you can get is downloading a repo, but you can’t actually check out and manage a working copy.

The Google Maps app for Android doesn’t allow editing your “My Maps”, or to choose from (or create) alternate routes when getting directions. It also doesn’t include the web version’s traffic forecasting. The Blogger web app is next to useless; editing a note created on the desktop gives you a WYSIWYG editor with the plain text littered with markup, and writing a post on mobile and then looking at it on desktop shows that there’s some serious inconsistencies with handling of basic formatting elements like paragraphs. Don’t even get me started on the useless bundle of bytes that is the Google Analytics Android app; it’s such a pathetic shadow of the web application that there’s no point in even having it installed.

These seem to me like cases of failure to eat your own dog food. If there were employees – especially developers or product managers – of these companies, using these applications on each supported platform, these issues would have been solved. They’re the sorts of things that look small and insignificant on a backlog until they affect you on a day-to-day basis; those little annoyances, repeated often enough, become sources of frustration.

Teaching a Developer to Fish

I write a lot about development philosophy here, and very little about technique. There are reasons for this, and I’d like to explain.

In my experience, often what separates an easy problem from an intractable one is method and mindset. How you approach a problem tends to be more important than the implementation you end up devising to solve it.

Let’s say you’re given the task of designing a recommendation engine – people like you were interested in X, Y, and Z. Clearly this is an algorithmic problem, and a relatively difficult one at that. How do you solve it? 

The algorithm itself isn’t significant; as a developer, the algorithm is your output. The process you use to achieve the desired output is what determines how successful you’ll be. I could talk about an algorithm I wrote, but that’s giving a man a fish. I’d much rather teach a man to fish.

So how do you fish, as it were, for the perfect algorithm? You follow solid practices, you iterate, and you measure. That means you start with a couple of prototypes, you measure the results, you whittle down the candidate solutions until you have a best candidate, and then you refine it until it’s as good as it can get. Then you deploy it to production, you continue to measure, and you continue to refine it. If you code well, you can A/B test multiple potential algorithms, in production, and compare the results.

How do you fish for a fix to a defect? You follow solid practices, you iterate, and you measure. You start by visual inspection, checking for code quality, and doing light refactoring to try to simplify the code and eliminate points of failure, to narrow down the possibilities. Often this alone will bring the root cause of the defect to the surface quickly, or even solve it outright. If it doesn’t, you add logging, and you watch the results as you recreate the error, trying to recreate it in different ways, to assess the boundaries of the defect; if this is for an edge case, what exactly defines the “edge” that’s affected? What happens during each step of execution when it happens? Which code is executing and which code isn’t? What parameters are being passed around?

In my experience, logging tends to be a far more effective debugging tool than a step-wise debugger in most cases, and with a strong logging framework, you can leave your logging statements in place with negligible performance impact in production (with debug logging disabled), and with fine-grained controls to allow you to turn up verbosity for the code you’re inspecting without turning all logging on and destroying the signal-to-noise ratio of your logging output.

You follow solid practices, you iterate, and you measure. If you use right process, with the right mindset, you’ll wind up at the right solution.

That’s why I tend to wax philosophical instead of writing about concrete solutions I’ve implemented. Chances are I wrote the solution to my problem, not your problem; and besides, I’d much rather teach a man to fish than give a man a fish.