Wednesday, May 30, 2007

"How to Keep Your Code From Destroying You"...or not

Slashdot's carrying a link to an article called How to Keep Your Code From Destroying You by Jeff Vogel, the summary of which is:

  1. Comment code
  2. Use constants
  3. Use descriptive variable names
  4. Include error handling
  5. Don't optimise until you've found you need to
  6. Favour clearness over cleverness
Tips which are valuable to developers just starting out more than anything. Any developer who's been even slightly mentored will know these instinctively anyway.

But I'm afraid I really have to disagree with the remark about comments. Some circumstances will of course require the odd comment around it, but if a chunk of code requires a comment at such an in depth level, then the code needs to be refactored.

Take this example of Jeff's:
// This procedure moves the bullet upwards.
// It's called NUM_BULLET_MOVES_PER_SECOND
// times per second. It returns TRUE if the
// bullet is to be erased (because it hit a
// target or the top of the screen) and FALSE
// otherwise.
Boolean player_bullet::move_it()
{
Boolean is_destroyed = FALSE;

// Calculate the bullet's new position.
[Small chunk of code.]

// See if an enemy is in the new position.
// If so, call enemy destruction call and
// set is_destroyed to TRUE
[small chunk of code]

// See if bullet hits top of screen.
// If so, set is_destroyed to TRUE
[Small chunk of code.]

// Change bullet's position.
[Small chunk of code.]

Return is_destroyed;
}
Some points on this:
  • Those "small chunks of code" preceded by the comment are clear candidates for being moved into their own methods
  • A description of a method is fine, but why comment on where it is used? I doubt this comment will be updated when the method is used elsewhere
  • If a method requires a lengthy comment like this it's named incorrectly or is doing too much. Call the method MoveUp() if it's moving the bullet up the screen.
At Esendex we rarely find the need to comment at such a detailed degree. Comments just aren't updated when new functionality is added for one, and if code can be self-documenting, then so be it. It may only take a minute to add a comment, but if you've already written the code that says what it does, then it's a minute saved.

If you've got a method called "CreateAndPersistCustomer" that returns a Customer object, then it's pretty obvious that the method will instantiate a Customer object, persist it, and return the object it's just persisted. The only worthwhile comment I can see that could be added to the top of this method is possibly a note on where it is being persisted, but this itself becomes redundant if your system only persists to one place.

I take exception to comments such as "This method will create a customer and then insert it into the Customer table. It returns the customer that has been inserted". It's pointless if your naming conventions are any decent.

There's feedback in the Slashdot article that points to this code file as an example of when code really needs a comment. But I have to disagree here for the most part as well.

It's fine putting comments around bitwise operations such as shifts and the like, but when you've got a comment on a function that says "Updates that pad's states according to event inputs", then surely you're just masking unnecessary code complexity with comments. Why not call the function UpdatePadState?

It's sort of a tradition in C to have obscure type names, but don't compound that fact by needlessly adding your own. Code with a variable called dInt won't compile or run any faster than if you call the same thing directionIndicator.

Have meaningful names for everything. If you want to create a class (or unit, or whatever your programming language calls an encapsulation of something) that models a game pad, for god's sake call it GamePad. If that object needs a property to get the last event then call it LastEvent. Anything else is just being lazy.

Self-documenting code is clean and easy to maintain. My personal view is that if someone has to rely on reading comments, and can't read the code itself then they have no business updating it. If you don't know the difference between i++ and ++i, then get back to school and don't come back until you're qualified.

Comments will always have their place, but don't use them when refactoring your code will make more sense. Comments won't stop you duplicating code, refactoring will. Commenting a chunk of code doesn't make it usable from another method--moving that code into its own method will.

So the next time you're about to write a comment just think to yourself (or say aloud to your partner if you're pair programming) "Why do I need a comment here?".

Think of ways in which you can name your methods, variable names and classes so you negate the need for lengthy comments. Save your comments for the complicated bitwise operations, complex predicate logic and the like--places where you really do need to comment.

Don't comment the top of methods when you could just name the method differently and make more sense to everyone.

Monday, May 28, 2007

Introduction to 3D in XNA

For my next XNA project I think I should move into 3D. The Spacewars starter kit still looks complicated but I think I've come up with a game idea that can make use of 3D while still being relatively simple to visualise.

I'm not certain of this idea so won't go into detail yet, but I will need to figure out how to place models in the world and move the camera for any 3D game to work.

I've found an introduction to 3D models in XNA, and an introduction to matrices that should help somewhat. I've managed to render one of the Spacewars models into the game and can move the camera around in the way that I want.

