Thursday, November 15, 2012

Break Your Software

In Software Engineering, there seems to be a general acceptance that as long as there is software then there will always be software bugs.

Bugs in software are defects that produce incorrect or unexpected results or cause the software to behave in unintended ways. The majority of bugs in software arise from errors written in developers’ source code; yet it is generally the primary task of QA testers to find said bugs.

Nonetheless, testing for bugs in software should be the responsibility of the entire team: developers typically focus on unit testing to exercise units of source code in isolation whereas testers concentrate more on functional testing to verify the correctness of software end-to-end.

Developers benefit from unit testing simply because it allows them to find problems in the source code quicker: they can zone in on code at the lowest (unit) level and assert the code functions as expected.
It also facilitates difficult-to-reproduce scenarios, such as database offline, by using mock frameworks developers can fake external dependencies, and ensure the code is resilient to unhandled exceptions.

To summarize: the earlier bugs are detected, the cheaper they are to fix.

Writing testable code allows developers to push the boundaries and effectively "break their software". By proactively breaking their software, developers identify defects before anyone else does. These defects can, and should, be fixed immediately before any further work continues. This way, the software is more robust: stability is built into the code base and quality software can be delivered at speed as you code with confidence.

Test Driven Development is a formal way to break your software: you do not write one line of production code unitl you have written a test that fails. Implement the code to make the test pass and no more. Rinse and repeat. This style of programming does come at a cost but the additional time spent during development should be supplemented by a reduced QA cycle as fewer bugs are reported.

One final thought: in a world of abundant choice, people pay for quality in products and services that are important to them. Software is no exception. So go ahead: break your software (before anyone else does) and deliver the best software you can.

Saturday, September 15, 2012

Quality vs. Velocity

In Software Engineering terms, quality reflects how well the software conforms to a given design, based on functional requirements and the degree to which the software is built correctly. Whereas velocity simply measures how fast the software is built.

Example
A piece of functionality needs to be added to the system; there are typically 2x options:
  1. Build a clean and solid design that is well tested but may take longer to integrate
  2. Apply a quick and dirty change that works but makes future coding more difficult
Cutting corners in terms of code quality may provide short term gains as features are implemented quicker, but this false economy leads to future costs: time spent refactoring, time spent fixing bugs; time spent re-understanding how the code works etc.

Technical Debt
Technical Debt refers to this false economy as the eventual consequence of poor software architecture and development within a code base.

In the example above, the quick and dirty change creates technical debt; similar to financial debt, technical debt incurs interest payments, which comes in the form of extra development which must be done in future because of the quick and dirty change.

In business, companies may be willing to incur financial debt to take advantage of market opportunities; they may also put pressure on developers to incur technical debt in order to hit important deadlines:

Here trading quality for development speed is really trading time now for time later; however, there is compound interest to putting off the work.

Therefore, there is constant challenge to minimize technical debt: work at high pace in order to meet aggressive deadlines while maintaining high levels of quality in the code.

Process
SCRUM process is being adopted more frequently to provide an iterative incremental framework for managing complex work, minimize rework and improve velocity.

However, it is still important to focus on agile software development techniques in order to improve quality and minimize technical debt.

Why? Because good code quality should help you move faster:
  • Consistent coding style / naming conventions makes code easier to maintain
  • Well-defined interfaces make self-documenting code easier to understand
  • High test coverage can uncover issues quicker and reduce potential bugs
  • High test coverage also allows teams to refactor code with confidence
Let’s revisit the example above:

Build a clean and solid design that is well tested but may take longer to integrate: the additional time spent during development should be supplemented by a reduced QA cycle as fewer bugs are reported.

In my experience, promoting quality over velocity, in the long-term: projects always take a lot less time.

Summary
In conclusion, agile software development techniques such as the following can help instil quality:
  • Unit testing, test-driven development, pair programming
  • Design patterns, domain-driven design, code refactoring
  • Stability through automated tests / continuous integration
Goal: drive quality through each software development project in order to eliminate technical debt!

Friday, September 7, 2012

XNA and Component Based Design

In the previous post, we discussed the topic of XNA and Level Validation.
Now, let's build on this information to discuss Component Based Design.

Note: this post includes complete code sample on CodePlex.
Download code sample here.

Component Based Design
Component Based Design is a common approach to build game objects that are flexible, maintainable and scalable: each component encapsulates a set of related functions, or data, so that additional game objects can be created without any extra code.

