Archive for February, 2011

Do or do not

2011/02/25

Assertion is a valuable tool that many languages provide, but recently I have come to think it is used too much and in the wrong places.  I put forward the idea that asserts should not be found anywhere in the main body of your code.  Permanently burying asserts deep inside your code could end up causing more problems than they seek to solve.  Asserts embedded in methods  are useful while debugging, but should rarely be committed to source control.

I extend this thought to other defensive practices like checking for nulls indiscriminately – even where there never should be one.   Sanitization of external data is prudent and necessary, but once things are safely inside your own codebase you have control of the expected range of values and should be able to trust that.

What an assert does

An assert stops execution and flashes up a message when a condition fails.  If there is a debugger attached then if it can it will direct the programmer to the source where the assert fired.  Great for the programmer trying to track something down, rubbish for someone else who has to skip the message (perhaps many times) to do what they are trying to do.

Asserts disrupting workflow for other programmers and disciplines have been mitigated in a few ways.  The following are some more common methods:

  • Builds with asserts turned off
  • Asserts with a concept of levels or categories that can be toggled
  • Assert instance toggle – it will appear once but as well as skip there’s an option to ignore

Crying wolf

Asserts that continually fire create too much noise; unless the game completely falls over then people start to not take any of them seriously.  Just like compiler warnings there is a point where many eyes just glaze over the number and a number above zero becomes an excepted part of life… perhaps even becoming a joke.

Do or do not, there is no try

Yoda: 'Do, or do not!  There is no try'.

Asserts show a lack of confidence of an operation being successful – so much so that a human being should be warned.  It is a developer communicating with themselves and others that at some point something is in a state so dire that normal execution must be interrupted so someone can take a look.  I do not believe having that kind of warning permanently buried and hidden is healthy.  It is preferable to either formally test and handle the situation if it really is expected, or get to the real root of the problem and prevent that invalid state from ever occurring.

Sanitize the data once properly rather than repeatedly sanitizing the same data in the same way throughout the program just in case.  Every time a conditional statement is encountered there is a computational cost associated with that.  A code block could have its own setup and destruction costs – perhaps more so if exception handling is being used.  This may seem like premature optimization but clear concise code is easier to digest for man, compiler and machine.  After all the best kind of processing is the processing you can eliminate – look to improve your algorithm.

Asserts in the middle of a method after a long conditional block could indicate that the method could be broken in to smaller more focused testable methods.  If possible architect so that a method will always succeed in some measure to allow callers to expect the same predictable outcome.  If a function should always return a populated something, use a default something rather than null.   For example use a valid bright pink texture for missing data and log the error rather than just returning null and forcing everything from that point on to check for nulls.

Silent but deadly

A badly written assert may cause a side effect as part of testing the condition perhaps without the programmer even realizing it.  When an assert like that is disabled it causes different behavior between types of builds.

Worse is when an assert expects to be heeded in the same way as exception.  Ignored or absent through compilation options, execution blunders on and states become corrupted, going on to cause unpredictable problems later.  Perhaps that problem will even mask itself as an issue with a completely unrelated system.   In the worst case corrupt data could be persisted, ruining a saved game.

Asserts encourage a codebase that constantly tries to correct itself rather than addressing the real problem.  Methods no longer trust each other to fulfill their remit.  Expectations of callers change from “I should only give it foo” to “I can give it foo, bar or nothing at all”.  Those expectations can virally spread throughout the codebase causing more methods to second-guess each other and bloat.

The truth is out there

Earlier I stated that asserts in the main body of code shows a lack of confidence and are used to try to mitigate bad states.  Used in the context of test functions they serve to communicate an expectation of success.  The tests can be run independent of running the game or application itself and provided with sample of runtime data to consume.  Instead of the same assertions being made in multiple places against the same method scattered across the codebase, an expectation for a specific scenario can be stated exactly once.

