Thursday, December 25, 2008

Hope You Had a Merry Christmas

The day's almost over.  Snow is still on the ground here although the temperature is going up and its days are numbered.  I spent most of today with family just hanging out.  I found it to be enjoyable and relaxing.  Didn't get much accomplished, but that's as it should be on a day like this.  I hope that your Christmas was a good one as well.

Wednesday, December 24, 2008

10 Programming Languages Worth Exploring

Now that I've completed the final class toward my Masters Degree I have the time to explore some things of my own choosing.  One thing I intend to do is to learn a new programming language.  This article I discovered via Reddit is a good place to start.  It lists 10 languages worth learning.  These are the up-and-coming languages, not the current hot topics like Python or Ruby.  Interesting items on the list include Squeak, Haskell, Clojure, and PLT Scheme.

Tuesday, December 23, 2008

Stroustrup on What's Wrong With CS Programs

Similar to thinking of Joel Spolsky (and me), Bjarne Stroustrup (the inventor of C++) says the way we teach CS today is broken.  That is, it is at odds with the needs of the industry.  Having just completed a Masters in CS I can say first hand that this is true.  Some of what I learned was applicable to my work at Microsoft, but I could see the tension in the higher-level classes especially between the needs of preparing someone for research and preparing them for industry.  Research is not about programming.  It is about thinking in new and innovative ways about problems.  Industry needs good programmers and the best solutions to problems.  CS research students often ignore the best solutions to problems because those have already been discovered and you can't get published writing about the same thing again.  Industry prefers the proven solutions. 