In game development, component based object data is typically stored in XML files. The logic used to parse XML and build game objects can be complex and error prone; consequently, system tests can
be used to validate all game objects before fully integrating into the game.

Example
As an example, let’s revise the Spacewar starter kit to demonstrate XNA and Component Based Design.
First, create a system that can parse XML files and build proxy objects for game consumption:
public class ProxyObjectBuilder
{  
 public void BuildProxyObjects(String folder, String txtFile); 
 public void BuildProxyObjects(String folder, IList<String> xmlFiles); 
 public ProxyObject GetProxyObject(String name); 
}
Next, create a component that can be used to build custom game objects at run-time:
public class GameObjectBuilder
{ 
 public T BuildGameObject<T>(String assetName) where T : GameObject;
 public GameObject BuildGameObject(String assetName);
 public GameObject BuildGameObject(ProxyObject proxyObject);   
}
Sample
The following code sample refactors the starter kit to integrate an unlimited number of spaceships using data driven design and validates each spaceship through system tests.
First, define an XML file that stores an unlimited number of spaceships available; each spaceship defines:
  • 3D model, ship class and ship skin
  • Position, rotation, flight boundary
  • Thrust power and bleed velocity
<Assets>
 <Asset name="PencilOneSkinOne" type="Spaceship">
  <ModelComponent id="100" shipClass="PencilOne" modelName="p1_pencil" textureName="pencil_p1_diff_v1" />
  <PhysicsComponent id="200" modelScale="0.02" rotateScale="0.02" position="0,0,0" rotation="90,0,0" boundLeft="-400" boundRight="400" boundTop="-250" boundBottom="250" />
  <ThrustComponent id="300" textureName="thrust_stripSmall" thrustFrame="12.0" thrustConstant="12" thrustMaximum="29" thrustFactor="1.0" thrustPower="100" bleedVelocity="0.3" />
</Asset>
Also, define an XML file that stores an unlimited number of weapons available to each spaceship:
<Assets>
 <Asset name="RocketTwo" type="Weapon">
  <ModelComponent id="100" modelName="p2_rocket" textureName="p2_rocket" />
  <PhysicsComponent id="200" modelScale="0.02" rotation="90,0,0" boundLeft="-400" boundRight="400" boundTop="-250" boundBottom="250" />
  <WeaponComponent id="400" cost="3000 " lifetime="1.5" maximum="1" burst="1" acceleration="300" damage="5" />
 </Asset>
</Assets>
Finally, write system tests to validate all data before fully integrating into the game.
Note: an IoC Container will be used to construct all components used throughout.

PROXY OBJECT BUILDER TESTS
[TestFixture]
public class ProxyObjectBuilderTests
{
 // System under test.
 private ProxyObjectBuilder proxyObjectBuilder;
 
 [SetUp]
 public void SetUp()
 {
  proxyObjectBuilder = IoCContainer.Resolve<ProxyObjectBuilder>();
 }

 [Test]
 public void BuildProxyObjectsSpaceshipsTest()
 {
  String path = GetPath();
  String[] xmlFiles = new[] { "Spaceships.xml" };

  proxyObjectBuilder.BuildProxyObjects(path, xmlFiles);

  Assert.AreEqual(18, proxyObjectBuilder.ProxyObjectManager.ProxyObjects.Count);
 }
}
GAME OBJECT BUILDER TESTS
[TestFixture]
public class GameObjectBuilderTests
{
 // System under test.
 private GameObjectBuilder gameObjectBuilder; 

 [SetUp]
 public void SetUp()
 {
  gameObjectBuilder = IoCContainer.Resolve<GameObjectBuilder>();
 }

 [Test]
 public void BuildGameObjectSpaceshipComponentTest()
 {
  String path = GetPath();
  String[] xmlFiles = new[] { "Spaceships.xml" };
  gameObjectBuilder.ProxyObjectBuilder.BuildProxyObjects(path, xmlFiles);

  String assetName = "WedgeTwoSkinOne";
  Spaceship spaceship = gameObjectBuilder.BuildGameObject<Spaceship>(assetName);

  var component = spaceship.GetComponent<ModelComponent>();
  Assert.AreEqual(ShipClass.WedgeTwo, component.ShipClass);
  Assert.AreEqual("p2_wedge", component.ModelName);
  Assert.AreEqual("wedge_p2_diff_v1", component.TextureName);
 }
}
Download code sample here.

