Posts Tagged ‘Language Agnostic’

Putting Your Best Font Forward

No, the Horseman isn’t about to give you a lesson in typography (like traditional graphic design, it’s not exactly his forte). What the Horseman does intend to do however, is extol upon you the benefits of selecting the correct font for coding.

FlashDevelop is an incredible ActionScript IDE with very few things I feel left to be desired (linting, possibly… but Eclipse’s linting is just as bothersome as it is helpful so I’m on the fence here). The biggest problem I have with FlashDevelop is a flaw that is not unique to it but is shared by virtually every code editor I’ve used.

The default fonts are horrible.

In FlashDevelop and Eclipse both, the default font manages to break a cardinal rule of good programming typography. It’s difficult to distinguish at a glance the difference between 1, l, | and 0, O. Beyond that though, I just find the typefaces to be… clunkysuffocating, even.* I honestly never knew just how suboptimal the default fonts were for these editors until I stumbled across a discussion about a programmer’s font choice several years ago. That’s when the Horseman leapt upon his black stallion and sallied forth in search of a better font, to see just whether there was anything to this notion. After finding several worthy candidates, I finally settled on a font family known as Proggy. The creator wrote a short description of the thought process and design choices he made when designing Proggy, and I think he succeeded rather well.

Aside from the obvious benefits of total disambiguation of glyphs, the font has a “feel” and “flow” that work well to help me follow easily along with what’s on the screen. It bolds well, it italicises well, and the center-aligned operator symbols stand out clearly and distinctly. No dot operators being subsumed here! The font size works well for me too, hitting a sweet spot that the default fonts can’t quite manage to occupy in terms of letter spacing or line spacing.

The author is a C++ programmer, but Proggy certainly works wonders for ActionScript and thusfar as well for Java (and yeah, for XML as well).

So, one of the first thing I do these days when setting up a new IDE is to seek out Proggy and install my favorite of the variants (currently Proggy Clean). Maybe Proggy isn’t the font for you, but it’s almost certain that somewhere out there is a better font than the one your IDE uses by default. Taking some time to find it will pay dividends as you suddenly find your code easier to read. As I’m sure you know, code is frequently a “write once/read many” type of occupation, and anything that aids the reading aspect carries an unusually large boost to your productivity and peace of mind. Imagine all the hours you’ve spent on debugging that came down to stupid typos in a section of the code that can’t offer intellisense, and then imagine how many of them you’ll never lose again once your font is finally helping you.

 

 

* Not an exaggeration. While working with a default font-set, before actually realizing that the font was a default, I had this unshakable sense of tension that abated only upon seeing a friendlier typeface. I had no clue that I was barely breathing until I took a huge gasp of air after finally seeing my code look “right” again.

 

 

Tags: , , ,

4 Comments


Knock Down The If-ful Tower

Novice coders, as well as intermediate coders who are simply in a rush often end up with code structures like these:

public function importantLogic(player:Player):void {
 
	if (player.isMoving) {
		if (player.isJumping) {
			// do something with player...
			//...
			//...
		}else if (player.isAboutToJump) {
			// do something with player...
			//...
			//...
		}
	}else if (player.isCrouching) {
		// do something with player...
		//...
		//...
	}else if (player.isAboutToMove) {
		//...
		//...
	}else if (player.isAboutToJump) {
		//...
		//...
	}
 
 
 
}

I call these structures “If-ful Towers” (pronounced like “Eiffel Towers” without the leading “E”). Obviously there is nothing wrong with the humble if-else statement, or its cousin if-else-if. Our code would hardly work without branching logic, after all. One of my co-workers and I were talking about this sort of structure and how it’s highly indicative of the “Broken Windows” syndrome discussed in “The Pragmatic Programmer“. How do you maintain code that is structured this way? It already looks imposing, and there’s not even any real code written in the blocks.

If you look closely at this particular code snippet, you’ll notice that we’re testing the state of the Player instance. The Player clearly can exhibit a great number of states. Most of them are simple boolean properties. Many of those properties are mutually exclusive. Who knows what sort of havoc could happen if somehow the player thinks that it isMoving, and isCrouching, and isJumping, and isAboutToMove all at the same time? Couldn’t we knock down the If-ful Tower if we were to just be a little smarter about how we determine the state of the Player?