Stroustrup bemoans the use of Java in so many programs today.  He doesn't attack Java per se but rather the emphasis on the libraries.  Students don't learn to solve fundamental problems (like sorting) because the library can do that for them.  It is easy to become an expert in Java rather than an expert in programming, something Rovert Dewar states well in this interview.  When the Java (or C# or Ruby) language wanes in popularity, it is the underlying CS skills that translate, not the intimate knowledge of the Java collections hierarchy.  I have a more fundamental problem with higher-level languages for learning.  It is important to learn how the machine works because someday everyone will be stuck with a leaky abstraction and will have to solve the deeper problem.  Without an understanding of what is below the byte code (or code), doing so can become very difficult.  It is easy to code oneself into a corner without knowing it if the understanding of the underlying system is missing.


He also talks about the lack of quality in the code written by students.  Too many projects are littered with magic constants, not well factored, etc.  This probably comes from the fact that code written for classes is thrown away.  Most of my professors never even asked for our code let alone actually read it.  A TA in my OS class actually said they didn't care about memory leaks.  In a freaking OS class of all things!!! 


The takeaways:



  • Learn a lower-level language.  Joel Spolsky says everyone should learn C.  I'm inclined to agree.  It's not too hard to learn and it is as close to the metal as you usually want to get.

  • Learn to express your ideas in more than 1 language.  Each is a little different.  Learning other languages gives you tools to think about problems in new ways.  This also ensures your knowledge is about the algorithms, not the base class libraries.

Sunday, December 21, 2008

Why You Get Nothing Done When You Have So Much Free Time

Interesting musings on a subject I can attest to be true.  Why is it we get so much done when we're on a tight schedule but then fail to get anything done when we have a long vacation?  The same applies to work too.  Give someone a long time to get a project done and it will still come in late.  Give them a short time and it will be done earlier.  The author attributes this to Innumeracy.  That is, the inability of humans to understand large numbers.  When we see a huge amount of time, we don't understand the true magnitude or true limit of that size.  It is this same effect that often casues lottery winners to go broke.  They have what they think is a huge amount of money and don't understand when the finiteness catches up to them.  Likewise when a person has a seemingly lot of time available, they fill it with too much stuff and end up getting nothing (important) done.  The author has a suggestion for solving this.  He suggests applying the 80-20 rule.  Target the top 20% of the tasks you have to do.  The other 80% only if they can fill in the gaps.  Basically this boils down to prioritizing.  When we have a seemingly infinite amount of time in front of us, prioritizing doesn't feel necessary and so low-priority tasks dominate.  Perhaps this is why Agile works so much better than Waterfall.  By imposing numerous (arbitrary) deadlines mid-project, it forces prioritization. 

Tuesday, December 9, 2008

Modern Computing Began 40 Years Ago Today

Modern computers all utilize the same user paradigms:  interactive computing, mouse, windows, hyperlinks, teleconferencing, etc.  Many people consider Xerox Parc to be the nest in which most of these concepts were born.  That is, afterall, where Steve Jobs got his inspiration for the Macintosh.  It is not where they were first conceived or even accomplished.  All of these were first demonstrated 40 years ago today by Douglas Engelbart of Stanford Research Institute (SRI). On december 9, 1968 he demonstrated to a crowd of 1,000 many of the things that make up modern computers.  Some pictures of the event can be seen here.  SRI is hosting an event today honoring the event.

Friday, December 5, 2008

Improving Task Estimation Accuracy

In my opinion estimating how long it will take to write a piece of software is difficult if you haven’t done it before and with software we never have.  The more experience you have, the more you’ll have done similar things and thus the more accurate your estimates will be.  To help build this experience faster, it is important to track how long things actually take. 

Many software developers just start working and don’t really plan.  They have a vague idea what they want to accomplish, but haven’t really thought it through.  This inevitably leads to the task taking longer than expected.  There is a great discussion of this on the Stack Overflow Podcast.  Check out episodes 5 and 16 for the before/after.  There are transcripts available if you don’t have time to listen.  The reason why things take longer is because without careful planning, there are a lot of pieces of work that aren’t taken into consideration.  Basically the programmer makes an unfounded assumption that he doesn’t have to do some work that indeed he does.  In my experience, this is one of the largest contributing factors to things taking too long.

The good news is that most of these unconsidered items can be teased out if sufficient thought is given to the problem.  They are known unknowns.  The questions are usually known, just not the answers.  There are techniques for doing this. 

The simplest is breaking down the problem into small pieces.  On our projects we never let items get bigger than 5 days of work.  This is probably too large.  If you are estimating in chunks larger than a day or two, you are probably glossing over important details. 

Writing a spec in some level of detail is also important.  Be honest with yourself and explain how things will get done, not just that you need to do them.  “Break class Foo into two classes” may not be enough detail.  What are the two other classes going to do?  How will they work together?  My rule of thumb is that a spec isn’t done until someone could pick it up cold and implement a reasonable facsimile of what you intended.  If they can’t, it is too vague.

For estimation of larger projects, there is a process called Wideband Delphi estimation that can help to flush out the underlying assumptions.  It is very lightweight and can be done by a few people in a couple hours for many projects.

Once the task is broken down into small segments and these segments are estimated, it is important to track how long each item really took.  Be honest.  You are only cheating yourself if you report a 3-day work item as having taken 1 day.  This helps to build experience and make better estimation possible in the future.

One more thing to consider is whether you are staying on task.  When it isn’t something we failed to consider, the next highest cause of under-estimation is distraction.  How much time are you actually spending on a project?  If you spend an hour a day working on it and the other 7 hours doing e-mail, meetings, surfing the web, talking to people, etc. you won’t finish on time (unless you account for an 87.5% buffer).

Speaking of buffering, it is my experience that it is easier to estimate uninterrupted time than to try to estimate how much time all of the distractions will take.  On our team we estimate each work item in a vacuum.  This will take 1 day of coding and debugging time.  Meetings, vacations, e-mail and other distractions all fall into another category we call “buffer.”  We usually estimate 30% of an average person’s time will be spent in this buffer state.  This varies with the project of course.  Separating the two allows us to better see where the time is being spent.  It is a much different issue if someone takes 5 days actually working on what was estimated as a 2-day problem than if they take 2 days coding but are distracted with other items for 3 days.

Thursday, November 27, 2008

Happy Thanksgiving 2008!

Here's wishing everyone a happy Thanksgiving day.  It's a great time to reflect on the past year and all that has transpired. 

Wednesday, November 26, 2008

Using Perl for Mass In Place Editing

Have you ever wanted to update some text in a bunch of files all at once without a hassle?  I had reason to do this recently and turned to Perl for my solution.  Once I found the implementation quirks, it turned out to be quite easy.  This functionality is pretty well documented, but not for Windows.  There are some gotchas trying to do it there.  What follows is what I found to work.


I had a set of files that were database queries for a particular milestone in our product release.  Let's call it M1.  I needed to update them all for a different milestone that we'll call M2.  Each file was an XML version of a query so text parsing seemed like the logical course of action.  Perl is good at text processing so I went that route.  First off I had to install Perl.


Perl is capable of accepting a single line of code at the command prompt so there is no reason to actually author a perl script.  The command for this is -e (execute?).  To change something inline, you can use the -i (in place) command.  The command looks something like this:



perl -pi.bak -e "s/M1/M2/g" file.txt


The -i.bak means to rename the original files with the .bak extention.  In theory -i alone will delete the originals but ActivePerl wouldn't accept this. 


The -p tells perl to run the command over every line of standard input (i.e. over every line of the file).


The "s/M1/M2/g" command is a regular expression telling it to substitute M2 for M1 globally.  It could be any regular expression.  Note that most examples of this online use only single quotes ( ' ), but this doesn't work on Windows.  One hint:  If the command fails, try adding -w to the command line to generate warnings. 


The above command will change all instances of M1 to M2 in file.txt.  What I wanted to do was to replace it in every file.  Simple, I'll just change file.txt to *.*.  Sorry, no dice.  ActivePerl doesn't accept this nor does it accept *.  Time for some more command-line action.  There is a for command that can be utilized at the cmd prompt which fits the bill.  Use it like so:



for %i in (*.txt) do perl -pi.bak -e "s/M1/M2/g" "%i"


This command will iterate over all the files (*.txt) and execute the command following the do.  You have to quote the trailing %i because filenames might contain spaces.


There you go, quick and dirty text replacement from the command line.  Note that perl regular expressions are capable of much more than simple search and replace.  You can use this technique to accomplish anything they can.


Is there an even simpler way to do this?  There probably is.  If so, please let me know in the comments.


 


12/4/08 - Updated with -p thanks to Maurits.

Wednesday, October 29, 2008

More Win7 Previews

Previews of some specific parts of Windows 7 which are of interest to me:


Audio


Media Center

Tuesday, October 28, 2008

Win7 Previews Starting To Appear

Windows 7 is being unveiled for the first time at PDC and the initial previews are starting to hit the net.  Here is a sampling:


Gizmodo (covers Device Stage with lots of pictures)


WinSuperSite (lots of pictures of the shell)


Ars Technica (mostly new UI)


NeoWin (UI plus Device Stage)

Tuesday, October 21, 2008

The MUD is 30 Years Old

Back before World of Warcraft or even Everquest there existed an entity called a MUD or Multi-User Dungeon.  These were a lot like today's MMOs except that they were text-only interfaces.  Most of the concepts were the same.  Build a character, kill lots of bunnies/elves/etc. to grind out levels, get cool gear, group with your friends.  They were just as addicting as modern MMORPGs.  I recall playing something like 24 hours of game in a 2-day period during finals week.  That's when I decided I should quit.  It was my grades or the MUD and the grades won.  That's probably why I'm writing this blog today instead of asking, "Would you like fry's with that?"  The first MUD I ever played seriously was called Crystal Shard.  As most MUDs, it shared a common code base with others but was heavily customized. 


Anyway, the MUD turned 30 this week.  It was October 20, 1978 that the first MUD came into existence.  It took a while for them to make it to the mainstream...

Saturday, October 18, 2008

Some useful traveling gear

I just returned from a trip to the University of Illinois, Urbana-Champaign.  I brought some items with me that turned out to be very useful so I thought I'd pass along the tips in case you are in the market for such items.


Headphones - I brought several pairs along, but I really enjoyed my Sennheiser HD 280 Pros.  They are full-size headphones, not earbuds or anything.  This gives them much better sound than most smaller headphones.  They also provide a lot of sound isolation.  They are not actively noise canceling, but keep out most external noise due to their design.  What makes these better than most full-size headphones is that the earpieces both pivot so that they are aligned with the body of the headpiece.  This allows them to be stored in 1 1/2-2" of space rather than the 4-inches or so that would be required of other headphones.


Jacket - I wore my Scottevest Evolution jacket.  This jacket has 15 functional pockets (and several other smaller ones) which makes it great for packing things.  Instead of trying to put a backpack or laptop back under the seat, I just put all the items I want for a plane flight into my jacket which stows easily and still leaves room for my feet to move.  There is a pocket perfectly sized for a paperback book, one just right for a magazine (in the back), one that perfectly fits my Eee PC (below), space for a water bottle, plus pockets for Zune, phone, etc.  In addition, the arms come off turning it quickly into a vest.  I found the full jacket a bit warm for most airports and airplanes, but the vest to be quite comfortable.  The arm pieces stow easily in the back pocket and attach quickly when you are ready to leave the airport and face the elements.


Laptop - I brought along my Asus Eee 1000h on the trip.  It has several benefits over the Lenovo and Dell laptops I have brought on previous trips.  First, it is very light.  It weight around 3 lbs which is a lot nicer to lug through an airport than the 6+ lb notebooks I was accustomed to.  Second, the battery life is amazing.  I'm currently looking at 75% of my battery left and an estimated 5 hours, 27 minutes of time remaining.  The time drops when doing more than reading papers and typing blog posts, but it is still very respectable.  The third advantage is the size.  The 1000h is big enough to have a functional keyboard, but small enough that it is easy to stow in a backpack or even the inside pocket of my Evolution jacket.  It's also small enough to comfortably open in a coach airplane seat.  A 15" laptop can't fully open in those cramped quarters.  The problem gets even worse if the person in front of you decides to recline.  The 1000h suffers from no such problem.


[Updated SEV link - Thanks Bill]

Friday, October 17, 2008

The Five Why's and Testing Software

Toyota was able to eclipse the makers of American cars in part due to its production and development systems.  The system has been popularized under the rubric of "Lean" techniques.  Among the tenets of the Lean advocates is asking the "Five Why's."  These are not the W's of journalism:  Who, What, Why, Where, and When?  They are not specific questions even.  Asking five why's means asking why 5 times.  Why was the production of cars down?  Because there were missing screws.  Why were there missing screws?  Because the production robots were bumping them.  Why were the robots bumping?  Because the programming was faulty.  Why was the programming faulty?  Because the programmer didn't take into account a metric->English conversion.  Why didn't the the programmer consider conversions?  Because... 

There is no magic in the number 5.  It could be 4 or 6.  The importance is to keep asking why until the root cause is understood and fixed.  Fixing anything else is just alleviating the symptoms of a deeper problem.  Not solving the root problem means it will likely cause other problems later and more time will be wasted later.

How does this apply to testing?  It goes to the core of the role of test in a product team.  Think about what happens when your team finds a bug in your software.  What do you do?  Hopefully someone on the test team files a bug report and either the tester or the developer root cause the problem and fix it.  This usually means determining the line of source code causing the issue and changing it.  Problem solved.  Or is it?  Why was that line of source code incorrect in the first place?  We rarely--if ever--ask.

What if we began to view our role as testers as trying to eliminate bugs from the system instead of from the source code.  In that case we would be asking what coding techniques or early testing systems the team could employ to stop the bug from entering the source code at all or at least detecting it while the code was still under development (better unit testing might be a solution in this category).

Wednesday, October 15, 2008

Change Your Environment

As people grow in maturity in their jobs, the way they interact with their environment changes.  I have had this discussion a few times during the recent review cycle so it's probably time to pass it along to a wider audience.  As I see it, there are three stages most people go through during their career.

Stage 1 - Rejection

A new person in an environment will often chafe at that environment.  Things aren't the way they would do it.  They find it wrong and complain about it.  Sometimes loudly.  The trouble is, they don't do anything about it.  Complaining doesn't help.  Suggestions do.  At this lowest maturity level, suggestions are rare.

Stage 2 - Acceptance

The next stage of maturity is acceptance.  A person at this stage stops complaining.  They see value in the way the system works and willingly participate.  People at this maturity level still consider the rules to be an external force.  They are to be followed, but not questioned. 

Stage 3 - Change

By stage 3, the person is comfortable enough in their environment to begin changing it.  He sees something imperfect and, rather than complaining like a stage 1 person or just putting up with it like a stage 2, he takes steps to improve the environment.  Mature employees will come with solutions, not complaints.

Use these levels to help mature in your career.  Assess where you are at and then decide on the behaviors that will take you to the next level.  Many times I've seen people bogged down in their careers and not understanding how to advance it.  The trouble was often that they were not taking initiative.  They were in stage 2 and not progressing to stage 3.  When was the last time you went to your manager with a solution?  Not a complaint, but a way to improve the system?  What did you do when it wasn't immediately adopted?  The right response is to persevere.  If the change is worth making, it is worth expending energy on.

Monday, October 13, 2008

Windows 7 Will Be Officially Called... "Windows 7"

After Millenium, XP, and Vista comes... Windows 7.  Yep.  Not a lot of imagination in this one.  As unexciting as the name is, I'm excited that we're finally starting to talk about it.  It's shaping up to be a really nice OS.  I can't wait until you all get to experience it.


http://windowsvistablog.com/blogs/windowsvista/archive/2008/10/13/introducing-windows-7.aspx


 

Sunday, October 12, 2008

Review: Tribal Leadership

I just finished the book Tribal Leadership by Dave Logan et al.  It's one of the better leadership books I've run across.  The authors stress the need for leadership to develop a "we" culture instead of an "I" culture.  The authors call this a stage 4 culture and the leadership style Tribal Leadership.  The advantage of moving to a culture that embraces group success over individual success is the ability to accomplish more.  A group of individuals acting as induhviduals cannot reach the heights that a group acting in concert can.

The authors identify five group cultures:

Stage 1 - Life Sucks - People in stage one believe that all of life sucks.  The world is oppressive and there is nothing the individual can do to fix it.  This is the culture most likely to be found in prison or the projects.  It is not something seen often in corporate life.

Stage 2 - My Life Sucks - People in stage two acknowledge that life can be good, just theirs isn't.  The blame is externalized.  Something is in the way of their success.  It might be their manager or the company's rules.  Stage two is marked by complaining, but not action.  Employees in a stage two company will form bonds of shared oppression.  If you've seen The Office, you've seen a stage two culture in action.

Stage 3 - This is much of corporate America today.  People in Stage 3 say "I'm great" and mean "I'm great and you aren't."  Stage three is all about individual excellence.  People in this stage can produce amazing results, but it is tiring.  Everything is a struggle against those less excellence than one's self.   Power is hoarded.  Help is unidirectional.  People at stage three tend to burn out because every success take such great personal investment.  This is the hero culture typical of companies like Microsoft for much of its history.

Stage 4 - "We're great" is the mantra of stage four.  The corollary is "You are not."  Cultures at this stage work together--putting the good of the group above the good of the individual--against a common foe.   This might be Apple's operating system group against Microsoft or the Live Search team as it comes together to take on Google.  Cultures at Stage 4 can operate more efficiently because they can share information and build upon each others' successes.  People are happy about the success of others instead of being jealous.

Stage 5 - "Life is great."  This is stage 4 without the common foe.  It is working together for the betterment of mankind (or some such) without the need of a common foe to unite the tribe.

The book focuses primarily on the Stage 4 culture and the leadership style necessary to achieve it.  It should be noted that the "Tribal Leadership" style of these authors is very similar to the "Level 5 Leader" described in the book Good to Great.  Stage Four cultures and leaders exhibit the following behaviors:

  1. A desire to work together.  To get to stage 4, you have to have gone through stage 3 and become disenchanted with the limitations of personal success.
  2. Shared core values.  People must be on the same page.  It is important that each member of the group be able to make decisions in line with all the others.  Having a shared set of values enables this.  Each decision can be reached by asking "What do our values have to say about this situation?" and following  where that leads. 
  3. A "noble cause."  The group needs a shared goal.  If core values are how a company operates, a noble cause is what it shoots for.  The authors say this cause must be "noble" but I'm not convinced it does. Any shared vision that all are bought into would seem to do.  Noble is, of course, better than ignoble. 
  4. The use of "triads."  Communication should be decentralized.  Imagine the situation where a manager is trying to coordinate the work of two employees--Jane and John.  If the manager goes to John and then takes that information to Jane, this is an example of 2 dyadic relationships.  Manager::John and Manager::Jane.  Instead, the manager should encourage John and Jane to work together or perhaps for the three of them to meet together.  This sort of communication does not happen in a stage 3 culture because knowledge is power and having knowledge flow through you is a way to concentrate said power.
  5. Using values and cause to work toward an outcome.  Actions must be informed by the values toward the cause.

A recent management talk I attended made the point that leaders set direction and then let their employees determine the best path toward success.  The job of the leader is to set the direction, align the team members around that direction, set the values for the group, and then be responsible for the growth of the team.  This sounds a lot like Tribal Leadership.

The end of the book feels a little utopian, but if you ignore the final chapter, there's a lot of useful ideas here.

Thursday, October 2, 2008

James Whittaker on Why MS Software "Sucks" Despite Our Testing

A friend turned me on to this post by James Whittaker.  I didn't know he had a blog so now I'm excited to read it.  He has a lot of really interesting things to say on testing so I encourage you to read his blog (now linked on the left) if you are intrigued by testing.

Microsoft prides itself on the advanced state of its testing operations.  This leads to the inevitable question, "If Microsoft is so good at testing, why does your software suck?"  James Whittaker was once a person who asked this question and now that he's at Microsoft he is in a good position to try to answer it.

James gives basically three reasons:

  • Microsoft's software is really complex.  Windows, Exchange, Office, etc. are really, really big projects.
  • Microsoft's software is used by a whole lot of people.  Eric Raymond once made the comment that all bugs are shallow if you have enough eyes.  This applies to closed source software just as much as open source.  Within the first few days of a release of Microsoft software, millions of people are using them.  Windows has an install base in the hundreds of millions.  With so many people looking at it, all bugs are likely to be hit by someone.
  • Microsoft testers are not involved early enough in the process.  This varies throughout the company, but there is still a lot of room for improvement.

Friday, September 26, 2008

22,500 Paper Airplanes

Rainn Wilson (Dwight K. Schrute from the Office) was the MC at this year's Microsoft company meeting.  Ever since they tore down the Kingdome, the meeting has taken place at SafeCo field.  Sitting up in the 300-level seats, it is tempting to throw paper airplanes.  Each year some people do.  This causes some strange moments when a speaker mistakes the applause for a particularly long airplane flight for applause for whatever they just said.  At this year's company meeting they decided that everyone should throw paper airplanes.  All at the same time.  Rainn orchestrated it dressed in a flight jacket.  It was a pretty impressive sight.


Video at 11.


 

Test Suite Granularity Matters

I just read a very interesting research paper entitled, "The Impact of Test Suite Granularity on the Cost-Effectiveness of Regression Testing" by Gregg Rothermel et al.  In it the authors examine the impact of test suite granularity on several metrics.  The two most interesting are the impacts on running time and the impact on bug finding.  In both cases, they found that larger test suites were better than small ones.

When writing tests, a decision must be made how to organize the tests.  The paper makes a distinction between test suites and test cases.  A test case is a sequence of inputs and the expected result.  A test suite is a set of test cases.  How much should each test suite accomplish?  There is a continuum but the endpoints are creating each point of failure as a standalone suite or writing many points of failure into a single suite.

The argument for very granular test suites (1 case or point of failure per suite) is that they can be better tracked and analyzed.  The paper examines the efficacy of different techniques for restricting the number of suites run in a given regression pass.  They found that more granular cases were more effectively reduced.  However, the time savings even from aggressive reductions in test suites did not offset the time taken to run all test cases in larger suites.  Grouping test cases into larger suites makes them run faster.  Without reduction the granular cases in the study ran almost 15 times slower.  With reduction, this improved to running only 6 times slower.

Why is this?  Mostly it is because of overhead.  Depending on how the test system launches tests there is a cost to each test suite being launched.  In a local test harness like nUnit, this cost is small but can add up over a lot of cases.  In a network-based system, the cost is large.  There is also the cost of setup.  Consider an example from my days of DVD testing.  To test a particular function of a DVD decoder requires spinning up a DVD and navigating to the right title and chapter.  If this can be done once and many test cases executed, the overhead is amortized across all of the cases in the suite.  On the other hand, if each case is a suite, the overhead is multiplied by each case.

Perhaps more interesting, however, the study found that very granular test suites actually missed bugs.  Sometimes as much as 50% of the bugs.  Why?  Because more less granular cases cover more state than less granular ones and are thus more likely to find bugs. 

It is important to note that there are diminishing returns on both fronts.  It is not wise to write all of your test cases in one giant suite.  Result tracking does become a problem.  It can be hard to differentiate bugs which happen in the same suite.  After a certain size, the overhead costs are sufficiently amortized and enough states traversed that the benefits of a bigger suite become negligible.

I have had first-hand experience writing tests of both sorts.  I can confirm that we have found bugs in large test suites that were caused by an interaction between cases.  These would have been missed by granular execution.  I have also seen the immense waste of time that accompanies granular cases.  Not mentioned in the study is also the fact that granular cases tend to require a lot more maintenance time. 

My rule of thumb is to create differentiated test cases for most instances but then to utilize a test harness that allows them to be all run in one instance of that harness.  This gets the benefits of a large test suite without many of the side effects of putting too much into one case.  It amortizes program startup, device enumeration, etc. but still allows for more precise tracking and easier reproduction of bugs.  If there is a lot of overhead, such as the DVD case mentioned above, test cases should be merged or otherwise structured so as not to pay the high overhead each time.

Thursday, September 25, 2008

This Blog Makes Top 100 Software Development Management Blogs

Just barely, but I made the list.  It is determined by Technorati authority, Alexa rank, Google page rank, etc.

Check out the list as there are a lot of interesting blogs on it.  The top 10 are:

Nr Site

1 Joel on Software

2 Coding Horror

3 Seth's Blog

4 Paul Graham: Essays

5 blog.pmarca.com

6 Rough Type

7 Scott Hanselman's Computer Zen

8 Martin Fowler's Bliki

9 Rands in Repose

10 Stevey's Blog Rants

That's some esteemed company to be even mentioned with.

Wednesday, September 17, 2008

Metallica's Death Magnetic Poorly Mastered

Metallica's new CD, Death Magnetic, is pretty good.  Certainly it is better than St. Anger although I suppose that's not setting the bar very high.  This CD is closer to And Justice For All than anything Metallica has done in the last decade.  Unfortunately, the CD is mastered very hot. Basically, the CD is authored so loud that there isn't much range between loud and quiet and the loud becomes distorted.  Ryan explains this phenomenon quite well and in a lot more detail. 

The fact that Kotaku is running an article about this means it has gotten the attention of people beyond the audiophile community.  Their claim is that the Guitar Hero versions of the same songs is much better.  I've heard Amazon MP3s are a lot less hot than CDs generally.  I wonder if they fix this particular case.

We can only hope that the negative reaction this CD is getting in some sectors shows a trend and that CD mastering will go back to where it once was.  Having to turn up the CD to make it loud isn't a bad thing.

Friday, September 5, 2008

Not Everyone Has the Same Definition of "Done"

Years ago I had an employee, let's call him Vanya (not the real name).  He was struggling a bit so I was watching his work closely.  Every week we discussed what he needed to get done the next week and what he had done the previous week.  I kept a list of the work items he needed to complete and checked them off when he was done with each.  For one particular work item which was testing a particular DirectShow filter, the item on the list was writing tests for it.  One week he worked on and completed this work.  A few months later we became aware of an issue that would fundamentally cause the filter to not work.  In fact, it had probably never worked.  Why, I wondered, didn't Vanya's tests catch it?  I went to speak with him.  It turns out, he had written the tests.  They had compiled. He had not, however, ever actually run them.  They were "done" in his mind, but not in mine.  Oh, and what he had written didn't actually work.  Shocking, I know.


I tell you this story to introduce a problem I've run into many times on many different scales.  This story is probably the most aggregious, but it is certainly not isolated.  The problem stems from the fact that we rarely define the word.  It is assumed that everyone shares a definition but it is rarely true.  Is a feature done when it compiles?  When it is checked in?  When it can run successfully?  When it shows up in a particular build?  All of these are possible interpretations of the same phrase.


It is important to have a shared idea of where the finishing line is.  Without that, some will claim victory and others defeat even when talking about the same events.  It is not enough to have a shared vision of the product, it is also necessary to agree on the specifics of completion.  To establish a shared definition of done, it is necessary to talk about it.  Flush the latent assumptions out into the open.  Before starting on a project, it is imperative to have a conversation about what it means to be done.  Define in strict terms what completion looks like so that everyone will have a shared vision.


For large projects, this shared vision of done can be exit critera.  "We will fix all priority 1 and 2 bugs, survive this many hours of stress, etc."  For small projects or individual features in a large project, less extensive criteria is needed, but it is still important to agree on what will be the state on what dates.


While not strictly necessary, it is also wise to define objective tests for done-ness.  For instance, when working on new features, I define "done" as working in the primary scenarios.  Bugs in corner cases are acceptable, but if a feature can't be exercized in the main way it was intended to be, it can't be tested and isn't complete.  To ensure that this criteria is met, I often insist on seeing the feature demonstrated.  This is a bright line.  Either the feature can be seen working, or it cannot.  If it can't, it isn't done and more work is needed before moving on to the next feature.

Tuesday, September 2, 2008

My PAX08 Experience

Penny Arcade Expo (PAX) is an annual gaming convension in Seattle put on by the guys at Penny Arcade.  It covers all aspects of gaming from consoles to PC games to roleplaying and tabletop games.  It is big.  Very big.  40,000 tickets pre-sold kind of big.  This was my second year attending.  Last year I dipped my toe in the water.  This year I came back and dove in fully.  I was there all 3 days for most of the time the doors were open.  I had a great time and intend on attending again next year.  Here are some of the highlights:


Felicia Day and The Guild.  The Guild is an online video series which pokes fun at MMORPG players.  I had only seen 2 episodes before coming to PAX.  We watched the whole thing and then it was followed by a Q&A afterwards.  The video is hilarious.  The Q&A great.  Felicia Day is a fun speaker and her cohorts were quick-witted, especially Sandeep who plays the "love interest" in the show.


Wil Wheaton.  Last year's keynote speaker was back.  He was available for book signings and was on 2 panels that I'm aware of.  I saw him on the "Is casual gaming killing hardcore?" panel and on his panel of one.  For his own panel he read a selection from his latest book and one of his ST:TNG reviews.  He then took Q&A from the audience.  If you ever get a chance to see him in person, jump at the opportunity.  I'm still kicking myself for missing his keynote last year.


The Expo Hall.  Filled with the latest in gaming goodness.  Gears of War 2?  Check.  Starcraft 2?  Check.  Fallout 3?  Check.  ChronoTrigger DS?  Check.  Even some board gaming companies like Wizards of the Coast and Fantasy Flight Games were there.


Ken Levine's keynote.  The lead designer of Bioshock gave the keynote.  I didn't really know much about him beforehand and didn't expect a whole lot.  He exceeded my expectations and gave a great speech.  Mostly it was a humorous approach to his biography.  He tells of when he first encountered D&D, first got hired at Looking Glass and found people like him, etc.  If you can find the audio of this online, give it a listen.


Omegathon.  The Omegathon is a 6-round competition through all aspects of gaming.  This year involved Peggle, Pictionary, Geometry Wars, Rock Band 2, Jenga, and Vs. Excitebike (on a 1986 Nintendo Home Computer no less).  Watching 3,000 people cheer for Vs. Excitebike is an experience like none other. 


Overall, it was great fun.  I'll definitely be going again next year.

Friday, August 15, 2008

Code Review Options

There are many ways to conduct a code review.  Here are a few ways I've seen it done and the advantages and disadvantages of each.

Over-the-Shoulder Reviews

Walk over to someone's office or invite them to yours and walk them through the code.  This has the advantage that the author can talk the reviewer through the code and answer questions.  It has the disadvantage that it pressures the reviewer to hurry.  He won't want to admit he doesn't understand and will sign off on something without really validating it.  It also doesn't work for teams that are not co-located.

E-mail Based Reviews

This model requires some method of packaging the changes.  This is then e-mailed to another person for review.  The reviewer than then open the code in WinDiff or a similar tool and review just the deltas.  This tends to be efficient and allows the reviewer ample time to read and understand the code.  The downside is that the reviewer can take fail to prioritize the review correctly and it can sit around for a long time.

Centralized Reviews

Code reviews are sent (via an e-mail based system usually) to a centralized team of trained code reviewers.  These are usually the senior coders.  It has the advantage of helping to maintain high quality and uniformity in the reviews.  In a team trying to change coding styles or increase the quality of their code, this can be  a great way to do so.  The downside is that this team becomes a bottleneck.  If only a small portion of the team must review all the code, they can fall behind and reviews can back up.  Being part of the central review team can also be a drain on the most efficient coders.  Instead of writing code, they spend a large portion of their time reviewing code.

Decentralized Reviews

In this format, everyone in the team participates.  Any person can review any other person's code.  This form scales most easily with team size but can require some tools if it is to work on a large team.  Otherwise it becomes too hard to tell which people are participating and which are not.  The advantage of this form is that everyone is exposed to both sides.  This allows junior members to learn by reading code written by more experienced members.  The disadvantage is that the quality of the reviews is uneven.  Different members will have different abilities.  Over time this should even out as the team grows together.

Group Reviews

So far I've been speaking of reviews which involve only two people.  The reviewer and the reviewee.  There is another model in which a group gathers together in a room and the reviewer leads them through the code.  This model puts a lot of eyeballs on the code and is likely to find the issues better than any individual reviewer, but it also costs a lot of eyeballs.  This model uses the most manpower and is the least efficient reviewing model.  It suffers the same problems as the over-the-shoulder reviews except exacerbated.  The likelihood of people not being able to follow is high.  Additionally, the review will likely go slowly as people bring up questions about various points.  Finally, it may bog down into argument between the reviewers.  This model can be improved if participants review the code ahead of time and come prepared to only talk about their issues.  If they reviewers aren't reading the code in the meeting, it can be efficient.  Sometimes this is called a code inspection.

What We Use

There is no single right way to conduct reviews.  I won't pretend to proscribe a single manner of conducting them that will fit all organizations.  I will, however, tell you what I've found to work.  My team uses a distributed e-mail model.  We have a tool which will take the diff of the latest code in the repository and the code on your box and package it up.  The reviewee then sends mail to a mailing list asking for someone to review his or her code.  A reviewer volunteers and responds letting everyone know he is taking the review.  The reviewer then reads the code, sends his comments to the reviewee.  The reviewee then makes any required changes and eventually checks in the code.

Wednesday, August 13, 2008

Code Review Rights and Responsibilities

Code reviews are an important part of any project's health.  They are able to find and correct code defects before making it into the product and thus spare everyone the pain of having to find them and take them out.  They are also relatively cheap.  Assuming your team wants to implement code reviews, it is important to lay out the expectations clearly.  Code reviews can be contentious without some guidelines.  What follows are the rights and responsibilities as I see them in the code review process.

Participants:

Reviewer - Person (or persons) reviewing the code.  It is their job to read the code in question and provide commentary on it.

Reviewee - Person whose code is being reviewed.  They are responsible for responding to the review and making necessary corrections.

Must Fix Issues:

A reviewer may comment on many aspects of the code under review.  Some of the comments will require the reviewee to change his code.  Others will be merely recommendations.  Must fix issues are:

  • Bugs - The code doesn't do what it was intended to do.  It will crash, leak memory, act erroneously, etc.
  • Potential maintenance issues - The code is not broken, but is written in such a way that it will be hard to maintain.  Examples might be magic numbers, poorly named variables, lack of indirection, lack of appropriate comments, etc.
  • Coding standard violations - If the group has a coding standard, it must be followed.  Deviations from it must be fixed when pointed out.

Recommendations:

Other items are merely recommendations.  The reviewer can comment on them, but the comments are only advisory.  The reviewee is under no obligation to fix them.  These include:

  • Architectural recommendations - The reviewer thinks there is a better way to accomplish the goal.  Seriously consider changing these, but the reviewee can say no if he disagrees.
  • Style issues - The reviewer wouldn't have done it that way.  Fascinating.

Code Ownership:

In my teams there is no ownership of code.  Some people touch certain pieces of code most often and may even have written the code initially.  That doesn't give them special rights to the code.  The person changing the code now does not need to get the initial writer's permission to make a change.  He would be a fool not to consult the author or current maintainer because they will have insights that will help make the fix easier/better, but he is under no obligation to act upon their advice. 

Thursday, August 7, 2008

The Company You Work For Matters

In an episode of Stack Overflow Podcast, Jeff Atwood made an interesting point.  He spoke of the difference between companies that deliver code as their product (like Microsoft) and companies who use code to support other business interests (the IT department inside Weyerhauser for example).  In a company whose business model is to make and sell software, making the software incrementally better supports the business function and is thus rewarded.  In an IT department, once the project crosses a certain threshold, the returns on making it better diminish rapidly.  Improving the code is often discouraged.  All this has been said before.  Joel Spolsky has talked on this subject as have I. 

What Jeff added to this conversation was a practical application.  He rightly pointed out that you need to be aware of the type of person you are and the type of company you are working for.  If you love to code, you really don't want to work in an IT department.  Sure, someone will pay you to code, but you'll be frustrated by the limitations on your work.  If you enjoy programming, you want to work for a company whose job it is to produce software.  On the other hand, if you are willing to program but it's just a job, you don't want to work in a software house.  An IT department will be a better fit and you will find your career better served by working there.  In an software house, you'll be asked to give more of yourself and be more creative than you might otherwise like to.

Test Code Must Be As Solid As Dev Code

All good development projects follow certain basic practices to ensure code quality.  They use source control, get code reviewed, build daily, etc.  Unfortunately, sometimes even when the shipping product follows these practices, the test team doesn't.  This is true even here at Microsoft.  It shouldn't be the case, however.  Test code needs to be just as good as dev code.

First flaky test code can make determining the source of an error difficult.  Tests that cannot be trusted make it hard to convince developers to fix issues.  No one wants to believe there is a bug in their code so a flaky test becomes an easy scapegoat.

Second, spurious failures take time to triage.  Test cases that fall over because they are unstable will take a lot of time to maintain.  This is time that cannot be spent writing new test automation or testing new corners of the product.

Finally, poorly written test code will hide bugs in the product.  If test code crashes, any bugs  in the product after that point will be missed.  Similarly, poor test code may not execute as expected..  I've seen test code that returns with a pass too early and doesn't execute much of the intended test case.

To ensure that test code is high quality, it is important to follow similar procedures to what development follows (or should be following) when checking in their code.  This includes getting all non-trivial changes code reviewed, putting all changes in source control, making test code part of the daily build (you do have a daily build for your product don't you?), and using static verification tools like PCLint, high warning levels, or the code analysis built into Visual Studio.

Saturday, August 2, 2008

Cause of "Internet Explorer cannot open the Internet Site" found

Perhaps you, like me saw a rash of sites giving the error "Internet explorer cannot open the Internet Site" yesterday.  At first I thought one of my machines was messed up.  Then I saw it on another machine.  This one running XP.  A virus perhaps?  I can't recall doing the same thing on both machines.  How would I get a virus on both?  A worm maybe?  Updated the antivirus just in case.  This morning the errors seemed to be gone but still the mystery.  What caused it?


It appears that a tool called SiteMeter was causing the problem.  Mystery solved.  More detailed information here.

Wednesday, July 30, 2008

Loving My Eee 1000H

I was attracted to the "netbook" market with the release of the initial Eee PC from Asus.  The laptop was cheap and very small.  Unfortunately, it had a really small screen and an even smaller keyboard.  Then the next generation of netbooks was announced including the MSI Wind and the Eee 1000.  These are a bit pricier but still light.  They have bigger screens and keyboards and look quite usable.  I'm tired of carrying my 6 lb. laptop around on trips and so I decided I would take the plunge on one of these new devices.


At first I was attracted to the MSI Wind.  It is a little lighter than the 1000H and was supposed to be $150 cheaper.  When the Wind didn't ship, then shipped with only a 3-cell battery, then raised the price, I looked around and settled on the Eee 1000H.  What follows is my review of the 1000H.


The screen on the 1000H is gorgeous.  It's 1024x768 and is bright and clear.  It has a matte finish so it can be used with your back to a window or even outside.  It is bright enough that I usually run it on 1/2 brightness and it still works just fine.  The Eee has a really cool feature which allows you to change the screen resolution with the press of a button.  You can set it to 1024x600, 800x600, 1024x768 (which seems to cut off the bottom of the screen, and 1024x768 compressed.  This latter mode is very useful for programs that insist on a square aspect ratio.  One other nice feature is there is a button to turn off the screen.  This comes in handy for privacy or saving battery life.


The keyboard on the 1000H has received some criticism for being a little loose.  There is a little flex in the right-side of the keyboard.  It doesn't seem to be fully fastened to the tray beneath it.  It's not bad but does take some getting used to.  The keys are plenty big that I can easily touch-type on it.  The one downside is the right-shift key.  It is located to the right of the up arrow key.  There's no easy way to touch-type like that.  Luckily, there is a very cool utility called SharpKeys that allows you to swap the two.  After doing that, all is well.


The 1000H comes with a 1.6 GHz Atom processor.  This appears to be plenty fast enough for browsing the web, coding, writing documents, etc.  It's not going to set any land speed records but it works fine.  It does run quite cool though.  The Eee doesn't get hot even after hours of use.  I've tried a few older games on the system and it plays them fine.  Anything modern is probably too much for the Intel 945 graphics chip.


The 1000H ships with Windows XP SP3 Home.  I upgraded to Professional so I could join the domain at work.  I intend to try Mojave Vista on it which reportedly works, but I'll wait for my 2 GB memory to arrive first.  I must say that after using Vista for a few years, XP feels very antiquated.


The speakers have some sort of "Dolby Sound Room" thing on them.  I haven't looked into what that might actually be but I can say that the sound is much better than you would expect out of a laptop.


I find the size and weight to be just about right.  The Eee at 3.2 lbs is not quite as light as I expected, but it's pretty light.  The size is small.  It's literally 1/2 the size of my previous Dell Inspiron 6400.  The battery sticks out slightly which actually makes a great handgrip when carrying it.  The system is well balanced and feel very sturdy.  The case is a high-gloss black and does attract fingerprints. 


Finally, the battery life.  I took it to an all-day conference on Friday and it lasted all day without a recharge.  The battery is rated at 4.5-5 hours and that seems to correspond well with my experience so far.


So, am I glad I bought the Eee over the Wind?  Yes.  The Wind is lighter and the keyboard probably doesn't have the flex in it.  However, the Eee has many advantages.  It has 802.11n wireless networking.  The compressed screen resolution is nice.  The touchpad is a little bigger than the one on the Wind.  The Eee can be overclocked via software.  Another advantage is that the Eee can be upgraded (memory or hard drive) without voiding the warranty.


If you want more information, check out these great forums:


http://forums.msiwind.net/


http://forum.eeeuser.com/


 

Tuesday, July 15, 2008

10 Pitfalls of Using Scrum in Games Development

Interesting article about using scrum to manage game development.  Many of the pitfalls are true beyond games development.  The article is well balanced and has advice for how to overcome the pitfalls.  I don't agree with all of the advice, but it is thought provoking.  For example, the article makes a good point that daily standup meetings can be disruptive to the thought process.  It therefore recommends using an electronic means of tracking people that can be filled in at leisure.  I think it too quickly dismisses the collaborative effect of a standup meeting and overplays the disruptive nature.  Sure, it's a disruption, but so is lunch.  Schedule the two together.  :)  I've found that for many projects a daily meeting is unnecessary and instead meet only 2 or 3 times per week. Less disruption, same benefits.


 

Thursday, July 10, 2008

Becoming a Manager: Losing Direct Control

When my wife was expecting our daughter, someone gave me this advice, "When you have your first child, you lose all your free time.  When you have your second, you lose all the free time you didn't realize you still had."  Becoming a manager* can be a similar experience.  When you become a lead, you lose direct control.  Instead, you have to trust what others tell you.  Very recently we had a small re-org at work and I'm transitioning from a lead** to a manager and I'm quickly finding out that I have now lost all that control I didn't realize I had.

As an individual contributor, you have complete control.  Maybe someone tells you what to do, but when it comes to executing, everything that you do gets done exactly how you want it to be done.  As a result, you know first hand the status of your part of the project.  Becoming a lead results in a loss of this control. Instead of doing the work, you have to tell others to do the work.  This results in work being done in ways you may not have intended.  You no longer have direct knowledge of the state of the project, but rather have to rely on what your team is telling you.

Becoming a manager amplifies this state of no direct control much farther.  As a lead--it turns out--you still have a lot of control.  You get to tell your team what to do and (sometimes) how to do it.  You then get to directly monitor their work.  As a result, you have direct knowledge of what they are working on and how they are attempting to accomplish it.  If something isn't to your liking, you can request a change.  As a manager of leads, there is an extra level of indirection added to the mixture.  This extra level of indirection is known as a lead and all of your instructions will be filtered through this person.  They will be applying their ideas of how things should be done before passing on instructions to the individual contributors who will then apply their own opinion before anything is actually accomplished.  This adds a lot more variance to the outcome.

As a brand new manager I don't yet have any tried and true strategies for dealing with this loss of control.  I suspect it means being a lot more careful with what you measure.  At the lead level you are interacting with the individual contributors often enough (you are having 1:1s aren't you?  and scrum standup meetings?) that you have a good pulse of the project.  You don't need to be terribly precise in what you monitor because you can measure almost everything.  As a manager, your purview is too large to measure everything.  Instead, you'll only be getting a small amount of information from each individual contributor.  Thus, picking the right things to monitor becomes a critical factor in your success or failure.

As with the lead, there is a fine line to be walked between being aloof and micromanaging (or interfering as it might be known at the manager level).  When the work is being done by people who are not direct child nodes of yours, how do you interact enough to know what is going on but not so much that you disintermediate the relationship?  These are all interesting questions I'm now facing.  As I gain more experience, I'll try to revisit this topic with some advice on what does and doesn't work.

-----

* For the purpose of this post, a manager is someone who manages other managers or leads.  This position is sometimes referred to as an M2 or manager of managers.

** A lead in this context is someone who manages individual contributors but not other managers.

Monday, June 23, 2008

Get Out of E-mail and Walk Down the Hall

I was about to write this article anyway when XKCD posted this comic which reinforces my point.  People act differently in email than they do in person.  Everyone knows this to be the case, but they often don't act like it.  Usually when someone talks about how email is different it comes in the context, as in the comic, of a flame war.  It's very easy to misunderstand someone's e-mail and assume it is more aggressive than it really is.  However, the lack of subtle emotion isn't the only downside of email.  There are times to use email and times when it isn't the right tool.  Knowing the downsides of email can allow us to better understand when not to use it.  Sometimes it is better to put down the Outlook and walk down the hall.

Some people are addicted to email.  For them, it is the only communications medium.  However, just as email has its benefits--low-friction communication medium, low interruption value, near-instant transmission time--it also has its downsides.  An impersonal nature is one of them.  While not as often recognized, so is the infinite time and space allowed.  Too much space removes the forcing factor present in conversation to boil things down to key points.  E-mail is not a good decision-making tool for this very reason.  Think about it.  How many times have you seen a discussion in email about how to implement a feature or fix a bug get bogged down in tediously long message threads with loads of new text in each message?  It can be very hard to get resolution to a contentious issue in email because email doesn't make you focus.

When there are no size and time limitations, it is easy to (attempt to) refute every point in at argument with each message.  In a person to person conversion, people can't keep a dozen arguments in their mind at once.  They are forced to focus on only the most important points.  In email, each minute point can be a breeding ground for argument.  With this point-by-point refutation, it is also easy to get lost in the minutia.  Email doesn't solve the problem that people can't keep a dozen arguments in their mind at once and so by bullet point 8, what was stated in bullet point 1 is forgotten and often contradictory arguments are raised.  In the legal profession this is called arguing in the alternative and expected.  In the rest of the world, it just makes you look dumb.  It certainly doesn't help come to a consensus answer.

Something else happens in real conversation that is missing in email.  When two people are discussing something, one person will often stop the other and drill down on something that was just said.  In email, this opportunity is lost.  It's impossible to stop someone mid-mail and ask a clarifying question.  Instead, the question is asked after the fact.  This either just adds to the complexity of the thread or distorts it because the answer would have affected the rest of the message.

While trying to hammer out a decision in email is enticing, actually getting to a decision can be hard.  Instead of just bouncing mails back and forth, stop.  Think.  Is this something that would be better handled in person where emotions are visible, communication can be interrupt-driven, and time forces a focus on the most critical points?  If so, walk down the hall or schedule a meeting.  My rule of thumb is to try email first.  When it works it is very efficient.  However, if email fails to produce results in a few messages, I pick up the phone or find the person to talk.  If its a larger group, I schedule a meeting.  Try it.  Decisions will come much faster.

For some tips on keeping meetings running smoothly, check out my post on the subject.

Saturday, June 21, 2008

Vim Tip: My .vimrc File

.vimrc is the config file for Vim.  It can be stored in the Vim directory or in your user directory.  With greater protection of the Program Files directory on Vista, I've gotten into the habit of keeping it in my user directory (c:\users\steverowe on most systems).  here are most of the non-standard options I have in my .vimrc file.  Maybe you can pick up some pointers.


"set tabs to 4 spaces.
set tabstop=4
set expandtab
set shiftwidth=4

"automatically indent
set smartindent
set cindent

"case insensitive search
set ignorecase
set smartcase

"search the whole build tree for ctags
set tags=tags;/

"open the window larger than normal (100 wide by 40 tall)
win 100 40

set nocompatible
"allow for c,w to change part of a camel-cased word
source $HOME/camelcasemotion.vim

"make it so mouse and keyboard don't exit select mode."
"this makes it so we can select with the mouse and then act on that block."
set selectmode=""

"make long-line navigation work like other windows apps
map <DOWN> gj
map <UP> gk
imap <C-UP> gki
imap <C-DOWN> gji

"from here down is the default _vimrc
set nocompatible
source $VIMRUNTIME/vimrc_example.vim
source $VIMRUNTIME/mswin.vim
behave mswin

set diffexpr=MyDiff()
function MyDiff()
  let opt = '-a --binary '
  if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif
  if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
  let arg1 = v:fname_in
  if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' | endif
  let arg2 = v:fname_new
  if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' | endif
  let arg3 = v:fname_out
  if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' | endif
  let eq = ''
  if $VIMRUNTIME =~ ' '
    if &sh =~ '\<cmd'
      let cmd = '""' . $VIMRUNTIME . '\diff"'
      let eq = '"'
    else
      let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"'
    endif
  else
    let cmd = $VIMRUNTIME . '\diff'
  endif
  silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . eq
endfunction

Monday, June 16, 2008

June Netcast Update

By popular demand (seriously), here is an update of the netcasts I'm listening to on a regular basis.

 

Audio:

  • This Week In Tech - Round table discussion of technology topics.  Sometimes should be known as This Week in Twitter.
  • This Week In Media - Round table discussion of issues affecting media.  Everything from DRM to Red cameras.
  • Windows Weekly - Everything Microsoft.
  • Manager Tools - Great resource for both aspiring and current managers.  Practical advice.
  • Stack Overflow - Joel Spolsky (Joel on Software) and Jeff Atwood (Coding Horror) chatting and we get to listen in.  A bit rough, but fun and informative.
  • I, Cringely - Robert X. Cringley reading his weekly column.  Not always correct, but usually entertaining.
  • FLOSS Weekly - Interviews with the names behind common open source projects.

 

Video:

 

Suggestions for additional podcasts are welcome.

Wednesday, June 11, 2008

Windows Home Server Power Pack 1 Beta Is Available

At long last, there is a preliminary fix for the corruption issue that has dogged WHS since its release.  The WHS team released the fix with its Power Pack 1 beta.  See their blog post for details and a link to download it.  In addition to the corruption fix, many other bugs are fixed and it is now possible to back up your shared folders to an external drive.  The power pack also adds supports for connecting x64 machines.

I've been using Windows Home Server for several months now and find the ease of backup unparalleled.  Just connect your machines to the server and they will be backed up each night.  No need to fiddle with anything.  I've been using early versions of the power pack and have found it very stable.  It's still a beta so treat it as such, but in my experience it's solid.  If you are running WHS, consider trying out the beta.

Saturday, June 7, 2008

Vim Tip: Better Searching

Two things I discovered about searching:


* will search forward for the word under the cursor.  No longer do I have to type /WordUnderTheCursor.


# does the same thing, but goes backwards.  It's like ?WordUnderTheCursor.


 


g* will search for any word containing the word under the cursor.  So g* on the word count will find count, GetCount, Counter, etc.


g# is the same thing in reverse.

Friday, June 6, 2008

Better Writing

The Manager Tools podcast has an interesting series on better writing.  This isn't a management-specific topic.  Rather it is something everyone can benefit from.  In a day and age where so much communication is via e-mail, having the ability to communicate your thoughts clearly and quickly is important for everyone.  One of the points the podcasts make is to keep your writing succinct and readable.  Be careful how many 3+ syllable words you use and how long your sentences are.  Put the main points up front.  Save context for an explanation after the main point or just leave it out.  Business e-mails are not a place to increase the drama by building up to the main point.  A professor once told me that in technical papers, you should be able to understand the paper by just reading the first sentence of every paragraph.  This is true of all good technical and business writing.  There are some other good tips in the podcast.  Put it on your Zune/iPod and give it a listen.

Part 1

Part 2

Wednesday, June 4, 2008

Test For Failure, Not Success

We recently went through a round of test spec reviews on my team.  Having read a good number of test specs in a short period of time, I came to a realization.  It is imperative to know the failure condition in order to write a good test case.  This is at least as important if not more important than understanding what success looks like.

Too often I saw a test case described by calling out what it would do, but not listing or even implying what the failure would look like.  If a case cannot fail, passing has no meaning.  I might see a case such as (simplified): "call API to sort 1000 pictures by date."  Great.  How is the test going to determine whether the sort took place correctly?

The problem is even more acute in stress or performance cases.  A case such as "push buttons on this UI for 3 days" isn't likely to fail.  Sure, the UI could fault, but what if it doesn't?  What sort of failure is the author intending to find?  Slow reaction time?  Resource leaks?  Drawing issues?  Without calling these out, the test case could be implemented in a manner where failure will never occur.  It won't be paying attention to the right state.  The UI could run slow and the automation not notice.  How slow is too slow anyway?  The tester would feel comfortable that she had covered the stress scenario but in reality, the test adds no new knowledge about the quality of the product. 

Another example:  "Measure the CPU usage when doing X."  This isn't a test case.  There is no failure condition.  Unless there is a threshold over which a failure is recorded, it is merely collecting data.  Data without context is of little value.

When coming up with test cases, whether writing them down in a test spec or immediately when writing or executing them, consider the failure condition.  Knowing what success looks like is insufficient.  It must also be possible to enumerate what failure looks like.  Only when testing for the failure condition and not finding it does a passing result gain value.

Tuesday, June 3, 2008

What Won't Our Kids Ever Know?

A friend of mine just posted an interesting anecdote about the difference in the world we grew up in and the one our kids are growing up in.  In his case, his son didn't know what a stereo was.  He'd never seen one.  Music in his world comes from an iPod/Zune or from a computer.  That got me thinking.  Technology is changing the world quite drastically.  What other things that were common in my childhood will my kids never know about?

They won't know telephones that have wires.  All of ours are cordless (or cellular).

They won't know a world where you only have a handful of TV channels.  We visited my grandparents' and they were perplexed by the fact that there were only 3.5 channels.

They don't understand live TV.  Everything in their world is timeshifted by Media Center.  TV schedules are an unknown to them.

They won't ever have to think about long distance phone calls.  Calling Florida is no more expensive than calling next door.

They'll never know a world where the internet is not at their fingertips at all times.  Modems?  What are those?  Encyclopedias?  What are those?

No Saturday morning cartoons.  This doesn't really fit the list, but it's true.

 

I'm sure there's a lot more that could be added to this list.  What other things will kids of this generation never experience?

Monday, June 2, 2008

Refactor To Make Immediate Change Easier

Jeremy Miller gives his reasons for refactoring.  He gives two over-arching reasons.  The first is "To remedy a deficiency in code, design, or architectural quality" and the second, "To make a forthcoming change to the code easier."  I'm very much in agreement with the second, but the first makes me nervous.  Refactoring is not an end to itself.  Changing code to make it of higher quality without an immediate purpose in mind strikes me as wasteful.  Code doesn't need to be pretty until it is being maintained.  The compiler doesn't care how ugly the code is.  The reason to make code of higher quality is because someone will may have to change that code and it will be hard to change in its low-quality state.  However, if change is not imminent, cleaning up the code now is a non-optimal decision.  Suppose the code continues working and no change is necessary in that part of the code base.  Because the compiler doesn't care and no human looks at it, the effort to make it higher quality is wasted.  Instead, it is better to wait until the change is needed to make the updates.  This would seem to be in line with the Lean principle of waiting until the last responsible moment or just in time delivery.  It is better to wait than to refactor pre-emptively.  Refactoring can become a yak-shaving exercise if one is not careful.  To be fair, Jeremy does end with this advice:  "If a structural problem in the code isn't causing any immediate harm or friction, you probably leave it alone for now."

Saturday, May 31, 2008

Taking Advantage of Vim

Once you have mastered using Vim to replace Notepad.exe, it is time to starting taking advantage of what Vim has to offer.  Doing so can increase your productivity.  Below are most of the commands I use most frequently.  It is important to note that Vim has a veritable cornucopia of commands and thus supports many different usage styles.  What is presented here are just a fraction of the available commands.

Many commands in Vim have a similar format.  This format is [repetitions][command][movement].  For instance, 2dw will delete the next 2 words.

Useful commands that take this format include:

Command Action
c Change.  Delete the text moved over and enter insert mode.
d Delete.  Delete the text moved over.
y Yank.  Copy the text moved over.

No number implies 1.  The combination cw will delete the rest of the word under the cursor and enter insert mode.  This is probably the most commonly used combination for me.

There are two more variants on these commands.  A capital letter will execute the command to the end of the line.  D will thus delete the rest of the line.  Two repeated letters will execute the command on the entire line.  Thus cc changes the whole line and 2yy yanks the next 2 lines.

Common movement commands include:

Movement Action
w word.  A single word.
b word back.  A single word, backward.
) sentence.  A single sentence.
h left.  One character to the left.
j down.  One line below.
k up.  One line up.
l right.  One character to the right.