Summary
The revised Spacewar starter kit demonstrates how to integrate an unlimited number of spaceships using data driven design: simply update the XML file to add more spaceships without constant need to recompile and validate all data quickly and efficiently through system tests.

In conclusion, data driven design does seem to have the potential to scale using XNA:
Consequently, there is an opportunity to integrate more complex game code and data using XNA and
data driven design techniques.

Friday, August 31, 2012

XNA and Level Validation

In the previous post, we discussed the topic of XNA and System Testing.
Now, let's build on this information to discuss Level Validation with XNA.

Note: this post includes complete code sample on CodePlex.
Download code sample here.

Level Validation
In game development, level data is most often stored in text files. For example, the Platformer starter kit contains 3x levels, although an unlimited number of levels could be added using data driven design.

Level data can then be validated through system tests to ensure all data is true and correct, and that all rules are observed before the level is actually loaded into the game.

Example
As an example, let’s revise the Platformer starter kit to demonstrate XNA and Level Validation.
First, create a system that can parse text files on demand; use the interface from previous post:
public interface IFileManager
{
 IList<String> LoadTxt(String file);
 T LoadXml<T>(String file);
 XElement LoadXElement(String file);
}
Next, define all the rules for each Level in the game; for example, each Level must have:
  • Valid characters only for player, enemy, tiles + gems
  • Same number of tiles width for each row in level
  • Exactly one entry for player - no more, no less
  • Exactly one entry for the exit - no more, no less
  • A passable tile immediately above the exit
Sample
The following code sample refactors the starter kit to integrate an unlimited number of levels using data driven design and validates each level through system tests.
First, define a simple text file that will store all levels to load in the game and in correct order.
Next, add all the corresponding level data for all levels in the game; one level per text file:

E.g. Level 10
...........G.G.G.G..
...1............A...
..######..########..
.....G.G.....G.....G
......B.............
G...-----...--.G..--
....................
--.G.G........--...G
....C........G......
..----.G.G..--....--
........D...........
.......----...--....
.G.G.........G.G.G..
..X.................
######......########
Add a method to the Level class to validate all level data according to the rules as defined above:
public class Level : IDisposable
{
 public void Validate()
 {
  if (null == levelData)
  {
   throw new Exception("No level data loaded.");
  }

  string validCharacters = ".XG-ABCD~:1#";

  // RULES:
  // Ensure only valid characters parsed.
  // Ensure same tile width for each row.
  // Exactly one entry for player!
  // Exactly one entry for exit!
  // Ensure exit point passable!
 }
}
Finally, write system tests to validate all data before fully integrating into the game.
Note: an IoC Container will be used to construct all components used throughout.

FILE MANAGER TESTS
[TestFixture]
public class FileManagerTests
{
 // System under test.
 private IFileManager fileManager;
 
 [SetUp]
 public void SetUp()
 {
  fileManager = IoCContainer.Resolve<IFileManager>();
 }

 [Test]
 public void LevelDataValidateTest()
 {
  String levelsFile = GetPath("LevelData.txt");
  levelIndexes = fileManager.LoadTxt(levelsFile);
  numberOfLevels = levelIndexes.Count;

  // There must be at least one level!
  Assert.IsTrue(numberOfLevels > 0);

  for (Int32 levelIndex = 0; levelIndex < numberOfLevels; ++levelIndex)
  {
   String levelFile = levelIndexes[levelIndex];
   Validate(levelFile, levelIndex);
  }
 }

 private void Validate(String levelFile, Int32 levelIndex)
 {
  String levelPath = GetPath(Constants.LEVELS_DIRECTORY, levelFile + ".txt");
  IList<String> levelData = fileManager.LoadTxt(levelPath);
  level = new Level(levelData);
  level.Validate();

  String text = String.Format("Level #{0} = {1}.txt [{2} rows]", (levelIndex + 1), levelFile, levelData.Count);
  Console.WriteLine(text);
 }
}
Download code sample here.

Summary
The revised Platformer starter kit demonstrates how to integrate an unlimited number of levels using data driven design: simply update the text file to add more levels without constant need to recompile and validate all data quickly and efficiently through system tests.

In addition to complex text files, complex XML files may also be loaded into a game, for example, to build game objects using component based design.

This will be the topic in the next post.

Wednesday, August 1, 2012

XNA and System Testing

In the previous post, we discussed the topic of XNA and Data Driven Design.
Now, let's build on this information to discuss System Testing with XNA.

Note: this post includes complete code sample on CodePlex.
Download code sample here.

