Friday, November 30, 2007

Design Principles To Live By

Object-oriented design and design patterns can seem complex.  There are a lot of ideas and cases to consider.  However, there are a handful of principles that, if followed, will result in code that complies with most if not all of the patterns.  These are the patterns behind the patterns.  In my mind, there are 5.  In the next week or so, I'll be writing a post on each of these.



  1. Encapsulate Variation
  2. Design To Interfaces
  3. Loose Coupling Between Classes
  4. Classes Exhibit High Cohesion
  5. Prefer Composition Over Inheritance

  6. Don't Repeat Yourself [late addition]
I'm sure I've missed a couple.  If I have, let me know.

Thursday, November 29, 2007

Inbox Zero

If you're anything like me, you have way too much e-mail to read it all.  To try to cope with this, I've resorted to a collection of rules that sorts my mail into a Byzantine structure of folders.  This helps a little, but has the problem of helping me miss a lot of mail as well.  Things get neatly sorted into specific folders where they are summarily ignored for large periods of time.  I just ran across a talk by Merlin Mann discussing a concept he calls "Inbox Zero."  There are basically two main concepts:

  1. Don't let e-mail run your life.  Check it only periodically.
  2. When you do check it, take action on each piece of mail right away.  The key is the nature of the action taken.  In my world, taking action has always meant reading and responding to the mail.  This takes a long time and it's hard to get through the mailbox this way.  Instead, Merlin suggests doing one of the following, all of which are quick:
    1. Delete.  If the mail isn't important, delete it immediately.
    2. Archive.  If this isn't something you need now but might want later, move it to an archive folder.  He says to use just one.  That way you don't need to think about how to file it.  In Outlook 2007 (or earlier if you used desktop search or Lookout) and online mail programs, searching can solve the problem folders were intended to solve.  The advantage of only one is that you don't need to think about how to file it.
    3. Respond Quickly.  If you can answer in 1-5 sentences, just do it.  Then delete (or archive) the mail.
    4. Just Do It.  If action is required that can be done now, get up and do it.
    5. Flag For Follow-up.  If the mail requires more time, move it to a follow-up folder or mark in such a way that you know to get back to it.  This lets you move on.  Come back to this folder at the end of the day and clean it out.

That's all.  I'm going to give it a shot and see how it works.

Apparently this talk was based on a series of blog posts.

Sunday, November 25, 2007

Video Podcasts

With my new Zune, I've started watching some video netcasts.  Here are the ones I've found the most interesting so far:

  • Tekzilla - Feels a lot like old TechTV.  1/2 hour an episode talking about everything from routers to Black Friday sales.
  • The GigaOm Show - Om Malik interviews headliners and comments on the Web 2.0 world.
  • DL.tv - Another technology news show.
  • Cranky Geeks - John Dvorak hosts a panel discussion about the latest trends in technology.  Think Twit but with video.  Not quite as good though.
  • Ask A Ninja - Short form comedy.  Hard to describe.  Just watch it.
  • Tiki Bar - Comedy show set around the adventures in a tiki bar.  Well written and high production value.

If I'm missing any good video casts, let me know.

Saturday, November 24, 2007

The New Zune Revue

Over the past few years I have become an avid podcast listener.  I've been using Creative MP3 players until this point.  I have owned a Zen Nano, Zen Stone Plus, and a Zen Vision M.  The first was good its 1 GB size became restricting.  The second was a good size, but the battery life was terrible.  It's supposed to be 10 hours but it felt more like I was getting 5-7.  Worse, it's not clear when you are about to run out of battery.  The Zen Vision M is nice, but too heavy for my liking.  The UI is also quite a mess.  It's very inconsistent and not always intuitive.  For various reasons, I've never owned an iPod.  I also skipped the first Zune due mostly to the form factor.  I want to carry my player in my pocket all the time.  A hard drive player is just too big for that to be comfortable for me.

About a month ago I started seeing and reading about the new second generation Zune.  I liked the firmware on the first one but the PC software was pretty bad.  The new one did two things that piqued my interest.  First, they came out with a flash model.  Second, they totally rewrote the PC software.  As an added bonus, there is finally podcasting support.  The new unit looked promising so on the first day it was available, I bought one of the black 8GB Zunes.  I was not disappointed.  The device is solid, the firmware great, and the PC software very well done.  It's not perfect, there are certainly things that could be better, but overall the experience is amazing.

Highlights

When you unbox a new Zune, there is no CD included.  Instead, you have to go to the web to download the software.  The first thing I noticed is that there is a native 64-bit version of the Zune Player.  I run a 64-bit version of Vista on my main home machine so this was a welcome thing. 

