Reduced Cost BOP Gear Crafting FTW

30 July 2008

I’m going to make an effort to start refining and posting some of my WOW forum rants here on my blog. This first is an idea I’ve been tossing around for a few weeks and just recently found a forum post to pose it in.

I’ve been frustrated with gear-crafting professions in general. They aren’t worth training until late-game because they consume too many resources better put towards leveling. Even in the late-game they’re of questionable use except as cooldown-based money generators.

In Burning Crusade, Blizzard attempted to fix this by creating a few sets of gear that require a certain tailoring level or spec to be able to wear. This has been effective, as these sets are some of the best and easiest to obtain gear for new lvl 70s.

When I hit 70 and had plenty of gold to spare, I leveled my tailoring to full (375) and started looking for gear. It turned out that all of the good recipes were rare drops from difficult dungeons. But then the items were Bind on Equip (BOE), so anyone could use the items once created. Despite having 375 tailoring, I found myself having other tailors make me the cloth gear I was interested in. In addition, there are some Bind on Pickup (BOP) recipes, which are equally questionable. If only you can wear the item the recipe creates, then a BOP recipe drop is effectively a gear drop that you also have to pay for (by purchasing materials).

/facepalm

Alchemists are now getting a bonus effect when using potions that they can create. Here is my idea for a similar effect on gear-crafting: give tailors a discount on materials required for a BOP version of all recipes. This would be a separate button on the tailoring interface – a “make for self” tab that shows the reduced costs. I’m thinking 50% of BOE cost, but that may need to be tweaked upwards a bit. Disenchanting of these items would apply the same multiplier.

This route to fixing gear-based crafting has a lot of benefits. First of all, it’s extremely cheap from a development perspective. Using multipliers on existing recipes avoids any issues where someone would need to modify and test every existing recipe. It would also simplify creation of new recipes. The designers are presently forced to create custom tailoring-specific recipes for every class, that are only usable by tailors. This is a lot of extra work for items that 1/3rd or less of tailors would have a chance to use. Tailors and classes that wear cloth are already very limited subsets of the population, so this isn’t development time well-spent.

With this change, all recipes would be created as BOE and be available to all players who wear that type of gear. But at 50% reduced cost, tailoring would be a profession well-worth grabbing. Likewise, grinding for a BOE recipe would become worthwhile. Instead of comparing the grind time to how much time you would spend in trade chat trying to find a tailor with the recipe, you would be comparing the grind time to the amount of time required to farm for an extra 5 Primal Might and 3 Spellcloth. This would tilt the scales back towards people making the effort to obtain recipes.

Likewise, gear-crafting might become a cost-effective method of upgrading gear during leveling. The BOP versions of gear would reduce the cost of skillups, albeit at a slight cost of reducing the amount of select “cheapest” crafted gear appearing on the auction house. Personally, this would be a welcome change from speccing herbalism/skinning on every character I level.

I’ve referred to tailoring a lot here, but it applies equally to blacksmithing and leatherworking. For the low cost of creating a “BOP” tab on the gear-crafting interfaces that divides mats by 2 and toggles the BOE flag to BOP, gear-crafting would receive a much-needed buff. Considering this would also simplify recipes for both the game developers and for players, it seems like it could be a valuable addition to the WotLK expansion.

M.A.G.E.

16 July 2008

Got a kick out of this video rapping about mages in WOW:

Test-first Coding, Unit Tests Not Required

16 July 2008

Some developers don’t need to test their code. They think up a grandiose scheme in their head, program every last line of it, and then commit the code to version control. The code may or may not even be used in the application, but that’s ok. The goal is getting more lines of code saved, right?

All wrong. More code is not “more better” – just the opposite. It’s more important to have simple well-tested code that covers all scenarios that are encountered, than to have piles of “wishful thinking” unused functions and “just in case” error handling.

Here are a few guidelines that can help any developer or project improve in quality:

1. All new code should be tested repeatedly while being written.

This is a code-level equivalent to Agile’s principle of frequent reviews with the client. Everything can be fixed faster if it’s caught sooner. Coding without testing along the way is like trying to paint blindfolded. Sure, you might be able to paint over the screw-ups when you finally take the blind-fold off, but why not do it right the first time?

There are many benefits to testing during coding. By testing as you go, you’re more likely to work on functional, testable features. Who hasn’t seen or coded something where an enormous amount of time was spent on some elaborate framework, only to find in the end that it wasn’t even what the project needed? By starting with testable functionality you force yourself to follow the important mantra of:

Make it work, make it right, make it fast. In that order.

It’s always easier to refactor code to be “right” if it’s already complete and working. If you write perfect, pristine code, that does the wrong thing, it will likely need to be trashed entirely to be able to create working code. Testing as you write guarantees that your code does what the application needs.

2. All new code should be tested and working before being committed to the repository.