Now I need to get the model moving based on mouse input. Oh, and get some 3D models to display in the actual game. I've found Turbo Squid, but what I've found on there can't be imported into XNA and need to be opened in 3D modelling software, which I don't have.

Does anyone have any recommendations as to some free software I can use that will let me create my own 3D models?

Thursday, May 24, 2007

First Stab at Pong in XNA

Pong was probably not a great choice as an ongoing XNA project after all. I know what I said about the possibility of adding different features, but Pong doesn't really offer itself up as an interesting game that is going to be able to grab my attention for long enough to make something more of it.

So for now I'm done with it I think. It's playable, and relatively challenging. It keeps score and certainly looks quite retro in its black and white styling, but doesn't really do much else right now.

UPDATE: Changed the download location to something I have control over :)

For the time being you can download the code for the game if you want. Please read the readme.txt file as it explains a few things.

And please excuse my lack of knowledge when it comes to free file hosting, I just wanted something quick so I could upload the zip file. I might put the file somewhere else in the future.

I know that Ziggy wanted to download my first card game too, and I'll try to get that uploaded over the weekend.

But for my next project I think I'll try something new, no more copying existing games.

Wednesday, May 23, 2007

Documenting Enum Values

If you maintain a codebase that is of any decent size, chances are you'll have defined a fair few enum types. You may also need these types and their values to be documented somewhere, as not everyone who needs them could have access to the code where they are defined.

You could of course do this manually, but if you already have lots of types this could be tedious. Luckily its quite simple to write something that will do this for you.

The code below takes a parameter for the assembly path and name, and writes the values to the Console.



private static void DumpAssemblyEnums(string assemblyPath)
{
StringBuilder builder = new StringBuilder();

// flag to check if we should put the string we
// create into the Console output
bool hasEntriesToShow = false;
try
{
builder.AppendLine(string.Format("===== {0} =====", assemblyPath));

// load assembly from the path
Assembly assembly = Assembly.LoadFrom(assemblyPath);

// get the types from this assembly
Type[] assemblyTypes = assembly.GetTypes();

for (int i = 0; i < assemblyTypes.Length; i++)
{
try
{
// check if the type is an enum
if (assemblyTypes[i].IsEnum)
{
hasEntriesToShow = true;

// output the full type name of this enum
builder.AppendLine(
string.Format("==== {0} ====",
assemblyTypes[i].FullName));

// get the values for the enum type
Array array = Enum.GetValues(assemblyTypes[i]);

// loop through the array
for (int j = 0; j < array.Length; j++)
{
// output the numeric value by converting to a
// long
// use long as enum values can be larger than
// an int
builder.AppendLine(
" " + Convert.ToInt64(array.GetValue(j)) +
" = " + array.GetValue(j).ToString());
}
builder.AppendLine();
}
}
catch (Exception ex)
{
// output any error
builder.AppendLine("**ERROR: " + ex.Message + "**");
}
}
}
catch (Exception ex)
{
// output any error
builder.AppendLine("**ERROR: " + ex.Message + "**");
}

// push to Console stream if we've got something to show
if (hasEntriesToShow)
Console.Write(builder.ToString());
}



You can call this directly, or use a directory traversal to output all enum values in all assemblies in a directory.

This example will output into a format which can be used on a Wiki page, but you can edit it to output in any format you like.

Posting Code on blogger.com

Wish I'd known how to post code on this blog before. I've manually spaced code out before, and it was so tedious it took multiple tries as I just go so bored with it.

Thanks Neil

Tuesday, May 22, 2007

Set LocalEndPoint in UdpClient

I haven't done that much work using UDP as a protocol, most of the time I'm lucky enough to use TCP. Now some work has called for UDP to be used, and we're currently just figuring out how to use it.

Each UDP packet will have a source and destination port, and if the receiver needs to send a response then it will send it to the source port specified in the original packet.

The default constructor for the .Net UdpClient assigns a value for this port for you, which is OK if you don't need a response, but if you want a separate process to handle the response then you need to use a different constructor to specify a port value and/or address.

Use UdpClient(Int32) to just set the local port value, or UdpClient(IPEndPoint) to set address and port values.

A Packed Tech Ed Schedule

After reading a few tips for Tech Ed first timers I went back to the schedule builder and started to select every session that looked interesting, both for myself and for Esendex. Adam's given me a few pointers for some potentially interesting sessions too.

I've now got a schedule where pretty much every time slot is filled, and most are filled with more than one. I've got a choice of about 4 at one time in places. Tuesday is looking particularly busy.

I was going to post the schedule I had, but I don't really have time right now to copy the sessions I've got planned. If anyone knows of an easy way to publish or save these sessions then let me know.