The new player is elegant.  It is very streamlined.  This means that some functionality you might want is missing, but for the purpose of playing media and syncing to a Zune it is great.  In fact, I don't think I've loaded Windows Media Player since installing the Zune player.  It's that good.  It uses the same 2D control system that the Zune uses.  Visually, it looks great.  It makes iTunes look like a spreadsheet by comparison.

The support for podcasting is well done.  There is a list of hundreds of podcasts included in the marketplace.  You can search for them by keyword or browse by category.  Subscribing is as easy as hitting a subscribe button.  If the podcast you want isn't in the marketplace, you can just enter the url of the rss feed and it works the same.  It will then download the 3 most recent episodes and upload them one at a time to the Zune.  You are free to change these defaults if you want.  On the Zune, the podcasts show up in their own menu and are separated into audio and video podcasts.  When you finish listening to a podcast, it is automatically marked as watched and will be removed next time you sync.  In a really cool touch, each podcast has its own bookmark.  Unlike the Creative players I'm used to, I'm no longer hostage to the podcast.  It's easy to switch to music or even another podcast and come back to the same place later.

The screen on the Zune 4 and 8 GB models is a bit small, but it's fine for watching many shows.  I have watched video podcasts and TV shows transcoded from my Media Center and both are definitely watchable.  The screen is bright and the colors vivid.

Wireless sync is really cool.  Once you set up the Zune on your wireless lan, you can cause the Zune to sync any time you want.  It works well.  Look Ma!  No wires.

Lowlights

Unfortunately, not all is wonderful in Zune land.  The first thing I noticed is that I couldn't install the updated firmware.  I got an error 0xC00D11CD.  Searching the web I found that I'm definitely not the only one hitting this error.  Luckily, I also found a solution hidden in the forums.  If you see this error, try plugging in the cable directly into one of the motherboard mounted USB ports.  I get the error every time I'm plugged into the front jack but never in the back.  Your mileage may vary but hopefully this will help someone.

I really miss the ability to force a transcode before syncing.  The Zune can play audio at high bitrates and video at high resolutions.  If I'm not going to copy the file elsewhere, though, the extra resolution is wasted.  I want an easy way to down-res the audio and video files before syncing.  I can't find a way to do this presently.  This becomes a big problem when I'm trying to sync files from Media Center.  These are often 2-3 GB .dvr-ms files.  Because the Zune can play them directly, it doesn't transcode them.  Unfortunately, I don't want to waste 3 gigs of my 8 for one TV show.

While I'm at it, I'd like to see support for Divx and Audible formats.  Neither are on the device or in the software presently.

Conclusion

While there are definitely some things that could be better, this is a major leap forward from the first Zune.  The device UI is easy to use.  The new player is great.  The support is much broader than the first time out.  I haven't used an iPod extensively so I can't compare, but I don't feel like I'm missing anything with the Zune.  In fact, there are features like wireless sync I would miss if I did have an iPod.  If you are in the market for a new MP3 player this Christmas, give the Zune a good look.  You might be surprised at what you find.

Thursday, November 22, 2007

Happy Thanksgiving!

It is Thanksgiving today.  My wife and I will be having a small gathering of about nine family members.  I always enjoy getting some time to put work aside for a few days just hang out with family.  I hope you all have a great Thanksgiving today and that many of you get to spend time with family and friends.  I've often said that 80% of happiness is just deciding to be happy.  I encourage everyone to take the opportunity today to reflect on the good things in life.

Saturday, November 17, 2007

Resume Advice

Some resume advice from Steve Yegge.  I don't agree with all of it but it's good stuff to consider when writing your technical resume.

Friday, November 16, 2007

Phone Screen Questions

Steve Yegge from Amazon offers his Five Essential Phone Screen Questions.  It's an old post, but a good one.  His advice is solid.  It's always disappointing to bring in a promising candidate for an interview only to have them bomb.  It would be much better to screen them out early.  Steve give suggestions for what to ask (and not ask) to make a better determination up front.  Most of the advice is universal.  Some is specific to the type of work Steve is hiring for.  For example, he suggests that one of the five areas to probe is scripting and regex.  There are a lot of jobs out there that need this, but not all.  On my team (Audio Test Development in Windows), scripting and regex don't get a lot of use.  Instead, I would tend to ask about OS concepts and debugging.