package {
 
	/**
	 * ...
	 * @author The Horseman @ Scriptocalypse.com
	 * 
	 *   Here we have a base class for a certain set of actions to perform.  
	 *   We can create many different subclasses, such as....
	 * 
	 *       WalkingContext
	 *       CrouchingContext
	 *       JumpingContext
	 */
	public class Context {
 
		public function Context() {
 
		}
 
 
		// override in your subclass...
		public function execute(player:Player, foo:*):void {
			// player is the Player object.
			// foo is some data that player should be concerned with.
		}
 
	}
 
}
 
 
 
 
 
// And here's the very basics of Player...
package {
 
	/**
	 * ...
	 * @author The Horseman @ Scriptocalypse.com
	 * 
	 *   The player has a context that is called upon to execute
	 *   on command.  Since there is only one context active at
	 *   any given time, we can be assured that as long as we 
	 *   supply the *one* correct context that the action taken
	 *   will be expected and desired.
	 * 
	 */
	public class Player extends MovieClip{
 
		private var _context:Context;
		public function get context():Context{
			return _context;
		}
 
		public function set context(value:Context):void{
			_context = value;
		}
 
 
 
		public function Player() {
 
		}
 
 
	}
 
}

Now it is completely unambiguous precisely which “state” the Player instance happens to be in at any given moment. There can be only one! As long as you have correctly assigned the context, simply calling upon it to execute should be all you need to do. Where once stood the If-ful Tower, we now have this:

public function importantLogic(player:Player):void {
 
	// That's it.  
	player.context.execute(player, 10);
 
 
 
 
}

Wow. Things just got a lot more readable in this code block. This is of course not the only way to knock down the If-ful Tower, and depending on your circumstances there may be better ways. Indeed, the player doesn’t necessarily need to have a reference to the Context object. That could perhaps be stored elsewhere, and simply accessed when needed.

Perhaps you need to implement collision handling between Player and an Enemy? It’s probably tempting to just build up yet another If-ful Tower replete with deeply nested logic and branches… but that’s a tower to topple another day!

Tags: , ,

2 Comments


At the Logic Gates

How many times have you found yourself with a tangle of code that looks something like this?

/*
While the code is in ActionScript 3, it could easily 
be something you've seen in the likes of Java, C#, 
or almost any other similar language.
*/
 
package  {
	import flash.display.MovieClip;
	import flash.events.Event;
 
	/**
	 * ...
	 * @author The Horseman @ Scriptocalypse.com
	 */
	public class UtterMadness {
 
		private var bugsDance:Boolean = false;
		private var voiceOverCompleted:Boolean = false;
		private var fireworksExploded:Boolean = false
		private var bannerSign:MovieClip;
		private var youWinClip:MovieClip;
 
		public function UtterMadness() {
			this.playVoiceOver();
			this.makeBugsDance();
			this.shootFireworks();
			this.unfurlBannerSign();
		}
 
		private function onBugsDanceComplete(e:Event):void {
			bugsDance = true;
			if (bugsDance && fireworksExploded && voiceOverCompleted && bannerSign.currentFrame == bannerSign.totalFrames && youWinClip.currentFrame == 1) {
				youWinClip.gotoAndPlay("win");
				bugsDance = false;
				voiceOverCompleted = false;
				fireworksExploded = false;
				bannerSign.gotoAndPlay("goAway");				
			}
		}
 
		private function onVoiceOverComplete(e:Event):void {
			voiceOverCompleted = true;
			if (bugsDance && fireworksExploded && voiceOverCompleted && bannerSign.currentFrame == bannerSign.totalFrames && youWinClip.currentFrame == 1) {
				youWinClip.gotoAndPlay("win");
				bugsDance = false;
				voiceOverCompleted = false;
				fireworksExploded = false;
				bannerSign.gotoAndPlay("goAway");				
			}
		}
 
		private function onFireworksExploded(e:Event):void {
			fireworksExploded = true;
			if (bugsDance && fireworksExploded && voiceOverCompleted && bannerSign.currentFrame == bannerSign.totalFrames && youWinClip.currentFrame == 1) {
				youWinClip.gotoAndPlay("win");
				bugsDance = false;
				voiceOverCompleted = false;
				fireworksExploded = false;
				bannerSign.gotoAndPlay("goAway");				
			}
		}
 
		private function onBannerSignComplete(e:Event):void {
			if (bugsDance && fireworksExploded && voiceOverCompleted && bannerSign.currentFrame == bannerSign.totalFrames && youWinClip.currentFrame == 1) {
				youWinClip.gotoAndPlay("win");
				bugsDance = false;
				voiceOverCompleted = false;
				fireworksExploded = false;
				bannerSign.gotoAndPlay("goAway");				
			}
		}
 
	}
 
}