Thursday's 4.30pm session should be interesting too: "DEV344 Microsoft XNA Game Studio Express: Creating Your First Microsoft Windows and Xbox 360 Game".

I've already created my first XNA game, and am well on the way to my second, so maybe I won't learn much. But the session is rated as a 300 difficulty, which should mean that it's more advanced than just an introduction.

Monday, May 21, 2007

First Timers at Tech Ed

In two weeks time I'll be in Orlando at Tech Ed 2007. It's the first time I've been so I'm grateful to others who have taken the time to write about how to work through it, notably Scott Dorman's Tech Ed for Novices.

I've nearly completed my schedule builder, but I have tried to keep 1 session in 1 time slot, which Scott says is a mistake. So I'm going to select all the sessions I think look interesting and decide on the day.

Also intriguing is the mention of Blue Casting at the Convention Center. I'm wondering what kind of "stuff" Microsoft is going to send to my phone...

Friday, May 18, 2007

SMS Dead? Don't think so

Roland's blogging about SMS being dead on the basis that "a well funded startup like Twitter which is full of smart people can't get SMS to scale".

I don't really know where he's coming from basically. Is this just an American feeling? I know the US has been slow to take up SMS, and that is because of the carriers over there, but in Europe and over here in the UK SMS is the way to communicate.

There have been some posts in response to this already, and I couldn't agree more with some comments made. If Twitter can't scale their own systems, then that's Twitter's problem, not SMS as a technology. Twitter developer Alex Payne admits that Ruby on Rails makes it difficult to scale the web application, but makes no mention of limitations of SMS.

Twitter and other sites have had security problems with SMS but these have been misuses of SMS, not SMS itself. Likewise, the Australian Bopo card has potentially the same problem, but again, this is not a problem with SMS.

These problems have come about from people implementing SMS solutions without knowing all they need to know about SMS in the first place.

Anyone who's read this Letter to American Execs should surely understand how far behind Europe America currently is with SMS.

SMS is quick and discreet. Email is ignored or deleted. Phone calls are too direct and intruding for many things, and IM is too.

SMS is not dead. Esendex has customers worldwide, and we send millions of messages a month on their behalf to prove it.

ASP.Net AJAX v1.0 Versioning

One of the reasons behind migrating to the .Net 2.0 Framework was to allow us to use more of the newer features of ASP.Net, such as AJAX. We've been trialing a few AJAX features, such as the AutoCompleteExtender, and was happy with the tests on one development machine so tried to build on another one to do some work in parallel.

Everything went OK until we got to the new page and got a Parser Error saying that the ScriptManager "does not have a public property named 'EnablePageMethods'." The same code worked on another development machine.

The version numbers of the System.Web.Extensions assembly was the same on both machines: 1.0.61025.0, but we had the Release Candidate version of the System.Web.Extensions assembly, while the other machine had the full version--yet the version numbers of the assembly were exactly the same!

Installing the full version solved the problem we were having, but I can't figure out why those assemblies have the same version number! It was clear we had something wrong but discarded the possibility of a version mismatch because the version numbers were the same.

Not the easiest of problems to resolve, but we're moving forward now

Wednesday, May 16, 2007

Time For a New XNA Project

Well I've finished what I'm doing on my first card game in XNA. I'm not claiming it's a fun game, or that playable, but it has rules, 2D sprites, mouse control, scoring, and a win condition.

Now I want to move on to something with a little more action. I still think that the Spacewars 3D project is a little beyond me right now though. I've gone through the video tutorials and followed them so I can move a 3D model on the screen, but I've yet to get the 3D co-ordinate system straight in my head and can't quite visualise it enough. I'm sure that will come in time though.

I'm not going to be terribly original in my next game idea. It seems everyone needs to write a version in XNA: like a rite of passage or something. I am, of course, talking about Pong--that age old game from the 70s that started it all.

It's an advance on my card game because (among other things) it's 2 player, it has moving sprites on screen, I'll need to detect collisions between bats and ball, and it contains some rudimentary physics to calculate how the ball should bounce from the bat and walls.

It also has plenty of opportunities for additions later. I could:

  1. add AI to make it a single player game
  2. add network play (I have no idea if XNA helps with this at all)
  3. have a 4 player version with 2 bats on either side for a doubles game
  4. allow the bats to be moved left and right instead of just up and down
  5. allow players to set colours and control preferences

So it should be more of a real game. Certainly seems more substantial than a card game which I could really have written as a standard Winforms application.

Maybe after this I could create a 3D Pong. I know its been done before as well (I think the version on kontraband.com is highly addictive), but it might be an easier starting point than the full Spacewars project.