Movements can be issued without a command in front of them.  2w will move the cursor 2 words to the right.  You can maneuver all over the document using hjkl instead of the cursor keys if you like.  Personally, I use the cursor keys and only use l when I want to change some number of characters.  5cl will delete 5 characters and enter insert mode.

Some commands operate without a movement.  These include:

Command Action
x Delete one character
~ Change the case of one character.
r Change one letter and return to normal mode.

These commands can accept a number.  Thus 5x will delete the next 5 characters.

Other useful commands:

:<line number> Jump to that line number
% If on top of a ( or {, jump to the matching one.  Very useful in coding.
m<letter> Sets a bookmark labeled <letter> at the cursor.
'<letter> Returns to <letter> bookmark.  Useful for jumping around a file.
u Undo the last change.  Useful if you forgot you weren't in insert mode.
gg Go to the top of the file.
G Go to the bottom of the file.
>> Increase indent.
<< Decrease indent.
o Insert a new line below and enter insert mode.

These commands, in addition to the search and replace command introduced in the notepad post are the ones I find myself using most frequently.  Once you become accustomed to them, editing in something without them will feel strange.  I want to hit 2cw to change the next 2 words in Word all the time.  I find the /search very useful also and miss it whenever editing in something that does not have Vim keybindings.  My repertoire is fairly limited presently.  As I discover new ways of doing things in Vim, I'll post them as Vim tips.  If there are commands you use frequently that I don't discuss above, please mention them in the comments.

Friday, May 30, 2008

We Need A Better Way To Test

Testing started simply.  Developers would run their code after they wrote it to make sure it worked.  When teams became larger and code more complex, it became apparent that developers could spend more time coding if they left much of the testing to someone else.  People could specialize on developing or testing.  Most testers in the early stages of the profession were manual testers.  They played with the user interface and made sure the right things happened.


This works fine for the first release but after several releases, it becomes very expensive.  Each release has to test not only the new features in the product but also all of the features put into every other version of the product.  What took 5 testers for version 1 takes 20 testers for version 4.  The situation just gets worse as the product ages.  The solution is test automation.  Take the work people do over and over again and let the computer do that work.  There is a limit to the utility of this, but I've spoken of that elsewhere and it doesn't need to be repeated here.  With sufficiently skilled testers, most products can be tested in an automated fashion.  Once a test is automated, the cost of running it every week or even every day becomes negligible. 


As computer programs became more complex over time, the old testing paradigm didn't scale and a new paradigm--automated testing--had to be found.  There is, I think, a new paradigm shift coming.  Most test automation today is the work of skilled artisans.  Programmers examine the interfaces of the product they are testing and craft code to exercise it in interesting and meaningful ways.  Depending on the type of code being worked on, a workforce of 1:1 testers to devs can usually keep up.  This was true at one point.  Today it is only somewhat true and tomorrow it will be even less true.  Some day, it will be false.  What has changed?  Developers are leveraging better programming models such as object-oriented code, larger code libraries, greater code re-use, and more efficient languages to get more done with less code.  Unfortunately, this merely increases the surface area for testers to have to cover.  Imagine, if you will, a circle.  When a developer is able to create 1 unit of code (r=1), the perimeter which a tester must cover is only 3.14.  When the developer uses tools to increase his work and the radius stretches to 2, the tester must now cover a perimeter of 12.56.  The area needing to be tested increases much faster than the productivity increase.  Using the same programming models as the developers will not allow test to keep up.  In the circle example, a 2x boost in tester performance would only cover 1/2 of the circle.


Is test doomed?  Is there any way to keep up or are we destined to be outpaced by development and to need larger and larger teams of test developers just to keep pace.  The solution to the problem has the same roots as the solution to manual testing problem.  That is, it is time to leverage the computer to do more work on behalf of the tester.  It will soon be too expensive to hand-craft test cases for each function call and the set of parameters it entails.  Writing code one test case at a time just doesn't scale--even with newer tools.  In the near future, it will be important to leverage the computer to write test cases by itself.  Can this be done?  Work is already beginning, but it is just in its infancy.  The tools and practices that will make this a widespread practice likely do not exist today.  Certainly not in a readily consumed form.


This coming paradigm shift makes testing a very interesting place to be working today.  On the one hand, it can be easy for testers to become overwhelmed with the amount of work asked of them.  On the other hand, the solutions to the problem of how to leverage the computer to test itself are just now being created.  Being in on the ground floor of a new paradigm means the ability to have a tremendous impact on how things will be done for years to come.


 


Update:  There are a lot of people responding to this post who are unfamiliar with my other writing.  Without some context, it may seem that I'm saying that test automation is the solution to all testing problems and that if we're smart we can automate all of the generation.  That's not what I'm saying.  What I advocate in this post is only a powerful tool to be used along with all of the others in our toolbox.  If you want some context for my views, check out:



 

Saturday, May 24, 2008

GVim As Notepad

When I first encountered Unix in the early 1990s, I needed a text editor.  I tried Emacs but the meta key and double control keys struck me as wrong.  I tried Vi but couldn't figure out how to type anything.  I came across Pico and for years used that as my editor.  Why?  I wasn't doing much other than modifying some shell scripts or dot files and it was easy.  All the commands I needed were listed at the bottom of the screen.  Pico is the Notepad.exe of the Unix world.  Years later I was forced to do some programming on a Linux system via an ssh connection.  Needless to say, Pico isn't really a great programming editor.  I had a friend who was really excited about Vim (Vi Improved) at the time so I gave that a try.  Emacs still didn't sound inviting. 


I began by reading tutorials on the web.  They all intended to get me up to speed on all the nifty functions in Vim very quickly.  For instance, most tutorials start by teaching that hjkl are the cursor keys.  They are, but you don't really need to know that for basic functionality.  The ones with arrows on them will work just fine for most purposes.  Options like this serve just to confuse at the beginning.  The trouble is, I can only learn so much at once.  Before I could learn how to run, I had to learn how to walk.  I needed to be comfortable doing the basics before I could grok the extra stuff.  I needed to be able to use Vim like notepad functionality before I could move on to various visual modes, regular expressions, and about 80 billions ways to get around the screen. 


This then is the tutorial I wish I had found.  It is how to use GVim as Notepad.  GVim is the graphical version of Vim.  It's the same as the shell-based version, but you get to use your mouse and there are menus.  What I am about to present doesn't show any of the power of Vim, but it will help you become comfortable enough that the myriad other tutorials on the web can be of assistance.


Modes


The first thing to understand about Vim is that it is modal.  Most editors are modeless.  Letters are entered by typing them.  Control keys do special things.  This is true all the time.  Control-S will invoke Save in notepad no matter what you are doing.  Not so in Vim.  Vim has different modes and different commands will have a different effect depending on which mode the editor is in.  It is important to keep in mind which mode Vim is in.  For now there are 2 modes you need to know about. 


First there is "normal" mode.  Vim always opens in normal mode.  This is the mode where you enter commands.  Whether you want to save a document or change the case of a letter, normal mode is where you want to be.  The confusing part is that in normal mode, you can't actually add text to your document.  If you start typing in a blank document, not much will happen.  If you start typing in a full document, all sorts of strangeness will.  In Vim's normal mode, nearly every key on the keyboard is a command.  See this graphical cheat sheet if you want to see them all.


Insert mode is probably what you are familiar with.  It's just like being in Notepad or Pico or even Word.  Insert mode works just like you expect an editor to.  The letters you type show up in the document as text.  Cursor keys or the mouse can be used to move the cursor around.  To enter insert mode, just type i.  The cursor will change from an XOR cursor to a bar cursor.  The word -- INSERT -- appears at the bottom of the screen when in insert mode.  If you are new to Vim, this is the mode you'll spend the most time in.


Esc will exit insert mode and return to normal mode.


Basic Editing


If you are using GVim, editing is simple.  Just enter insert mode and it works the ways Notepad works.  You can select text with the mouse, cut with <ctrl-c>, paste with <ctrl-v>, cut with <ctrl-x>, and delete with the del key.


To save your work, hit esc to go to normal mode.  The combination :w (write) will save the document.  Many commands in Vim are prepended with a colon ':'.  There are good reasons for this, but we won't go into them now.  Just accept that they are needed to increase the number of available commands.


Exiting Vim can be done via the menus or by issuing the :q command from normal mode.  If you want to quit without saving, :q! will accomplish that.


To load a new file, I recommend using the menus at this point in your Vim career.  If you must, :e filename will load filename.


Search & Replace


Often times you'll need to find something in your document.  To do so, enter normal mode (hit esc).  Type / following by the word you are looking for.  For example, /Steve will find the next time Steve appears in the document.  As you type, you'll notice two things.  First, the cursor immediately jumps to the first S following the cursor, then to the first St, etc.  It's doing an incremental search as you type.  In this way, you can stop when you have reached the desired location.  No need to type the whole word.  To stop, just press <enter>.  The other thing you'll notice is that all instances of the word Steve have been highlighted.  This makes it easy to see all the places in your document where the word appears.  To go to the next instance, press n while still in normal mode.


To replace some text, say the word "from" with other text, the word "to", do this in normal mode:  :%s/from/to/g.  :%s means substitute on every line of the document.  The /'s separate the parts of the command ala regular expressions.  The trailing g says to replace all instances on each line.


If you already search for the word you want to replace, the syntax can be simplified by leaving out from.  Thus :%s//to/g will replace whatever was last searched for with "to".


Conclusion


This should be enough to get you up and running in Vim.  You won't notice any advantage from Vim yet, but you will be able to edit.  Once you are comfortable with GVim as a Notepad alternative, you'll be ready to learn the parts that make Vim such a great editor.  I have a post to help with that here.


For the Non-Visual User


If you happen to be using Vim from a command-line instead of GVim, a few more commands will be necessary for basic operation.


To select text, hit <ctrl-v> to enter visual mode and use the cursor keys* to select the text you want to operate on.  If <ctrl-v> does a paste, you can use <ctrl-q> instead.


To cut or delete the selection, press x.


To copy the selection, press y (yank).


To paste a previously cut or copied selection, go to where you want to insert it and then (from normal mode) press p.


----


*This won't work in GVim.  If you know how to make it work, let me know.