Steve gives some other good advice.  First, he says that the interviewer needs to direct the interview.  That seems obvious but it is easy to focus on the areas the candidate wants to cover (the things on his/her resume) and forget the things that are missing.  Second, he gives a bar for the answers.  He says that you are looking for a well-rounded individual.  The acceptable candidate does not have to excel at all five points.  Rather, they cannot fall flat in any area.

I concur with most of Steve's advice.  My addition to his is to probe beyond the first-level answer.  I like to ask questions that go deeper until I find the point at which the candidate no longer knows the next level of answer.  It's easy to cram some high-level ideas.  Everyone can say that threads are more "lightweight" than processes, but what does this really mean?  Either the candidate really understands and has some solid second- (or third-) level answers or they don't really know the subject area.  Don't be afraid to ask follow-up questions until the candidate runs out of answers.  You'll get a much better sense for the candidates' strengths and weaknesses.  Of course, if you are going to do this, tell the candidate up front.  It's not fatal to not be able to explain how page tables can be used to map memory across processes.  You don't want them flustered when they mess up.

Wednesday, November 14, 2007

"Everyone" Is Not A Valid Owner

Saw this over on {Codesqueeze}.  He talks about the danger of self-organizing teams.  When people aren't given clear responsibilities, things get dropped.  If there is a task which belongs to everyone it will in the end be accomplished by no one.  Everyone who sends e-mail knows this.  If you want an answer to your mail, never send it to two people at once.  Send two individual mails.  I liked this quote:

Managers with strong knowledge but are weak leaders tend to run hippie communes.

This is often true.  There is a management style which tries to leave responsibility up in the air.  Weak leaders hope their teams will self-organize.  This just doesn't work most of the time.  If it does, it is usually because a strong leader who wasn't the manager took charge.

Tuesday, November 13, 2007

Analog to Digital Conversion

If you want digital audio in a computer, you have to get it from somewhere.  Usually that means taking analog sound out of the air and turning it into the bits that a computer can understand.  Ars Technica gives us another installment of the AudioFile. This one covers the subject of Analog to Digital Conversion.

Monday, November 12, 2007

Always Question the Process

Let me recount a story from the television show Babylon 5.  In one episode there is the description of guard posted in the middle of an empty courtyard.  There is nothing there to protect.  When one of the characters, Londo, questions why, he finds that no one, not even the emperor, knows why.  After doing some research, Londo discovers that 200 years before, the emperor's daughter came by the spot at the end of winter.  The first flower of the spring was poking up through the snow.  Not wanting anyone to step on the flower, she posted a guard there.  She then forgot about the flower, the guard, and never countermanded her order.  Now, 200 years later, there was still a guard posted but with nothing to protect.  There had been nothing to protect for 200 years.


This demonstrates the unfortunate power of process.  It often takes on a life of its own.  Those creating the complex system of rules expect it to be followed.  Once written down though, people stop thinking about why it was done.  Instead, they only expect it to be carried out.  This often leads to situations where work is being done for the sake of process instead of the outcome.  It is from this situation that bureaucracy gets its sullied reputation (well, that and the seeming ineptitude of many bureaucrats).  Process can easily become inflexible.  This is especially true in the technology industry where process is embedded in the code of intranet sites and InfoPath forms.


I encourage you to constantly revisit your process.  Question it.  Why do you do things the way you do?  Is there still a reason for each step?  If you don't know, jettison that step.  Simplify.  You should have just enough process to get the job done, but no more.  Once again, I'll re-iterate.  You hire smart people.  You pay them to think.  Let them.


This isn't to say that all process is bad.  Having common ways of accomplishing common tasks is efficient.  If a process truly makes things more efficient, it should be kept.  If not, it should be killed.  What was at one time efficient probably isn't any more.  Be vigilant.

Saturday, November 10, 2007

The Ultimate Geek Jacket

With Christmas approaching, here is a cool idea for the gadget-lover.  The ScottEVest Evolution Jacket is a waterproof jacket with 25 pockets for all the cellphones, Zunes, PDAs, pens, etc. that we tend to carry these days.  The jacket also has special ducting for headphones from the iPod/Zune pocket, space for books, water bottles, and magazines.  The sleeves come off to make it into a vest.  In short, it looks very cool.  If a coat isn't what you are looking for, they also have shirts, hats, and pants with special pockets for gear.


You can get 20% off if you go through TWIT.  Here is a cool video of the CEO showing this off on Donny Deutsch's show.

Friday, November 9, 2007

Keep Process Simple