This should go without saying, but somehow it does require saying. If code doesn’t work, it absolutely should not be committed. I’m a firm believer in keeping your repository sane throughout development. If you break a page or function and commit it broken, you’re preventing others’ from getting their work done. There’s also a good chance that you’ll leave that code broken due to some distraction, at which point it’s possible the broken code will get launched.

If you get distracted by a more urgent priority, create a second sandbox to work on that from. For a larger refactoring or a big new feature, create a project branch. These tactics allow you to mangle the code in any way imaginable, while still letting your teammates work and launch incremental improvements or bugfixes as necessary.

Even if you only made the tiniest of changes affecting something, test it. More often than not, you’ll be surprised to find some kind of syntax or logic error that would have gone to production because of your carelessness.

In an ideal world QA is going to review the code before launch, but let’s be realistic: Most projects don’t have the time for that. When it comes down to it, it’s your code, and you’re responsible for it. QA has enough to worry about without developers being outright careless.

3. All code should be in use, or be deleted.

Even if you’re pretty certain a function will be needed down the line, don’t do more than creating a stub for it. By implementing code that isn’t used, you’re immediately breaking rules #1 and #2. You can’t test it while you work on it OR when you’re finished with it – it’s not used anywhere! Unit testing sort of gets around these problems, but what’s the point? You’ve now got a unit test AND a function that may or may not match actual functionality that doesn’t exist and may or may never be needed.

Note that this rule doesn’t just apply to new code! If you remove all references to a function, remove the function too. This is every bit as important as not creating unused functions in the first place. Unused code will rapidly become broken or deprecated. Later on, developers will find this function and attempt to use it, with the expectation that it works correctly. In addition, you have an exaggerated codebase of unused functions – so any attempt at refactoring or adding on to the codebase is more difficult than it should be.

These are some of the most important concepts to drill into your junior developers’ heads. I’m grateful to my Comparative Languages teacher at Virginia Tech for getting me started on the right path during college. Combine these concepts with a version control system like Subversion, and you can successfully refactor even the most horrific of codebases. Trust me – I have!

Interfaces, not Objects

15 July 2008

When I was young I used to hate vegetables and Object Oriented Programming. I learned C++ in high school and college, but was turned off by the overly elaborate and useless example projects. Especially in C++, the obtuse syntax and strict typing made OO painful to work with.

I’ve grown a lot since then. I’ve been programming OO for several years, even refactoring a large functional codebase into objects. I also eat vegetables, as long as they’re sauteed, steamed, or cooked with other food. But, like the mushy microwaved carrots my parents used to make, there’s still a lot to hate about Object Orented Programming.

For many programmers OOP amounts to little more than code obfuscation. They go wild imagining the most complicated set of objects possible to solve a problem. You’d think they were handing out prizes for checking off every OO language feature. When the coding is done (if it ever gets done!) you have a mess of spaghetti that’s impossible to read or debug. One function call in your front end might require tracing through 8 different files to figure out what code is actually being executed.

The goal of OOP is not to stuff everything into as many objects as possible, and reimplement the = operator with Getter/Setter functions. Even if that’s what your college professors told you.

A better approach to OOP is coding for interfaces. Figure out the functions and data structures that would make your front-end the easiest to write. Now implement that, and only that. Don’t worry about having a few blocks of code that are moderately similar. First things first, make the code work. You can factor out those similar blocks of code into other objects or functions later if you need to. There’s a good chance that time will never come.

Every object you write before you need it is adding complexity, difficulty, and time to your project. Start with the top-level interfaces and refactor complexity in only as needed to implement Real functionality. If you try to account for every single possible scenario and abstraction it could take you months just to write “Hello World”. I once interviewed someone whose company spent 6 months working on a simple poker game, and still couldn’t get it working. Unfortunately that mindset of perfection (at the cost of results) comes natural to developers, and can be difficult to overcome.


The example that immediately comes to mind is the Active Record pattern. When you start a website, you should have a basic interface where you can transfer your objects to and from the database using straight-forward object.save() and object.get() calls. These calls can be hard-coded for MySQL, and even use hand-typed INSERT, UPDATE, and SELECT statements. It works, things are cool. The project zoomed by because you only implemented the objects and functions you needed.

Uh-oh! Your site was a hit and you’re getting slammed! Now you need to switch to an Oracle back-end with MySQL slaves. Not a problem. Because your interface is sane, you can modify your objects’ save() and get() calls. Change save() to connect to Oracle and trigger cache updates, and change get() to use the MySQL slave DBs. Wow, that was pretty darn easy.

If you end up needing to refactor into a Factory Pattern later on – well, great! That means your site was a success! You’ve found the need to add a great deal of complication to your site, and that’s OK.

But do you really think your site would have made it if you had taken the time to make every object imaginable when you first started the site? Would you have been able to hire developers and gotten anything useful out of them for the first 6 months while they tried to decipher your over-OOPing? The answer to both is ‘probably not’.