System Testing
System Testing is the practice in which complete, end-to-end software is tested to evaluate the system’s compliance with its specified requirements.

Game development that implements data driven design may find system testing effective because it can be used to validate all data before fully integrating into the game.

When experimenting with new ideas, all changes made to game data must be valid, otherwise it may be possible to easily break the system, or have the system behave in an unpredictable fashion.

System testing allows for this feedback quickly, efficiently and without need to execute the entire game.

Here is a common workflow to integrate system testing into game development:
  • Write game code and edit game data
  • Run system tests and validate
  • Launch game with current data
  • Update any game data as necessary
  • Re-run system tests and validate
  • Hot swap updated game data
  • Repeat process: no constant build / deploy
Example
As an example, let’s build a basic snake simulation to demonstrate XNA and System Testing.
First, create a system that can parse text files on demand (not just at start up):
public interface IFileManager
{
 IList<String> LoadTxt(String file);
 T LoadXml<T>(String file);
 XElement LoadXElement(String file);
}
Next, create a component to manage all data that will be loaded into the game:
public interface IDataManager
{
 AllData LoadData(String[] files);
}
Sample
The following code sample builds a simulation to integrate an unlimited number of snakes into a maze using data driven design and validates each snake through system tests.
First, define a simple text file that will store all 3x possible maze sizes: Small, Medium, and Large.
Next, define an XML file that stores an unlimited number of snakes available; each snake defines:
  • Start position in maze and direction
  • Length of the snake tail
  • Time delay on each tile
  • No. tiles before direction change
<?xml version="1.0"?>
<ArrayOfSnakeData>
 <SnakeData>
  <StartPosX>10</StartPosX>
  <StartPosY>5</StartPosY>
  <Direction>Left</Direction>
  <TailLength>20</TailLength>
  <TimeOnTile>50</TimeOnTile>
  <TileToMove>10</TileToMove>
 </SnakeData>
</ArrayOfSnakeData>
Finally, write system tests to validate all data before fully integrating into the game.
Note: an IoC Container will be used to construct all components used throughout.

FILE MANAGER TESTS
[TestFixture]
public class FileManagerTests
{
 // System under test.
 private IFileManager fileManager;
 
 [SetUp]
 public void SetUp()
 {
  fileManager = IoCContainer.Resolve<IFileManager>();
 }

 [Test]
 public void BoardDataTest()
 {
  String boardFile = GetPath("BoardData.txt");

  IList<String> lines = fileManager.LoadTxt(boardFile);
  String line = lines[0];

  GameSize gameSize = (GameSize)Enum.Parse(typeof(GameSize), line, true);
  Assert.AreEqual(GameSize.Small, gameSize);
 }

 [Test]
 public void SnakeDataTest()
 {
  String snakeFile = GetPath("SnakeData.xml");
  SnakeData[] snakeData = fileManager.LoadXml<SnakeData[]>(snakeFile);
  Assert.AreEqual(1, snakeData.Length);

  SnakeData snake = snakeData[0];
  Assert.AreEqual(10, snake.StartPosX);
  Assert.AreEqual(5, snake.StartPosY);
  Assert.AreEqual(Direction.Left, snake.Direction);
  Assert.AreEqual(20, snake.TailLength);
  Assert.AreEqual(50, snake.TimeOnTile);
  Assert.AreEqual(10, snake.TileToMove);
 }
}
DATA MANAGER TESTS
[TestFixture]
public class DataManagerTests
{
 // System under test.
 private IDataManager dataManager;

 [SetUp]
 public void SetUp()
 {
  dataManager = IoCContainer.Resolve<IDataManager>();
 }

 [Test]
 public void AllDataTest()
 {
  String boardFile = GetPath("BoardData.txt");
  String snakeFile = GetPath("SnakeData.xml");

  String[] files = new[] { boardFile, snakeFile };
  AllData data = dataManager.LoadData(files);

  Assert.AreEqual(GameSize.Small, data.GameSize);
  Assert.AreEqual(1, data.SnakeData.Length);
  
 }
}
Download code sample here.

Summary
The snake simulation demonstrates how to integrate an unlimited number of snakes into a maze using data driven design: simply update the XML file to add more snakes without constant need to recompile and validate all data quickly and efficiently through system tests.

In reality, more complex text files will be loaded into a game, for example, to build game levels. Level data may require more complex validation to ensure all data is true and correct, and that all rules are observed before the level is actually loaded into the game.