Year ago one of our Software Test Engineers was tasked with documenting our smoke* process.  It should have been something simple like:



  1. Developer packages binaries for testing
  2. Developer places smoke request on web page
  3. Tester signs up for smoke on web page
  4. Tester runs appropriate tests
  5. Tester signs off on fix
  6. Developer checks in

Instead it turned into a ten page document.  Needless to say, I took one glance at the document and dismissed it as worthless.  As far as I know, no one ever followed the process as it was described in that document.  We all had a simple process like the six steps I laid out above and we continued to follow it.


When tasked with creating a process for a given task, the tendency is to make the process complex.  It's not always a conscious effort, but when you start taking into account every contingency, the flow chart gets big, the document gets long, and the process becomes complex.  To make matters worse, when a problem happens that the process didn't prevent, another new layer of process is added on top.  Without vigilance, all process becomes large and unwieldy.


The problem with a large, complex process is that it quickly becomes too big to keep in one's mind.  When a process is hard to remember, it isn't followed.  If it takes a flow chart to describe an everyday task, it is probably too big.  It is far better to have a simple, but imperfect process to one that is complete.  The simple process will be followed out faithfully.  The complete one will at best be simplified by those carrying it out.  Worse, it may be fully ignored.  It is deceptive to think that a complex process will avoid trouble.  More often than not, it will only provide the illusion of serenity.


I have discovered that process is necessary, but it must be simple.  It is best to keep it small enough that it is easily remembered.  The best way to do this is to document what is done, not what you want to be done.  People have usually worked out a good solution.  Document that.  Don't try to cover all the contingencies.  It will only hide the real work flow.  Documented process should exist to bring new people up to speed quickly.  It should be there to unify two disparate systems.  It should not be there to solve problems.  You hire smart people, let them do that.  Expect them to think.


My final advice on this topic is do not task people with creating process.  It is tempting to say to someone, "Go create a process for creating test collateral."  Tasking someone with creating process is a surefire way to choke the system on too much process.  The results won't be pretty.  Nor will they be followed. 


 


*Smoke testing is a process involving testing fixes before committing them to the mainline build.  Its purpose is to catch bugs before they affect most users.

Thursday, November 8, 2007

The Need for a Real Build Process

Jeff Atwood at Coding Horror has a good post about how "F5 is not a build process."  In it, he explains how you need a real centralized build process.  F5 (the "build and debug" shortcut key in Visual Studio) on a developer's machine is not a built process.  At Microsoft, we have a practice of regular, daily builds.  We use a centralized content management system which everyone checks their code into.  At least daily, a "build machine" syncs to the latest source code and builds it all.  There are three main advantages of this system. 

First, it makes sure that the code is buildable on a daily basis.  If someone checks in code which causes an error during the build process, it shows up quickly.  We call this "breaking the build" and it's not something you want to be caught doing.  If you break the wrong build, you can get a call early in the morning asking you to come in immediately and fix it.

Second, it ensures that there is always a build ready for testing.  This has the added benefit of providing one central spot for everyone to install from.  If the build process is just on individual developers' machines, it is not uncommon for different people to be testing a build from radically different sources and thus have conflicting views of the product.  If you find a bug and someone says "Oh, it's fixed on my machine with these private bits" that is a sign of trouble unless they fixed it in the last 24 hours.

Finally, it ensures there is a well-understood manner of building the product.  If the builds are not centralized, there is no documented way of building the product.  Being able to build then becomes a matter of having the right tribal knowledge.  Build this project, then copy these files here, then build this directory, then this one.  Having a centralized and well-understood build process is a sign of a mature project.

If you are looking to improve your build process, there are plenty of tools out there to help.  The oldest and probably most-used tool is make.  It's also probably the hardest to use.  It has a lot of power, but it pretty quirky.  I've heard good things about Ant but I haven't used it.  It seems to be taking the place of make in a lot of projects.  The latest Visual Studio has a new build tool called MSBuild.  Again, I've heard good things but I haven't used it.

Thursday, November 1, 2007

Don't Blame the User for Misusing Your API

A conversation the other day got me thinking about interfaces.  As the author of an interface, it is easy to blame the users for its misuse.  I think that's the wrong place for the blame.  An interface that is used incorrectly is often poorly written.  A well-written one will be intuitive for most people.  On the other hand, a poorly-designed one will be difficult for many people to operate.  Sure, properly educated users could use even a poor interface and even the best interfaces can be misused by incompetent users, but on average a good interface should intuitively guide the users to make the right decisions.  I'll focus mostly on programming interfaces but the same facts are true for user interfaces.