Tuesday, May 15, 2007

"Scratch" Me Some Code

The most emailed story on BBC News at this moment in time is about Scratch:


A free programming tool that allows anyone to create their own animated stories, video games and interactive artworks


I mean to take a look at this a little later on, but the signs are encouraging. There's a danger with programming that as developers need languages to do more and more, then that language will become more and more complicated to learn.

My sister's a teacher, and I can remember her asking if I knew of anything that might make teaching IT more exciting. I couldn't think of anything at the time that would be simple enough for a class of eight year olds, but maybe Scratch is what I was looking for.

Having a language such as this that (at first glance) doesn't seem to require people to type that much, can only really be advantageous to the industry. It's likely to get kids interested in programming from a young age.

The danger with simplifying programming is that it can let you develop bad habits, but Scratch seems so far removed from the actual coding process that its unlikely that this will happen.

Hopefully kids won't get the impression that programming is as simple as point and click though, as they're in for a shock if they do :)

Monday, May 14, 2007

Comments on the Esendex API

Had a nice comment left through Esendex's Contact Us page today:

Can I just say that as a new user/developer of the Esendex APIs that they are, without doubt, THE most comprehensive and easy to use (from Visual Basic) that I have worked with. Totally hassle-free.

Well done, keep up the excellent work.

I can't say I've personally worked that much on the VB SDK, but all kind words about the Esendex systems are more than welcome.

People are very quick to criticise when things don't go as they expect, but not many people take the time to give praise when something turns out well.

Thanks!

Friday, May 11, 2007

Auto Updates of Desktop Applications

I guess it's a sign of the times that the vast majority of customer facing software development I have done since leaving university has been ASP.Net web applications. For all the pitfalls of this environment what is great is the level at which you can update it live.

The Esendex Web/Email/API front end all runs from a web farm, so we have multiple servers feeding the same information through a load balancer. This means when we update we can safely remove a server from that array, update it, and put it back--and no one sees any downtime.

Recently though I've been delving into writing desktop applications for a project that I'm not at liberty to fully divulge at this moment in time. However, what I can say is that this application needs to be able to update itself in a number of ways.

This application gets its functionality primarily from plugins, which are loaded at runtime from a directory on the user's computer. This makes the "host" application relatively dumb, and I've spent a fair few hours getting these plugins loaded in an easy to manage way.

That is now all working and today I've managed to get a first pass at automatically updating the plugins. Well, I guess "automatic" is pushing it a little at this moment in time, but eventually the application will periodically ask for available updates and then go through the process which is currently being kicked off by a menu item click.

The main problem is that you can't update a file that is currently being used, which means the update procedure can't complete while the application is running. Applications like the Firefox browser appear to solve this by finalising the installation when the application restarts.

The current pass of the update manager works in this way, and I can't see a way around it at the moment. This is fine for the plugins that are being loaded--we can just finalise the update process of the plugins before we load them. The problem is, how do you update the main host application that is loading all the plugins?

It seems the only way is to create a second application which has the sole task of finalising updates, and then kicks off the main EXE that can be updated as part of the main updating process along with the plugins.

Of course, this raises the question of how do you update the "loader" application, but I guess if this app is simple enough that won't need to happen that much. Although, the main application could update the loader, as by the time that is running the loader should have quit.

An additional task of this updating process will also need to notify the end user of any new plugins that are available for their particular application. I think that this will have to be a separate process though, although it will probably use the same design patterns as what I've got at the moment.

The hurdle we need to get over though is that we won't have any control whatsoever over this install and update procedure, and that is quite a big hurdle. This is run of the mill stuff to those developers who write desktop apps day in day out, but as a service provider of online applications it's going to be a step into the unknown.

I've always been a subscriber to the "It Just Works" school of thought when it comes to software development, but that is easier to accomplish when you have full control over where it's running and how it's deployed. This desktop application needs to be able to hold its own across a variety of PC setups, and that will require a lot of testing before it's released.

I think I can recall only one instance of Esendex releasing a limited Beta to customers during my time here. This might have to be the second. :)

Thursday, May 10, 2007

Technorati Profile

I've just "claimed my blog" on Technorati.com. Check out my Technorati Profile

Tuesday, May 08, 2007

Tech Ed 2007 Schedule

Got sent a link to all the sessions that are being covered at Tech Ed 2007, which I'm lucky enough to be going to in June.

Literally hundreds of sessions, I have no idea which ones to attend. To limit it I've asked my boss to point at the ones he wants me to go to, but that will still mean having a lot to choose from.