Asserted expectations can be gathered in a test suite to form a living document in code that provides examples of use that are easily found.  Compile time can be quicker for coders because tests can be separated out in to different projects – run only during the testing phase of a change and on the build machine.

Conclusion

Asserts in the main body of your code clutter the logic and could be expressed more concisely elsewhere.  Programming too defensively could blur the responsibility of what is being written.  Do not always code “just in case” otherwise callers will start to rely on the defensive parts.  Either set the expectation of a method to always sanitize (and perhaps hint at that extra processing in the name) or fail as gracefully and quickly as possible.  Methods have to be able to trust each other.  Many applications and games are closed systems that have predictable points of failure, only the input from the boundaries should be considered for sanitization.  Failed asserts should be a point of immediate failure – though I would argue there are better ways of indicating failure.

Asserts are very useful for debugging, but be wary of the costs of permanently committing them to the main body of your source code.  Logging error messages and substituting inert values can be far less obtrusive then relying on asserts breaking execution and popping up message boxes.  It is outrageous for a tool that is supposed to run unattended to stop everything waiting for input, just fail and exit.

Asserts do belong in source control when used to formally test methods and when they clearly express specifications.  This kind of living documentation created by asserts is a form of cover fire.  If you cannot separate asserts in to formal test methods to create clear behavior specifications, try and gather them together close to where the bad state will first occur.  Group them close as possible to where an errant call could first appear on the stack, rather than scattering the expectations around deep in the code.  Let the developer see everything that is expected at a glance.  Asserts should help avoid detective work after all!

There are many advantages to taking asserts scattered through your code and creating test suites from them – see my previous article Cover Fire for Coders.

Further Reading

Some other related #AltDevBlogADay articles about debugging and asserts you might be interested in:

Some books you might be interested in:

McConnel, Steve (2004).  Code Complete – 2nd Edition.  Microsoft Press.  ISBN: 0-7356-1967-0 UK Amazon FlagUSA Amazon FlagCA Amazon FlagDE Amazon FlagFR Amazon Flag

Chapter 8 covers the split between debugging tools and effectively handling failure in production code.  It supports quite some things that I advocate in this article in a much more detailed discussion.  One of my favorite quotes from the chapter: “Sometimes the best defence is a good offense.  Fail hard during development so that you can fail softer during production”.

Keith, Clinton (2010).  Agile Game Development With Scrum.  Addison Wesley.  ISBN-13: 978-0-321-61852-8 UK Amazon FlagUSA Amazon FlagCA Amazon FlagDE Amazon FlagFR Amazon Flag

This book covers how spending time eliminating technical debt can help create a more predictable schedule and end up with a more focused, polished game.

[Paul Evans is a central technology programmer at Lionhead Studios.  He has worked on the Fable II, Fable III and other unreleased titles.  You can find him on Linkedin, see other things he has written on his personal blog, and follow him on twitter.  Everything in this article is Paul’s opinion alone and does not necessarily reflect his employers views. Copyright ©2011, Paul Evans.]

