2013-10-18

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

2013-09-17

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!

2013-09-10

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.

2013-08-04

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.

2013-07-04

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.