One of the rules in our coding standard is that memory should be released in the same scope in which it was allocated.  In other words, if you allocate the memory, you are responsible for making sure it is released.  This makes functions like this violations of our standard:



Object * GetObject(void)


{


    return new Object(parameters);


}


Why do we say this shouldn't be done?  It is not a bug.  Not necessarily anyway.  If the person calling this function just understands the contract of the function, he'll know that he needs to delete the Object when he's done with it.  If there is a memory leak, it's his fault.  He should have paid close attention.  That's all true, but in practice it's also really hard to get right.  Which functions return something I need to delete?  Which allocation method did they use?  Malloc?  New?  CoTaskMemAlloc?  It's better to avoid the situation by forcing the allocation into the same scope.  This way there is much less room for error.  The right behavior is intuitively derived from the interface itself rather than from some documentation.  here's a better version of the same function:



void GetObject(Object * obj)


{


    obj->Configure(parameters);


}


This second pattern forces the allocation onto the user.  Object could be on the stack or allocated via any method.  The caller will always know because he created the memory.  Not only that, but people are accustomed to freeing the memory they allocate.  The developer calling this function will know that he needs to free the memory because it is ingrained in his psyche to free it.


Here's another example I like.   I've seen this cause bugs in production code.  CComPtr is a smart pointer to wrap COM objects.  It manages the lifetime of the object so you don't have to.  In most cases if the CComPtr already points at an object and you ask it to assign something new to itself, it will release the initial pointer.  Examples are Attach and Operator=.  Both will release the underlying pointer before assigning a new one.  To do otherwise is to leak the initial object.  However, there is an inconsistency in the interface.  Operator& which retrieves the address of the internal pointer, p, does not release the underlying pointer.  Instead, it merely asserts in p!=NULL.  CComPtrBase::CoCreateInstance behaves similarly.  If p!=NULL, it asserts, but happily over-writes the pointer anyway.  Why?  The fact that there is an assert means the author knows it is wrong.  Why not release before over-writing?  I'm sure the author had a good reason but I can't come up with it.  Asserting is fine, but in retail code it will just silently leak memory.  Oops.  Who is to blame when this happens?  I posit that it is the author of CComPtr.


When someone takes your carefully crafted interface and uses it wrong.  When they forget to free the memory from the first GetObject call above, the natural inclination as the developer is to dismiss the user as an idiot and forget about the problem.  If they'd just read the documentation, they would have known.  Sometimes it's possible to get away with that.  If your interface is the only one which will accomplish something or if it is included in some larger whole which is very compelling, people will learn to cope.  However, if the interface had to stand alone, it would quickly be passed over in favor of something more intuitive.  Let's face it, most people don't read all the documentation.  Even when they do, it's impossible to keep it all in their head. 


Very many times the author of the API has the power to wave a magic wand and just make whole classes of bugs disappear.  A better written API--and by that I mean more intuitive--makes it obvious what is and is not expected.  If it is obvious, people won't forget.  As the author of an API, it is your responsibility to make your interface not only powerful but also intuitive.  Bugs encountered using your interface make it less appealing to use.  If you want the widest adoption, it is best to make the experience as pleasant as possible.  That means taking a little more time and making it not just powerful, but intuitive.


How does one do that?  It's not easy.  Some simple things can go a long way though. 



  • Use explanatory names for classes, methods, and parameters. 

  • Follow the patterns in the language you are writing for.  Don't do something in a novel way if there is already an accepted way of doing it. 

  • Finally, be consistent within your interface and your framework.  If your smart pointer class releases the pointer most of the time something new is assigned to it, that's not enough.  It should be true every time.  To have an exception to the rule inevitably means people will forget the exceptional situation and get it wrong.

As I said at the beginning, this same rule applies to user interfaces.  If people have a hard time using it, blame the designer, not the user.  For those of you old enough to have used Word Perfect 5.x, recall the pain of using it.  There was no help on the screen.  Everything was done by function key.  F2 was search.  Shift-F6 was center, etc.   The interface was so unnatural that it shipped with a little overlay for your keyboard to help you remember.  Is it any wonder that the GUI like that in Microsoft Word, Mac Write, Final Copy (Amiga), etc. eventually became the dominant interface for word processing?  People could and did become very proficient with the Word Perfect interface, but it was a lot easier to make a mistake than it should have been.  The more intuitive GUI won out not because it was more powerful, but rather because it was easier.  Think of that when designing your next API or User Interface.  Accept the blame when it is used incorrectly and make it so the misuse won't happen.  Keep it easy to use and you'll keep it used.