Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have a very basic game loop whose primary purpose is to check for updates & changes to a list.

I have contemplated using event driven programming to replace the game loop/list idea with an ObservableCollection, however I just have this big cloud of doubt on event driven programming. I'm posing these questions to those with experience with event driven programming:

  1. What are good ways to test & build an event driven programming design?

    That is, how will I know that I cannot run into "a sequence of unfortunate events"? I want to avoid the events I didn't plan for.

  2. Are there unit tests schemes to test event driven programming?

Because I have little reputation at the time of asking this question, I can't post more than two links: Observable collections are found at:

http://msdn.microsoft.com/en-us/library/ms668604.aspx

share|improve this question
add comment

2 Answers

up vote 4 down vote accepted

I will leave aside the wisdom (or not) of this particuar design for a game engine, I will address the core concern about the testability of event-driven designs.

When you state

I want to avoid the events I didn't plan for.

I presume you mean a sequence that you did not plan for, like Create/Delete/Update instead of the expected Create/Update/Delete, where the former might try and update a non-existant object and therefore crash or otherwise fail.

The entire nature of event-driven programming has to actually presume a near-random order of events, and so effectively your pre- and post- conditions become very important. Since you cannot fully qualify the order of events, you need to be robust against accidental ordering. So long as your Delete leaves no stray pointers, then a delayed Update should unambiguously fail, or at least have some well-defined behavior.

As far as unit-testing goes, most of the common suggestions would still apply. Generate test cases for various boundary conditions, as well as common cases to try and achieve appropriate coverage and interaction testing.

Perhaps in your game, I should be able to PickUp an item, which would add it to my inventory. If I attempt to PickUp an item, which was just destroyed for some reason (perhaps an ogre stepped on it), I should not somehow get an undamaged object due to a race condition. Either I got the object before it was crushed, or it is now gone, but nothing inbetween. If each event is atomic with respect to game state, then you won't get a partial object someplace it should not be.

Good Luck

share|improve this answer
    
you presumed correctly, i.e. "sequence that you did not plan for, like Create/Delete/Update...". because of this post, I'm thinking about leaving my game loop idea in place. –  Maelstrom Yamato Feb 12 '13 at 19:38
    
if you don't mind, please share your thoughts on a game engine. –  Maelstrom Yamato Feb 12 '13 at 19:49
    
Consider reading the original REST paper - a robust event system can take advantage of concept like statelessness of the messages and idempotency. –  ptyx Feb 12 '13 at 21:36
    
@ptyx do you have a link to the REST paper? –  Maelstrom Yamato Feb 14 '13 at 15:31
    
add comment

I used XSLT as a general purpose programming language for 6 years at work. XSLT is not exactly "event" driven, but it is input-driven - meaning that there is no pre-defined order of execution or limited number of paths that the execution of the code can take. Rather, each node in the input data tree triggers some code to be executed. It's totally data driven, which I imagine is similar to your event-driven model.

Anyone who has spent a few years writing software for a large organization knows that there is no end to the variety of data that gets into big systems. Every time you account for one condition, a new one pops up that no-one ever imagined. When your input data defines the order of execution of your code, then the paths you need to test are equal to the total number of data conditions that your code can be exposed to - a number which grows daily. The people using XSLT to write batch data crunching processes would be paged repeatedly at home, at night, pretty much every night as new data conditions were "discovered" by the program.

When you let your data drive your software, you will often run into a "sequence of unfortunate events." Fault tolerance is a big deal. Emergent behaviors rule the day. Limits are your friends. Obviously for a game universe to feel real, the fewer limits, the better. You must choose your limits very wisely. After all, a game is art, and an important part of any artistic statement is its limits.

Speaking of art, John Cage wrote a piece of music, "Four minutes and thirty three seconds" where the performer sits, making no sound, for that length of time. The point of this artistic composition, as far as I'm concerned, is not the picture, but the frame. Everything has limits. You are making a game about one thing, not another thing. It is one game, not another game. The better you can choose limits, and the more appropriate those limits are for your art/game/project, the easier it's going to be, and the better the experience will be for your users/gamers.

All software (like all music and art) has limits. Choosing those limits wisely may be the single most determining factor of the success of any software design. But with event- or data-driven programming, this is perhaps even more critical, if such a thing is possible, because every bit of non-essential flexibility that you allow in such a system will punish your development team with bugs and unimaginably complicated testing. First make as many limits on your event-driven system as possible, and only remove or extend a limit when doing so has a major, positive effect on the system as a whole.

Unit testing (generally black-box testing) usually takes the form of, "given certain inputs, does the software being tested return the expected outputs." For a very versatile event-driven system, you need a lot of variety in those inputs. Maybe you could capture all the interesting kinds of input data that you've seen in your game so far and make tests from those. Maybe you can add a new test whenever you encounter a new and interesting data condition. But with a sufficiently complicated system, there is no way to test every data condition, only the currently known conditions.

Maybe it would be good to build that kind of sanity testing (bounds-checking, things null or not null, no exceptions, etc.) into some sort of logging utility that would alert you when your method sees something new in the wild?

Hopefully a statistician will answer your question too and tell you how to cover a high percentage of the possible data conditions in a meaningful way. But until then, choosing the limits of your data- or event-driven software wisely is the only way I know to control the complexity of a meaningful set of unit tests.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.