(Originally posted for #AltDevBlogADay)

Cats have nine lives

2011/02/10

(Originally posted #AltDevBlogADay)

 

“Oh no I died again!” – not something you generally get to say in real life is it?  Yet gamers readily accept death as a temporary failure state – just a blip towards achieving their goal.  Death has been abstracted in games in many varied ways over the years and in some games abstracted away completely.  It has been used to provoke emotion, to punish,  to teach, to up the stakes or just to increase a score.

 

But the cat came back the very next day…

 

Arcades with video games and pinball machines are quite rare now in the UK (now they are full of fruit machines) but are still a good starting point for looking in to players’ lives in games.  Lives in Pinball are represented by identical silver balls – a limited resource per game.  A player may start with three balls and might even win extra balls but eventually the game will end with a score.  Score is used as a measure of success across all of your lives, with each finite reincarnation another chance at increasing the net accomplishment.

 

Space Invaders sees the player’s ship explode and be replaced with an identical clone  a limited number of times.  PacMan actually shrivels up in to nothing and makes a pitiful whining noise as his little spherical body implodes at the touch of Inky, Blinky, Pinky or Clyde… but another identical PacMan takes his place.  These games are over thirty years old but the themes of credits, lives and scores still permeate throughout modern games in all sorts of disguises.

 

This kind of death and credit system is useful to monetize failure.  Want to see more of the game?  Well okay then… you have ten seconds to cough up the money and we will let you see some more.  If you do not come up with the money then back to the start for you!  Progression therefore will cost you, mastery of skills and patterns only earned after costly failure.  Is it worth antagonizing a player with this kind of death in games that are not pay-per-play?

 

Mario and Sonic teach via death.  I cannot believe that these games were designed so that a brand new player could get through the entire game without learning through a fatal kind of trail and error.  Punishment for death can increase from the arcades where you can always bribe your way through a section, because in some games you pay in time instead.  After dying a few times in a row the punishment goes from a pained animation to having to restart an entire area – taking away hard fought progress from the player.  While some players thrive on this type of this type of challenge I would argue this action can be demotivating.  Only a certain kind of player continues on to conquer this, others will just walk away in frustration.

 

‘Splosion Man has death but you just bounce right back in a glorious  splodey sentient cloud of insanity.  The game has levels and stages to clear and it is not possible to save your progress in the middle of a stage.  The game does offer the player an option to skip to the next stage if you die in a section too many times in a row.  So a frustrated player can skip forward to see new content and get some sense of progress.  I never took up the option… too much gamer pride.  But I did hear something about a pink tutu you have to wear in the next stage if you do!

 

Games with lives and credits often also keep score, either in terms of points or fastest times.  They promote competition through leaderboards, with players trying to out do each other for bragging rights.

 

If it bleeds we can kill it (apart from if it is the player)

 

There is a snowy mountain path continuing to the NORTH.  To the SOUTH a noisy group of villagers carrying flaming pitchforks are closing in on your location.  They all seem kind of angry.  Well apart from the springer spaniel that is wagging his tail furiously.  He seems to think this is the best walk ever.

 

> NORTH

 

You tripped over something and fell off the cliff, a whooshing sound fills your ears followed by a very nasty crunching noise.  Breathing heavily and looking up you see the villagers standing where you were laughing.  One shouts down to your broken body “enjoy your trip?”  Another takes your INFRARED SUNGLASSES that fell from your pocket before your tumble and puts them on.  “OOOh INFRARED SUNGLASSES, I’ve always wanted a pair of these! I’m seeing red… oh look at that INVISIBLE TRIP WIRE across the path!”  Rolling your eyes, you promptly expire.

 

THE END.

 

If only the player would have typed USE GLASSES.  Ah well.  It was all great playing that text adventure until you died, then you had to consider if you really wanted to play through all *that* again.  It is like not being able to cheat in a “Choose Your Own Adventure” book.  Part of the reason I like Monkey Island II so much was that you could not get in to that situation.  Sure you could get stuck, but Guybrush could not die (but could certainly embellish the stories he told about it).  The lack of death (but the presence of peril) made the game a very accessible adventure game.

 

In Fable III, you get knocked down, but you get up again.  There is a price though; you get scarred up and you could lose some experience towards your next guild seal.  This cosmetic toll is unbearable to some – I have known people to quit to the dashboard to avoid the auto save kicking in and saving their character in a knocked out state.  Of course others play well but get knocked out on purpose… because scars are cool and perhaps they like the villagers making negative comments about their looks (just another reason to take the safety off).

 

The player in these games has one life that is constantly threatened but never ends.  It gives a player license to experiment without fear of a sticky end.  Games where the player cannot die often focus on telling a story rather than keeping score.  They might also have to fight against the perception of being “easy”.

 

Ouch that really stings

 

There are a breed of games where death is both an inconvenience and a common occurrence.  Gone are the limits on lives and credits.  A player can retry many different things in different ways without fear of being sent back to an arbitrary check point a designer decided would be a good place to start again.

 

In Braid, everything fades and pauses… whoops better rewind time to before that death happened.  No penalty really, unless the backwards noise really grates against you.

 

Crackdown and Bioshock have the concept of clones… so just like Pacman and the hero’s ship in Space Invaders there is always a new vessel for a player to jump in too.  Though in Crackdown & Bioshock the effects of the previous clone are still present in the world.  You literally are a player clone army and in Crackdown II there is actually an achievement rewarded for finding all the ways an agent can die.  Death then can be its own reward.

 

Demon’s Souls adds a community aspect to death.  Death can come completely out of the blue but blood stains can be used to communicate to other wary players what is in store for them – death is a form of shared learning experience.

 

Limbo sees the little boy avatar you control dying over and over again with very little game penalty.  I take it back, the deaths are really quite disturbing and stomach churning though I’m sure there are those reading that just think it is funny!  Heck it is probably a good way of acclimatizing to that kind of horror.  Each death is over so quickly and so little ground is lost that it hardly costs any player time at all to die.

 

These games attempt to limit the frustration of death by placing the player close to the point of failure.  They dust off the player and say “have another go, try something different”.  Many of these games want you to complete them and know that some of the challenges they offer are tough.

 

No you really are dead

 

Something that computers and home consoles can do that I have not known in the arcades is the game save.  A precious area of memory where a player can save their progress through the game and return to it at will.  This allows the paradox of a player dying and a game ending, yet able to return to a certain point of time before that happened.  Kind of like Ground Hog Day, where the entire world in unaware that all this has happened before (and all this will happen again).  The player though has hopefully gleaned some knowledge to progress past that sticky point, so perhaps after x amount of times it will actually happen differently!

 

The downside of this is that the game does not know you played through a section either, so if there are any sections of non-interactive play then a player is doomed to sit through them again and again.  As a player I really, really do hate times where I am forced to sit through sections of the game deemed so essential that I must watch them before interacting again.  Perhaps there is a happy compromise, a separate save file held that indicates if a player has experienced that oh-so-important content once even if they revert to a previous save?

 

Grand Theft Auto IV and Red Dead Redemption do sometimes have fresh dialogue for retrying a totally failed mission from a checkpoint.  GTA does exact a penalty for death (or at least lack of heath) – the player does not automatically revert to a save but instead ends up in a hospital with the contents of their previously bottomless pockets empty.

 

Red Dead Redemption did rely on teaching me that I cannot disarm people in story mission duels via killing me off and reverting me to a save / checkpoint.  I really would have preferred disarmed opponents that had to die to have killed themselves rather than gimping the disarm mechanic and killing me in duels.  Being quite a persistent gamer I believed them to just be formidable opponents, so I did try one particular duel over and over again for an hour before I caught on (sigh).

 

If a player veers away from where the story teller wants them to go, they are killed off and put back somewhere they can make a different choice.  It does become frustrating if that choice is not clear, or if a player sees what they are supposed to do but lacks the skill to do it.  Perhaps worse still, when the player remembers something from several hours ago that would change things now.  Arguably save slots offer redemption for mistakes… at the cost of perhaps many hours of player time.  Multiple save slots also potentially endanger the weight of player decisions.

 

Should a player be able to decide to “cheat” and turn the pages back, or should that temptation be removed?  Do you trust a player to not replay one part of the story again and again to see all the different outcomes?  Does it even matter if they do?  I don’t think so if the player is having fun, but Mr. Resetti would disagree!

 

You wear yellow, they wear red

 

When a hero dies there is a save point or usually a special something that allows them to fight another day.  The same cannot be said of other characters and things the player interacts with in a game world.  You are Captain Kirk, the other characters are red shirts.

 

Games in the Civilization, Age of Empires and Command & Conquer series reward units that survive many battles with experience.  They reward the player for leadership that keeps the minions alive.   Cannon Fodder also had this but had an extra twist.  Giving my squad names and knowing the penalty of seeing a new grave on the hill at the end of the level made me work just that little bit harder to keep my squad alive (see comments from other gamers on this vid).

 

Some game’s deaths actually are a vital part of the storyline and they expect the player to accept that.  Characters in The Sims eventually die if you play with them.  Sure you could just switch characters, keep reverting to a save or allow them to continually imbibe from the water cooler of youth but you are always able to let time take its course and eventually death  will come to collect them.  Then they are gone.  Ok, well you might get a ghost hanging around but they are not remotely the same.

 

Mass Effect makes the player choose life or death for their own team members at points during the game.  Mass Effect  II rewards good leadership and truly knowing the players own team with extra story and different outcomes.  There comes a point where deep knowledge of a the supporting cast strengths and weaknesses can save their lives.

 

Having a player care about their supporting cast is terrible when it feels unfair (why won’t this healing potion work on them this time… it worked the other thousand times?!)  When done right though it gives a player extra emotional investment in not only the avatar they control but more of the world they are experiencing.

 

That’s all folks!

 

I would be very interested in hearing about how you think player death may evolve in the future, more examples of the above and your own personal experiences in the comments.  Many argue games are getting easier – some would say they are becoming more accessible.  A few designers have designed away player death completely in their games.

 

Death serves a few purposes, but chiefly to either completely end a score attempt or to impede progress through a larger game world.  Geometry Wars understands that smashing down a button lots of times should just let the player try again (a touch many gamers I am sure appreciate).  Other games use checkpoints and saves to snatch failed player actions out of the air as if they never happened; or return a carbon copy of that character back to the world sometimes none the wiser of the predecessors fate.

 

While writing this blog I asked an open question on Twitter about player and character death.   The many replies even then just go to show what a wide subject this is in both narrative and gameplay.  Grim Fandango, Planescape: Torment and Die2Nite have been suggested to me as games that explore death itself, though that is a topic for a different article.  As a programmer and gamer I believe the way death is handled in a game very much defines how the game feels and plays overall.  I do hope this article sparks off a few interesting conversations.  You may leave comments here or try joining a conversation on Twitter – I suggest the hash tag #PlayerDeath @paulecoyote.

 

Thanks

Tweeters that helped me out in no particular order: @DaveFeltham @zackfreedman @lingmops @glamgeekgirl @oOSTVOo @twonjosh @paulnew @acroyear3 @BusterMcFearson @Stomp224 @JurieOnGames @ChrisA9 @ColleenDelzer @Renmauzuo @NaviFairyGG @FatalWebMunki @bjoernknafla @daredevildave

 

Also many thanks to my lovely wife proof reading this for me several times before I published it.

 

Paul Evans is a central technology programmer at Lionhead Studios. He has worked on the Fable II, Fable III and other unreleased titles. You can find him on Linkedin, see other things he has written on his personal blog and AltDevBlogADay.org. You can also follow him on twitter @PaulECoyote. Everything in this article is Paul’s opinion alone and does not necessarily reflect his employer’s views, nor constitute a legal relationship.

Cover Fire for Coders

2011/02/10

By Paul Evans ( twitter | blog | Linkedin ) – Originally posted on #AltDevBlogADay

 

You are coding away and suddenly realize that there is a vital piece of new data you need to propagate through the battlefield of your game (or application) for your change.  Your heart sinks… you are going to have to take drastic action.  It will be tricky to safely create and navigate that vital piece of data through the lines.

 

A complex web of method signatures fill the field like barbed wire between your data and its goal – painful for both friend and foe.  Tracing back from your goal, you come across comments from generals that have trodden a similar path in the past and shudder at their remarks.  Some of them had to do some rather unsavory things, some warn against the consequences of using exactly the method you were thinking of.

 

You wipe sweat from your brow; is it really worth it to try and guide this plucky new data across such a hideous mine field?  A message from the tower tells you that you have no choice.  Reluctantly you make a plan for the fresh data recruit to cut through the battlefield at a certain point.

 

Your data makes it through and helps fortify the frontline – it all looks good.  Only three months later does a subtle change you made show up as having a hideous side-effect on the entire outcome of the war.  A halfling managed to make it behind the lines and is causing all kinds of problems.   But your plan was reviewed by one or more generals!  No one saw anything wrong with it!  Until that day when it *all* went wrong and now the Eye of Sauron is focused squarely on you…

 

If only there was an alarm hooked up… a simple safe guard to indicate there was something amiss.  Find a way to test, this story need not be about you!

 

Allow time for tests

Managers and leads, please allow time for tests in schedules.  Programmers, include extra slack in estimates for writing them.   There are many reasons why – but it all comes back to your definition of done.  Is “it works for me” good enough?  Is it enough to set things up and assume everything will go to plan?  When is something really signed off?

 

Scott Evil: Wait aren’t you even going to watch them?  They could get away!

Dr. Evil: No, no, no; I’m going to leave them alone and not actually witness them dying.  I’m just going to assume it all went to plan, what?

 

Austin Powers versus the Ill Tempered Sea Bass

and Austin Powers escapes.

 

Benefits of automated testing

For the coder it is like cover fire.  Every test is another sniper covering some small part of the code for you.  If something flashes up in their scope they can immediately warn of some nasty bug lurking.  That regressive bug never gets a chance to get a foothold.  Each extra test watches out over your software at a different angle and cumulatively they become a very useful force.

 

A well written test reviews your code – not on how you wrote something like a human reviewer might – just against an expected result.  A rational coder can not argue their code is decent if it fails a good test.

 

Tests form a kind of living functional documentation that any written form can never hope to compete with.  If a test becomes obsolete it is changed to fit a new requirement or even removed entirely.  Anyone that can write code can understand and write the tests.

 

A good test suite can even aide the gung-ho programmer that is desperate to rewrite a big chunk of code (ahem Alex Evans 🙂 ).  As long as the new code satisfies the integration tests and functionally achieves the same thing – have at it.  But before rewriting create some tests to measure performance, then after the rewrite the new work can have proven value.  If another change in the future reduces performance an alarm bell will go off.

 

Code passing a good set of tests in a branch can give any coder the confidence that a clean get from source control will result in a successful build of useful software.  That could be a pivotal moment for getting together something presentable for that last minute demo.

 

If you cannot test something, then it is unlikely that the code in question is fully understood.

 

But I can’t test

 

I can’t test because I don’t know where to start… there is just so much already there!

  • Some tests are better than none.
  • Try “Tracer Bullets”[2] to shoot down bugs and introduce tests to your game / application:
    • Create a test that tests the bug and fails.
    • Fix the bug, make sure the test now passes.
    • Commit and resolve.
    • Now if anyone regresses the behavior, your test will catch that right away.
    • Test coverage is cumulative – more bugs fixed in this way increase coverage at valuable pain points.

 

I can’t test because I don’t know what I expect yet.  I’m still figuring that out.

  • Prototype to investigate the problem domain.
  • It would be helpful to set a time box around the research period (a “spike” [4]).
    • Setting a time limit will allow you to :
      • Step back before going too deep down a rabbit hole.
      • Concentrate on estimating the size of the problem domain.
  • Concentrate on figuring out what to test – the tests are likely to be usable even if the prototype code is not.

 

I can’t test it because there is no one expected state.

  • Just think creatively while writing the test.  For example :
    • If a test is for randomness, then obviously there is no one predictable state.  But there can be a fitness function that defines how random something should be.
    • If looking for problems in a scene screenshot, perhaps a test could ensure a reserved color used for missing textures is not present.

 

I can’t test it because I cannot isolate the behavior to test

  • This could indicate:
    • Possibly blurring of responsibility with highly dependent and coupled code (perhaps too general).
    • Code could be reaching through objects, violating the principle of least knowledge.
    • Architecturally a lot of cruft is required to access useful behavior.
    • Code has been added to workaround a prior issue rather than refactored for a new requirement, adding to the cruft.
  • Rework to be testable if you can, try to isolate and retire if you cannot.Rework to be testable if you can, try to isolate and retire if you cannot.

 

I can’t do all these tests, it would increase build time

  • Keep tests in separate project or solution, you can run them only before committing to source control.
  • Ensure each test does not take long to run, mock where necessary.
  • Partition tests that must run for a long time.  Perhaps only run them on the build server.
  • Partition tests per module so that only particular module and integration tests are executed.   This gives the coder the choice to only run the tests they need.

 

I can’t write tests, I just do not have the time

  • This one is the hardest thing to overcome if there is no management buy-in to testing.  As a programmer at any level try your best to campaign for more scheduled time.
  • Writing tests gets quicker as a programmer gains experience (just arrange, act and assert one thing in each test).
  • Once tests start proving there are fewer regressions being reported in the bug database, it is an easier sell.  Gather any time saving metrics you can.

 

Summary

To many game developers I am sure tests don’t seem very rock & roll… not something they may have considered to be part of their role in the industry.  So I expect many do not test their work.  Writing elegant tests can present interesting engineering challenges and can be a good way to understand something that is new to you.  There is satisfaction to be had when all your tests pass after a big change, or when you realise a test saved you from an obscure bug or bad design choice.

 

Testing is no silver bullet, but try to think of it as an investment against that same bug being reopened many times later on.  Wouldn’t you rather spend time on polishing something else then finding and squashing the same bug again?

 

Further Reading

Clinton Keith’s book is written for game developers that want to think about different ways of prioritizing and scheduling tasks during game development.  It includes many reasons for testing and many interesting stories from the front line.  (For the purposes of disclosure he was also kind enough to acknowledge me for helping him out a little bit).

 

The other books listed are not specifically about game development but software excellence in general.

 

[1] Keith, Clinton (2010).  Agile Game Development With Scrum.  Addison Wesley.  ISBN-13: 978-0-321-61852-8

UK Amazon FlagUSA Amazon FlagCA Amazon FlagDE Amazon FlagFR Amazon Flag

 

[2] Richardson, Jared & Gwaltney, William (2005).  Ship It! A Practical Guide to Successful Software Projects. ISBN: 0-9745140-4-7

UK Amazon FlagUSA Amazon FlagCA Amazon FlagDE Amazon FlagFR Amazon Flag

 

[3] Martin, Robert C. (2003). Agile Software Development: Principles, Patterns and Practices. ISBN: 0-13-597444-5

UK Amazon FlagUSA Amazon FlagCA Amazon FlagDE Amazon FlagFR Amazon Flag

 

[4] Pryce, Nat (2010). Growing Object-Oriented Software, Guided by Tests. Beck Signature.  ISBN-13: 978-0321503626

UK Amazon FlagUSA Amazon FlagCA Amazon FlagDE Amazon FlagFR Amazon Flag

 

[5] McConnel, Steve (2004).  Code Complete – 2nd Edition.  Microsoft Press.  ISBN: 0-7356-1967-0

UK Amazon FlagUSA Amazon FlagCA Amazon FlagDE Amazon FlagFR Amazon Flag

 

[6] Subramaniam, Venkat & Hunt, Andy (2006).  Practices of an Agile Developer: Working in the Real World. ISBN: 0-9745140-8-X

UK Amazon FlagUSA Amazon FlagCA Amazon FlagDE Amazon FlagFR Amazon Flag

 

Paul Evans is a central technology programmer at Lionhead Studios.  He has worked on the Fable II, Fable III and other unreleased titles.  You can find him on Linkedin, see other things he has written on his personal blog, and follow him on twitter.  Everything in this article is Paul’s opinion alone and does not necessarily reflect his employers views. Copyright ©2011, Paul Evans.