Sometimes, you need to make certain things happen as a result of some action or event in the program. In this hypothetical scenario, we have a MovieClip in the “youWinClip” variable that we’re clearly very interested in playing, but only if the following conditions are true:

  • Some Bugs on the screen have danced.
  • Some voice-over has completed playing.
  • Some fireworks have gone off.
  • The “bannerSign” MovieClip is on its final animation frame.
  • The “youWinClip” is not already playing (let’s assume that’s what was meant by currentFrame == 1

So our solution up above is fine and dandy for now, if a bit verbose and repetative. Let’s expand on this, though. What if you’re working for a client who decides that there need to be more conditionals? Like for example, somewhere in the middle of all this mess they want you to set up a listener for a boulder tumbling down the hillside, which may or may not happen before or after anything else. But before you can do any of this, they add a requirement that the “youWinClip” must only play every 3rd time that all the previous requirements have taken place.

So you add some more code to this class and it looks something like the following:

package  {
	import flash.display.MovieClip;
	import flash.events.Event;
 
	/**
	 * ...
	 * @author The Horseman @ Scriptocalypse.com
	 */
	public class UtterMadness {
 
		private var bugsDance:Boolean = false;
		private var voiceOverCompleted:Boolean = false;
		private var fireworksExploded:Boolean = false
		private var bannerSign:MovieClip;
		private var youWinClip:MovieClip;
		private var boulderRolled:Boolean;
		private var numberOfTimeConditionMet:int = 0;
		private var maxTimesToMeetCondition:int = 3;
 
 
		public function UtterMadness() {
 
		}
 
		private function onBugsDanceComplete(e:Event):void {
			bugsDance = true;
			if (bugsDance && fireworksExploded && voiceOverCompleted && 
				bannerSign.currentFrame == bannerSign.totalFrames && 
				youWinClip.currentFrame == 1 && boulderRolled) {
 
					numberOfTimeConditionMet++
					if(numberOfTimeConditionMet == maxTimesToMeetCondition){
						youWinClip.gotoAndPlay("win");
						bannerSign.gotoAndPlay("goAway");	
						numberOfTimeConditionMet = 0;
					}
					bugsDance = false;
					boulderRolled = false;
					voiceOverCompleted = false;
					fireworksExploded = false;
 
			}
		}
 
		private function onVoiceOverComplete(e:Event):void {
			voiceOverCompleted = true;
			if (bugsDance && fireworksExploded && voiceOverCompleted && 
				bannerSign.currentFrame == bannerSign.totalFrames && 
				youWinClip.currentFrame == 1 && boulderRolled) {
 
					numberOfTimeConditionMet++
					if(numberOfTimeConditionMet == maxTimesToMeetCondition){
						youWinClip.gotoAndPlay("win");
						bannerSign.gotoAndPlay("goAway");	
						numberOfTimeConditionMet = 0;
					}	
					bugsDance = false;
					boulderRolled = false;
					voiceOverCompleted = false;
					fireworksExploded = false;
 
			}
		}
 
		private function onFireworksExploded(e:Event):void {
			fireworksExploded = true;
			if (bugsDance && fireworksExploded && voiceOverCompleted && 
				bannerSign.currentFrame == bannerSign.totalFrames && 
				youWinClip.currentFrame == 1 && boulderRolled) {
 
					numberOfTimeConditionMet++
					if(numberOfTimeConditionMet == maxTimesToMeetCondition){
						youWinClip.gotoAndPlay("win");
						bannerSign.gotoAndPlay("goAway");	
						numberOfTimeConditionMet = 0;
					}	
					bugsDance = false;
					boulderRolled = false;
					voiceOverCompleted = false;
					fireworksExploded = false;
 
			}
		}
 
		private function onBannerSignComplete(e:Event):void {
			if (bugsDance && fireworksExploded && voiceOverCompleted && 
				bannerSign.currentFrame == bannerSign.totalFrames && 
				youWinClip.currentFrame == 1 && boulderRolled) {
 
					numberOfTimeConditionMet++
					if(numberOfTimeConditionMet == maxTimesToMeetCondition){
						youWinClip.gotoAndPlay("win");
						bannerSign.gotoAndPlay("goAway");	
						numberOfTimeConditionMet = 0;
					}		
 
					bugsDance = false;
					voiceOverCompleted = false;
					fireworksExploded = false;
 
			}
		}
 
		private function onBoulderRoll(e:Event):void {
			boulderRolled = true;
			if (bugsDance && fireworksExploded && voiceOverCompleted && 
				bannerSign.currentFrame == bannerSign.totalFrames && 
				youWinClip.currentFrame == 1 && boulderRolled) {
 
					numberOfTimeConditionMet++
					if(numberOfTimeConditionMet == maxTimesToMeetCondition){
						youWinClip.gotoAndPlay("win");
						bannerSign.gotoAndPlay("goAway");	
						numberOfTimeConditionMet = 0;
					}	
					bugsDance = false;
					boulderRolled = false;
					voiceOverCompleted = false;
					fireworksExploded = false;
 
			}
		}		
	}	
}

Wouldn’t you say this is getting ridiculous? All this copy/pasting is becoming as tedious for me to execute as it is for you to read. Additionally, the more often you have to repeat yourself the more likely you are to make a mistake in your code. Just think of what might happen if you forgot to re-set boulderRolled in onBannerSignComplete. Oh wait, we just did! Have fun debugging that one.

Did I tell you there were more changes on the way? Yeah, the client has some more requests. You’ll have to fit them into that hornet’s nest somewhere. Hope you don’t mind poring over your wall of text for the next week… or is it month? Or year?

Maybe if you just move the on-true results of those checks to its own function, that will make things easier?

 
		/////////////////////////////////////////////////////
		// starting near the end for the sake of sanity...
		/////////////////////////////////////////////////////
 
		private function onBoulderRoll(e:Event):void {
			boulderRolled = true;
			if (bugsDance && fireworksExploded && voiceOverCompleted && 
				bannerSign.currentFrame == bannerSign.totalFrames && 
				youWinClip.currentFrame == 1 && boulderRolled) {
 
					numberOfTimeConditionMet++
					if(numberOfTimeConditionMet == maxTimesToMeetCondition){
						// move all this code to its own function.
						this.youWin();
					}	
			}
		}
 
		private function youWin():void {
			boulderRolled = false;
			youWinClip.gotoAndPlay("win");
			bugsDance = false;
			voiceOverCompleted = false;
			fireworksExploded = false;
			bannerSign.gotoAndPlay("goAway");	
			numberOfTimeConditionMet = 0;
		}

That does in fact help to solve the issue of having to re-initialize our booleans and play our “goAway” and “win” animations, but it’s still a great deal of copy-pasting. Also, you have to remember to account for each new boolean statement in every function as the client adds them.

I’m sure the electrical engineers in the audience, as well as honest-to-goodness CompSci majors are rolling their eyes right now. They see something blindingly obvious that we’ve missed so far. We’re in desperate need of a logic gate. What if we were to put some of this Object Oriented Programming to good use and make ourselves a nice little module that we can plug into our code any time we need to test the truth of a logic statement?

The last time you’ll see the boolean comparisons : In your logic gate
Edit: This approach is admittedly slightly ham-fisted.

package  {
	import flash.display.MovieClip;
	import flash.events.Event;
 
	/**
	 * ...
	 * @author The Horseman @ Scriptocalypse.com
	 */
	public class WinCondition {
 
		private var bugsDanceEvent:Event;
		private var voiceOverCompletedEvent:Event;
		private var fireworksEvent:Event;
		private var boulderRolledEvent:Event;
		private var bannerEvent:Event;
 
		private var numberOfTimeConditionMet:int = 0;
		private var maxTimesToMeetCondition:int = 3;
 
		public function WinCondition() {
 
		}
 
 
		// call this to determine whether it's okay to proceed.
		public function permission(e:Event, winClip:MovieClip):Boolean {
			var allow:Boolean = false;
 
			// string references to our properties...
			var events:Array = ["bugsDanceEvent", "voiceOverCompletedEvent", "fireworksEvent", "boulderRolledEvent", "bannerEvent"];
			// the expected event types we will encounter, mapped to the property references...
			var types:Array = ["danceType", "VOType", "fireworksType", "boulderType", "bannerType"];
 
			// eg: e.type == "VOType" will return an index of 1...
			var index:int = types.indexOf(e.type);
 
			// events[1] == "voiceOverCompletedEvent"...
			// therefore we're assigning to this["voiceOverCompletedEvent"]
			if (index >= 0) this[events[index]] = e;
 
			if (bugsDanceEvent && voiceOverCompletedEvent && 
				fireworksEvent && boulderRolledEvent && 
				bannerEvent && 	winClip.currentFrame == 1) {
 
					numberOfTimeConditionMet++;
 
					bugsDanceEvent = null;
					voiceOverCompletedEvent = null;
					fireworksEvent = null;
					boulderRolledEvent = null;
					bannerEvent = null;
			}
 
			if (numberOfTimeConditionMet == maxTimesToMeetCondition) {
				allow = true;
				numberOfTimeConditionMet = 0;
			}
 
			return allow;
		}	
 
	}
 
}

Notice how this new class “WinCondition” has precisely one function that returns a boolean value. Instead of keeping all the permissions code in the UtterMadness class, we’re keeping it in one place that will be unobtrusive, and easy to maintain. We don’t have to look at, think about, or care about any of that noise unless we specifically need to. I don’t know about you, but if I were to have to look at, think about, and otherwise be distracted by all that mess every time I wander through the class file for UtterMadness, I’m pretty sure I’d need some horse tranquilizers to keep my blood pressure in check.

Here’s what UtterMadness looks like with about 80% less madness

package  {
	import flash.display.MovieClip;
	import flash.events.Event;
 
	/**
	 * ...
	 * @author The Horseman @ Scriptocalypse.com
	 */
	public class UtterMadness {
 
		private var bannerSign:MovieClip;
		private var youWinClip:MovieClip;
		private var _winCondition:WinCondition;
 
 
		public function UtterMadness() {
			_winCondition = new WinCondition();
		}
 
		// e.type == "danceType";
		private function onBugsDanceComplete(e:Event):void {
			if (_winCondition(e, youWinClip)) this.youWin();	
		}
 
		// e.type == "VOType"
		private function onVoiceOverComplete(e:Event):void {
			if (_winCondition(e, youWinClip)) this.youWin();	
		}
 
		// e.type == "fireworksType"
		private function onFireworksExploded(e:Event):void {
			if (_winCondition(e, youWinClip)) this.youWin();	
		}
 
		// e.type == "bannerType"
		private function onBannerSignComplete(e:Event):void {
			if (_winCondition(e, youWinClip)) this.youWin();	
		}
 
		// e.type == "boulderType"
		private function onBoulderRoll(e:Event):void {
			if (_winCondition(e, youWinClip)) this.youWin();	
		}
 
		private function youWin():void {
			youWinClip.gotoAndPlay("win");
			bannerSign.gotoAndPlay("goAway");
		}
 
	}
 
}

Notice that I kept the youWin function in the main UtterMadness class. While it’s possible to place it in the permissions class and not bother with the Boolean return value, I find that I’d rather give the logic gate no more responsibility than to return the truth of an input. This way, I never have to open the WinCondition class again unless I’m modifying the conditions. If I were to place the ‘youWin’ logic in the WinCondition class, I’d have a second reason to modify or edit the file. Given how capricious our theoretical client is, it’s likely we’d have to add or change the youWin behavior many more times.

Changing code logic without a good reason is to be avoided because every time you edit or change a class or add more responsibilities to it, you increase the likelihood of injecting an error. For my money, “because we need to change what happens when you win” is not a good reason to modify or change “how you determine when you win”.

Tags: , ,

4 Comments