This will be the topic in the next post.

Wednesday, July 4, 2012

XNA and Data Driven Design

Games are made up of two things: logic and data. The logic defines the core rules and algorithms of the game engine, while the data provides the details of content and behavior.

When logic and data are decoupled from each other, the whole team, including designers and testers,
can experiment with different variations and tune the data to get the exact behavior they desire.

Therefore, game data should, ideally be loaded from text files; not embedded inside the code base.
This concept is essential to putting data driven design to work:
  • Create a system that can parse text files on demand (not just at start up)
  • Put constants in text files so they can be changed easily without recompiling code
  • Don’t hard-code anything; assume that anything can change, and probably will!
Example
Galaga: if the game requires only 3x types of enemy spaceships then you could program a perfectly good system that encompasses all of them. However, if you abstract away the functionality of each spaceship, using data to define its behavior, then you allow for an unlimited number; each with its own personality.

When core design decisions are flexible, the game is allowed to evolve to its full potential. In fact, the process of abstracting a game to its core helps tremendously in the design; this forces recognition of
what should be built, instead of the limited behavior outlined in the design document.

System Testing
System Testing is the practice in which complete, end-to-end software is tested to evaluate the system’s compliance with its specified requirements.

Game development that implements data driven design may find system testing effective because it can be used to validate all data before fully integrating into the game.

When experimenting with new ideas, all changes made to game data must be valid, otherwise it may be possible to easily break the system, or have the system behave in an unpredictable fashion.

System testing allows for this feedback quickly, efficiently and without need to execute the entire game.

Here is a common workflow to integrate system testing into game development:
  • Write game code and edit game data
  • Run system tests and validate
  • Launch game with current data
  • Update any game data as necessary
  • Re-run system tests and validate
  • Hot swap updated game data
  • Repeat process: no constant build / deploy
Two examples in which game data can be verified through system tests include:
Level Validation and Component Based Design.

Level Validation
In game development, level data is most often stored in text files. For example, the Platformer starter kit contains 3x levels, although an unlimited number of levels could be added using data driven design.

Level data can then be validated through system tests to ensure all data is true and correct, and that all rules are observed before the level is actually loaded into the game.

Component Based Design
Component Based Design is a common approach to build game objects that are flexible, maintainable and scalable: each component encapsulates a set of related functions, or data, so that additional game objects can be created without any extra code.

In game development, component based object data is typically stored in XML files. The logic used to parse XML and build game objects can be complex and error prone; consequently, system tests can
be used to validate all game objects before fully integrating into the game.

Therefore, it seems only relevant to try and integrate data driven design into XNA game development.
As an exercise, I would like to prototype data driven design using the following examples:
In conclusion, it will be interesting to see if data driven design has the potential to scale using XNA!

Sunday, January 1, 2012

Retrospective III

Last year, I conducted a simple retrospective for 2010. Therefore, here is a retrospective for 2011.

2011 Achievements
Note: receiving acknowledgement by George Clingerman on XNA Notes is an achievement!

2012 Objectives
  • Promote quality in game development using agile software methodologies
  • Incorporate three dimensional graphics into game development projects
  • Monitor the future of XNA, XBLIG, and the Microsoft Indie gaming scene
  • Explore alternative Indie game development distribution channels

In 2010, there was much concern from the developer community as Indie Games were hidden under Specialty Shops as part of the Xbox dashboard update.

In 2011, independent game developers responded angrily to the latest Xbox 360 dashboard update:
many feel that the marketplace is again hidden as Indie Games are now presented as a single list.

Also in 2011, the announcement: No XNA support for Metro applications in Windows 8 has prompted much speculation over the future of XNA.

Quote: It is correct that XNA is not supported for developing new style Metro applications in Windows 8. But XNA remains fully supported and recommended for developing on Xbox and Windows Phone, not to mention for creating classic Windows applications (run on XP, Vista, Win7, and Win8 in classic mode).

This report appears reminiscent to the XNA Game Studio 4.0 upgrade: Not for Zune HD.

Fortunately, there is some positive news for Independent game development, especially now as digital distribution is becoming more prevalent in the games industry; various portals such as Big Fish Games and Steam currently distribute the majority of Indie Games on PC and Mac.

There are also independent games distribution websites, such as IndieCity, built to cater exclusively for Indie Games and end discoverability woes for the community.

Therefore, year 2012 appeals to the future of the Microsoft Indie gaming scene compared to alternative Indie Games distribution channels.