What I would like to look at is the Windows Communication Foundation. I'm pretty sure it's .Net 3.0 only, but the jump from .Net 2.0 to 3.0 shouldn't be as difficult as the one from 1.1 to 2.0. Well, we can hope anyway :)

I'll post later in the month when I've got the sessions I'll be hoping to attend.

XNA Mouse "Clicks" Update

Zygote's made an interesting point in my previous post about changing the way I detect a click. It certainly would make more sense to detect a "click" as when the state goes from Released to Pressed, rather than Pressed to Released which I have now.

This more accurately detects a "MouseDown" event that will make the interface more responsive.

Thank you!

XNA Mouse "Clicks"

So I've been carrying on with my card game in XNA. I've created some crude textures for the empty card "slot" and managed to find some pictures of playing cards online that I can use for the card faces.

One of the first things I did was sort out all the back end stuff (like shuffling the deck, dealing a card, etc.), I just needed to capture a mouse click on an empty card stack and deal a card.

But when it came to detecting the mouse click I was surprised that not 1 card was dealt when I clicked a card stack, but pretty much half of the deck.

I was using the Mouse.GetState method to check if the LeftButton was Pressed. As this was happening in the Update loop the game was looping around multiple times for as long as I kept the mouse button down.

Pressed really does mean Pressed.

So now I'm storing the previous state of the mouse, and only when the LeftButton state goes from Pressed to Released do I count a click.

EDIT: Detecting Pressed to Released models a "MouseUp" event, and while this may be useful in some situations, in this game a "MouseDown" would make more sense. To detect a MouseDown you count a click as the state going from Released to Pressed.

Now I just need to implement the rules of the game, and some scoring mechanism so scores can be compared.

Friday, May 04, 2007

XNA Resources

Mykre's been kind enough to send over a couple of links to easily show the mouse pointer in an XNA game. I knew I had seen the IsMouseVisible property somewhere but couldn't find it again when I needed it. Seems so obvious that it would be there now...

The links are in the comments for my XNA Mouse and Sprite Tests posts, but for ease of use here they are again:

Thanks Mykre

XNA Mouse and Sprite Tests

Played around with XNA last night again. For the card game I need to be able to display cards on the screen and click a stack of them to deal another card onto it.

So there's two basic things there that I need: display cards, and control the mouse.

I just followed the example for How To Draw a Sprite and I think that this will be all I need to draw cards to the screen. I'm pretty sure I know how to use the SpriteBatch and Texture2D classes now, but whether or not I'm using them correctly is another thing. All I can say is, I followed the examples and it works.

So I looked into showing the mouse pointer. I found a good article about encapsulating the mouse functionality into a class, and I'll probably follow this to tidy up my code, but for now I've just put that in my main Game class.

So I drew a pointer in MSPaint and used that as my cursor. I don't have the DirectX SDK yet (couldn't be bothered to download it last night), so the pointer isn't masked in the way that is described. It looks a little odd having a block of white surrounding the pointer, but for a proof of concept it's fine.

It struck me as odd that there wasn't a simpler way to show the mouse. Maybe there is and I just haven't found it, but then I though that the way I'm using is very flexible. It gives me full control of when I show the mouse, and I can update it only when I need to. Why have needless processing of the mouse when you're in a section of game that doesn't require it?

So for now I've got a random card showing on my screen (which I can show in full screen mode and at a really nice resolution, but that's another story), a pointer on the screen, and a continuously updating line of text which tells me where the pointer actually is.

I'm still a long way from a playable game, but I think I'm beginning to get the basics.

Wednesday, May 02, 2007

XNA Game Studio Express

I tried XNA Game Studio Express when it was still in Beta, but at the weekend I thought I'd try the one that has actually been released. If you don't know what I'm talking about then I guess a quick introduction would be that XNA is a framework for creating games in .Net, and Game Studio Express is an addon to Visual C# Express that lets you create games.

It's all free, so go and download it if you want to try it.

So I went through the 2D tutorial, which teaches you how to display a sprite on the screen and get it moving. That was pretty easy to do, but you're not left with much of a game--more a screen saver of a picture bouncing around your screen.

I tried some of the additions described at the end of the article, and although it was pretty cool adding mouse support to throw the picture around, it still wasn't much of a game.

So I went onto the next tutorial, which was creating a 3D game. And talk about being thrown in at the deep end! The learning curve between the two examples is pretty steep, and I don't have the time to go through it to figure it all out.

So I've settled for a middle ground. I'm going to try and create a 1 player card game based on a game my parents taught me years ago. It's got quite simple rules, and will have simple graphics too, but at the end I hope to have an actual playable game.