c o d i n g f r o g s

croaking about programming, programming languages, software engineering, and the business of software

3Aug/110

How Long To Dig A Posthole?

Some days ago at work I asked a friend what he'd done over the weekend.  "Dig a posthole," he replied.

That seems an odd answer since there's quite a bit of time in a weekend.  He followed with, "How long does it take to dig a posthole?"

When my wife and I moved into our first home, we had two young kids and no fence around our yard.  After we'd saved the money, one of the first purchases we made was to buy materials to build a fence, which included some 40 or so fence posts if I remember correctly.  Each of these needed to be set a good two to three feet deep in a posthole and set with concrete.

I say this so it is clear that, while I'm no expert, I do have some experience with postholes.  If you have a good shovel and a good posthole digger, even someone of average fitness like myself can dig one in fairly short order.  "Oh, maybe 20 minutes," I replied.

"I spent three or four hours digging a posthole on Saturday," my friend countered.

Ah, yes.  I forgot that digging a posthole takes 20 minutes, except when it DOESN'T take 20 minutes.  You might be digging in clay, which is much heavier and will wear you out faster.  You might hit bedrock or caliche.  You might encounter a rattlesnake den.  Or, like my friend did, you might simply run into a series of large, flat rocks, one on top of the other, right where you need the post to go.

So, a posthole takes 20 minutes to dig, unless it takes an hour, or half a day, or longer.  A shovel and a posthole digger are the right tools for the job, except when they aren't.  And when they aren't, you might need a backhoe-mounted auger, or dynamite.

The point is, you can't ever tell for sure if your posthole will be quick or slow until after the digging has begun.  Unless you are an accomplished geologist, you don't know just by looking at the ground where you want the post to go whether this posthole will be quick or slow.

Writing software is much like this.  The very nature of our job means that most of the time we are, to use the metaphor, digging where nobody has dug before.  We're always inventing new things.  Given any development task, we can give our best estimate as to how long the task will take based on our past experience and our understanding of the nature of the task.  But this estimate is much like the estimate of how long it takes to dig a posthole:  You don't know what you are going to uncover until you start digging.

Unfortunately, sometimes software management misunderstands this.  There's sometimes a belief that the estimates are much more accurate than they really are, and that missing an estimate is an inexcusable offense.  But this would be like getting upset with my friend because there were rocks in the ground where the posthole was supposed to go.

Failing to know that there are rocks underneath the ground shouldn't be a sin.  Ultimately, my friend got the posthole dug anyway.  That's what we do, too:  We encounter the rocks, we figure out how to get them out of the way, and we continue to deliver.  Hitting all your estimates all the time isn't the important part.  Delivering useful software is the important part.

15Jul/110

Missing A Sprint Not Considered Harmful

Since I'm a sports guy, let's start with a sports analogy about Michael Jordan, the greatest basketball player of all time.  Over a 15-year NBA career, Michael Jordan played in over 1000 basketball games and scored over 32000 points.  In those 15 years he led his team to a total of six NBA titles.

Throughout his 15-years in the NBA, Michael Jordan made, on average, 49.7% of the baskets he shot.

Clearly, the fact that Michael Jordan missed more shots than he made isn't tarnishing his reputation as a Hall-of-Fame basketball player.  Yet, on agile software development teams, it often seems that missing the target on even a small percentage of sprints is considered an indication of a dysfunctional or struggling team.

Friends, this is simply not the case.

Scrum often uses the word "failed" to describe a sprint wherein the team does not complete all of the stories they committed to at the start of the sprint.  Technically speaking, it's a true description.  But the connotation of the word is so strong that I've sometimes seen teams get pretty down on themselves because of it.  I suggest using the word "miss" instead of "fail" for this reason.  Michael Jordan missed about half of the shots he attempted, but he's certainly not a failure, and I can't imagine he even spent ANY time at all dwelling on individual "failed" baskets.

If your Scrum team is truly challenging itself to fill each sprint with the most work that can reasonably be done during the sprint timeframe, you should fully expect to miss on your sprint about half the time.  That shouldn't be a problem for you, and if it is a problem for your management, you need to help them back off and see the larger picture.  Here's why:

Suppose there are three Scrum teams in two different organizations working on a series of 10 three-week sprints.  Suppose that the best each team can do, in terms of estimating how long work will take, is to achieve about 80% accuracy.  Team A always tries to fill their sprint with what they think is three weeks of work, while Teams B and C always commit only to the work they feel fully confident they can accomplish in three weeks.

This means that every sprint, Team A is trying to do three weeks of work.  Their margin of error is 20%, or 3 days.  In any given sprint, if Team A completes their work inside of the range of 12 to 18 days, they are operating within the margin of error and thus filling the sprints about as full as they can be.  About half the time they will complete all the committed work, and about half the time they won't.  But over the course of the 30 week project, those hits and misses will average out and they should accomplish about 30 weeks of work.  The management for Team A clearly gets the bigger picture that consistent execution toward achieving 30 weeks of work is preferable to always achieving every commitment along the way.

Now consider Team B.  Their management doesn't have the same vision as that of Team A, so instead they insist that Team B must meet their commitment every single sprint.  Team B realizes that their margin of error is 20% on each three-week estimate.  So how does Team B ensure they meet their commitments each sprint?  They only commit to about 12-13 days of work each sprint.  That way, in the worst reasonable case they take the full three weeks to get done, and still meet their commitment.  But what happens when they overestimate?  In the opposite case, they finish in about 9 or 10 days and spend the last week of the sprint waiting for it to end so they can start working again.  Over the course of their project, their estimate inaccuracies cancel each other out, just like they do for Team A, but because they were padding each sprint, they only did 25 weeks of work in the 30 week project.  They met their goals each sprint along the way, but it cost them 1/6 of their work capacity.

Team C has it even worse.  Their management insists that they fill each sprint with three weeks of work,  no padding.  But they also insist that they must meet each sprint commitment.  That means about half of the time, Team C will have no alternative but to crunch in order to overcome their faulty estimate.  If we assume Team C doesn't know until the last week that they are going to miss if they don't crunch, we can assume that about every six weeks, Team C will have to work a 50 hour week, on average, to make up for it, and sometimes as much as 65 hours.  Team C might complete 30 weeks of work in 30 weeks, if they don't go get new jobs first.  They didn't get any more work done than Team A, but they were a lot more stressed out and a lot more miserable for a good five weeks of their project.

Imagine if Michael Jordan's coach had told him, "Michael, I want you to score, but you are expected to make every shot you take.  If you take a shot and miss it, you're gonna get benched."  It's easy to imagine how this ridiculous situation would play itself out:  Michael Jordan would never have become a great basketball player because his fear of missing a shot would have kept him from shooting nearly every attempt he otherwise would have taken.

Like Michael Jordan, your team can only become great if it is safe to fail.  If you are missing every sprint, that's a problem that needs correcting, but I would be equally as worried about a team that hits every sprint.  A great team should hit their sprint about half the time, and they don't get down on themselves when they miss.  After all, it's the finished product, not the individual sprint, that the customer pays for.  Missing half your sprints on the way to delivering a great product on time is a fantastic recipe for smashing success.

Filed under: Methodology No Comments
18Apr/110

Scrum Will Not Make You Code Faster

It's funny how obvious this seems when you state it, yet how commonly organizations try Scrum (or any other methodology, for that matter) in an attempt to improve the speed at which developers deliver code.

Take any typical software engineer from any typical software engineering organization.  Years (or months) ago, this individual was attending college, probably studying computer science.  During this time, this person would attend classes and receive homework assignments from professors.  These homework assignments would often require this individual to write a computer program which would solve a specified problem in code.  This person would then hand in the compiled program and/or the source code to complete the assignment.  Getting good grades on assignments was required to get good grades in class; at a minimum, producing working code was usually required in order to pass.

Okay, you are saying:  So what?

Read the paragraph again if you must.  In order to attain a CS degree, the software engineer in question had to prove they know how to PRODUCE SOFTWARE.

Maybe not high-quality software.  Maybe not fully localized software.  Maybe not enterprise-class software.  But software nonetheless.

Software developers learn how to write software in college.  Yes, they learn more about it as they gain experience, this is true.  But they learned this skill in college, and had to prove it again and again to graduate.  They do not need a software methodology to help them write software.

Nor do they need one to help them write software faster.  The amount of time it takes a software engineer to write the code to implement a piece of functionality, the amount of time to actually write the code itself, is not dependent upon a specific methodology.  How long would it take me to write an HTTP server in JavaScript?  However long it would take, choosing Waterfall or Scrum or DSDM makes no difference in this case.  Someone else may do it quicker or slower, but it isn't because of the methodology they choose.

Organizations make this mistake a lot.  They ask engineering for an estimate to write the WhatsyDoo.  Engineering says it will take 9 months.  "They never give me an estimate that fits within my desired timeline," they think, even subconsciously.  "I need a way to get them to deliver it faster.  Maybe Scrum will help!"

These same people presumably consult with their wife, decide to have a child, then get frustrated when the doctor says it will be 9 months before the baby is born.  Presumably, they scour the internet looking for new techniques to allow you to deliver a fully-developed, healthy, full-term baby only 3 months after conception.

Software methodologies are designed to help software development proceed more efficiently.  But don't get confused.  No methodology can make a group of developers deliver code more quickly than they otherwise would.

What CAN a methodology do, then?

  • It can minimize distractions to developers, so they spend more time developing.
  • It can minimize meetings, so developers spend more time developing.
  • It can manage external requirements, so developers don't fight so many fires.
  • It can focus measurement on the right metrics, so developers don't spend so much time quantifying their work.
  • It can help identify the right features, so developers don't waste time working on stuff that customers don't want.

Software development methodologies are frameworks — frameworks for helping the art of writing code to fit within the context of an organization that delivers software products.  For example, the creation of software products that meet the goals of a business is a problem that can benefit greatly from methodology and process.  Software development methodologies provide guidance and structure around how to leverage the software writing activity towards the achievement of the goals of an organization.  How the organization management interfaces with the engineering group.  How performance is measured.  How the team works more effectively as a team.  How to manage external or last-minute requirements, even mid-stream.  How to facilitate the team working at a regular cadence.  How to improve predictability and accuracy of estimates.

Methodologies can help you achieve many efficiencies in your organization, but they can't help your developers learn how to type faster.  So before you try out Scrum to address your execution problems, fail to address said problems, and then demonize Scrum for utterly failing to save you, be sure the problem you are trying to solve can actually be solved by adopting a software development methodology.  If the problem you really have is that you want a full-term baby only 3 months after conception, what you need is an alternate universe, not a methodology.

(By the way, when you find that alternate universe, please comment.  I'm sure everyone else would love to hear about it.)

8Apr/110

Partial Baskets Are Still Worth 0 Points

In the 2010-2011 NCAA basketball season, Butler University built atop an improbably successful basketball season the previous year by repeating their run to the NCAA title game.  There was a lot of hype leading into the game.  Could mid-sized Butler really topple a mighty basketball powerhouse like UConn and win a national championship?

Butler came into the game full of quiet confidence, but for whatever reason they were never able to find a shooting rhythm like they'd had in previous games.  In the biggest game of the year they managed to make only a pitiful 18.75% of their shots from the field.  They fought hard, executed their offense and played excellent defense, but were not able to overcome such woeful shooting numbers.  UConn won the title, and Butler got to head home, in the words of Jerry Seinfeld, as "the best loser."

It's not my intent to pick on Butler — I often cheer for the underdog so I was hoping they would win.  My heart broke for them as they continued to try in vain.  The point is to drive home the title of this post:  Partial baskets are still worth 0 points.  Butler had so many partial baskets, shots that nearly went in, that they may have won the game if those counted for something.  Unfortunately, a partial basket is worth the same as a turnover:  Nothing.

It's funny how obvious this is in sports, but when it comes to business we pretend like it doesn't apply.

Let's suppose you are working on a software product, and you have exactly one primary competitor.  You both ship your next release at the same time.  Your competitor's product has 10 key features that customers want.  Your product has 8 of those same features.  You also know you were working on the other two features, plus five others, but those seven features did not get into the product.

Imagine your sales rep going into one of your big customer accounts:

Sales Rep:  "Check out the new version of our product.  It has 8 new features that are important to you!"

Customer:  "Yes, but your competitor's product has those features plus two others.  Why should I choose your product instead of theirs?"

Sales Rep:  "That may be true, but we almost completed those two features, plus five others!  We have seven other features almost in the product!"

Of course, the customer doesn't care about those other partially completed features.  Partial baskets are still worth 0 points.  So if the customer doesn't care about partially completed features, why do you?

Why do you track and report a "percentage complete" metric for your tasks?  Why do you go into a status meeting and report that your project is 50% done?  You cannot sell a feature, or a project, or a task that is less than 100% complete, so why do you measure for it?

One of my most prized learnings from Peter Drucker's "Management" book was this basic principle:  Performance measurement should be focused on measuring things that matter to the customer.  That's why I try to stay away from recognizing partial completion, and why you should too.

Organizations that can focus around this line of thinking will find that they become more in tune with their customers because they are continually thinking about their offering from the customer's point of view.  Thinking about a feature as 80% complete is thinking about it from the individual contributor's point of view.  On a 10-week project, the individual contributor has done 8 weeks of work so they are 80% complete.  They want those 8 weeks to matter; of course they do.  But those 8 weeks don't matter to your customer unless the other two weeks of work are also complete and the project is actually finished and shipped.  Customers don't care about partial completion; they think in binary, even if they don't understand it.  Complete.  Not complete.  Those are the only two states that matter to a customer.

Those are the only two states that should matter to you, too.

9Mar/110

Software Development Methodology Profile – Novell Forge

It was the fall of 2002 and I hadn't been in Novell's Developer Services group for more than a couple of months when I realized that the way Novell was maintaining and offering their developer content was flat-out broken.  We needed a new process for delivering developer content that was a lot more dynamic and interactive.  So I proposed we create a new web site with a web application that would allow us to publish more freely.  We soon realized that we wanted to publish code too, not just documents, and that many of our developers wanted to also host and share their own code.  The idea behind Novell Forge was born.

We were starting with an open source CMS, Xoops, and a fairly good-sized Xoops plugin named XoopsForge, but there was still a lot of software development needed to deliver Novell Forge from these foundational pieces.  We had a smallish development team of four or five engineers and a project manager.  I was somewhat unofficially designated as the lead.  Having recently read a bit about Extreme Programming and being interested in trying some of the techniques out, I somehow convinced the project manager that we should try out a new way of developing software.

This methodology was so amazingly lightweight and simple, and yet it worked so remarkably well.  It's shaped a lot of my thinking about software development ever since.

I wrote a very simple web application in PHP to facilitate the process.

  • There was a story card entry page, where you could add a new story to the list of stories that comprised the product roadmap, or edit a story.  Each story had only a couple of fields:  a name, a description, and exit criteria.  The exit criteria outlined a number of objective criteria that, if true, meant the story was complete.  A developer could also assign himself or someone else to work on the story.
  • There was a participant entry page, where you could add a new developer to the project, or edit one.  This was pretty simple also, maybe just the name.
  • There was a story prioritization list page.
  • There was a dashboard where you could easily see who was on the team and what they were working on currently.

That's pretty much it.  It took me about a day or so.

There were two keys to this.  The first was that the stories were prioritized from 1 to N where N is the total number of stories remaining to be completed.  This required a leap of faith on the part of the project manager, who had spent her entire career prioritizing features as P1 (mandatory), P2 (important), and P3 (desirable).  Maybe your project does things this way too.  Most companies I've worked for use this same technique.

Here's the problem with the P1-P2-P3 prioritization.  Suppose the product manager, or whoever, puts together a requirements document.  He lists all of the features and prioritizes each one P1, P2, or P3.  Any guess how many of the features are P1?  Based on my experience, probably about 60%-70%.  Another 20%-30% are P2, with maybe only 10% or less prioritized as P3.  What if the schedule can only allow us to do half of the requirements?  This prioritization doesn't help us at all.  When a developer finishes one assigned task, which should she work on next?  If they are all prioritized P1 it is hard to differentiate.

Sorting all the stories from 1 to N forces the people managing the requirements to think about what really matters first.  If you deliver each story completely and meet the exit criteria, the product should be "functional" with the new story fully integrated by the time it is done.  Note that this doesn't necessarily mean the product is shippable after the first story.  With Novell Forge, we knew we needed to deliver to about story 30 or 40 before we had a product we felt was worth releasing, but still we numbered every story from 1 to N.

A great benefit that comes from this is that now the developers can self-manage.  Is my work done?  This is easily determined by evaluating the progress against the exit criteria.  What should I work on next?  Just assign to yourself the next item at the top of the list.

The second key is trust.  A lot of more complex methodologies add a lot more process to replace the need to address incorrect behavior by your developers.  My web app didn't have any access controls, didn't have any roles or responsibilities.  Anyone could add, delete, reprioritize, or assign stories, but the key is that they DIDN"T unless they were supposed to.  Developers closed issues when they were done and assigned themselves more work when they needed stuff to do.  They kept themselves busy and continually marching toward the goal.  My point is this:  If your team can't follow very simple processes, you might have a personnel problem, not a process problem.  So don't try to fix your personnel problem by adding process complexity.

What were the results of this simple process?  Well, for one thing, it put the team and management at ease.  At any given point in the cycle, we had a functioning product with the most important features already delivered and the next most important features in progress.  We could ship whenever we felt like it.  We could decide to delay shipment until specific stories were done, or align our shipment with a specific event or announcement and go with what we had at the time.  Great flexibility here.

But another, arguably better, feature of this methodology was that the developers loved it.  They wanted to follow it because it was so lightweight, required so little of them, and assumed such a high level of trust from them.  It helped them to focus on just doing their work, and it was easy to see us progressing toward shipment.

Ultimately, Novell Forge was delivered on schedule with the full feature set, but having the flexibility along the way made it a lot less stressful.  Really, does the process have to be more complicated than that?

Tagged as: No Comments
3Nov/100

Grading on a Scale – I Mean, a Curve

Miguel de Icaza tweeted this today:

Performance Review Season at Novell is easy when your entire team is made of 100% super-awesome hackers.

It's a very nice thing for Miguel to say about his team, something I have no reason to doubt.  I don't know Miguel too well, but I have been in a handful of meetings with him back in my Novell days.  He doesn't strike me as the type of person to be disingenuous, and regardless of how you feel about .NET on non-Windows platforms, you have to be impressed with the impact and effectiveness of Mono, so I figure his team probably is pretty awesome.

I guess when you are among the privileged at Novell, you can do things your way.  I know when I was at Novell, having a team full of awesome people didn't make performance reviews any more straightforward.  Novell is by no means unique in this; I can personally attest to this fact.

At most big companies I've been at, how performance is measured depends on what time of year it is.  If you are measuring performance during any other time of the year, you do this by comparing a person's efforts against a published definition of their job description and level.  For example, on your company's intranet somewhere there is a document that describes the expected level of performance for a mid-level software engineer.  If you are a mid-level software engineer, you can compare your performance against the published standard and determine if your performance is currently on track or ahead of or lagging expectations.

This is true at any time of year except during performance review time.  During performance review time, suddenly your performance is measured by how you compare to your peers.  So now, if you are a mid-level software engineer, your performance is based on how your performance and contributions compare to the other mid-level software engineers in your organization.

For some reason this seems to be a pretty common way to measure employee performance, and yet it makes absolutely no sense to me.  In casual conversations with peers (and, frankly, also with a number of managers who will remain unnamed here), I think I can confidently say that it makes no sense to most other people either.

Imagine you are attending college and you sign up to take a calculus class.  On the first day of class, the instructor hands out a syllabus which clearly explains how you will be graded, which boils down to this:  If you get 95% of all the questions right on homework and tests, you will get an A, and the scale breaks down from there.  As the semester proceeds, you monitor your performance on homework and tests, studying to meet that magical 95% mark.  On the last day of class, you enter confidently knowing you have a 96%-97% average which gives you a little bit of a buffer on the final.  You leave the final feeling pleased with yourself, sure that you got at least 19 of the 20 questions right.

Then the grades come out, and you have a B-.

You go and ask the professor, and he says, "Well, I changed the grading from a scale to a curve.  See, everyone was getting As, and we can't have that.  So I graded on a curve instead.  You got a B-."

This is effectively how most employee performance measurement techniques work.  Your performance is graded on an objective, defined scale all year long.  Then comes performance review time, and suddenly you are now being graded on a curve, not a scale.  Before you knew where you stood; now, you have no idea.

A normal distribution curve makes sense when applied to a statistically average sample.  The question is, does your employee population comprise a statistically average sample?  In order to do that, you'd pretty much have to be willing to hire anyone who walks in the door asking for a job.  You probably don't do that; you are probably very selective in who you hire and keep.  You probably try to hire only the best talent you can find.  You probably take the approach of preferring to sometimes pass on talented people that you aren't sure of, rather than give the benefit of doubt, and so you've probably rejected some talented candidates.

That means your employee population is not statistically average.  So why is it that during performance review time you try to make this anomalous sample conform to a normal distribution curve?

I've worked for companies where they say that, organization-wide, some percentage of the population of any given job function MUST be underperforming, some percentage MUST be overperforming, and the rest MUST be performing at around average, within about a standard deviation or so.  This isn't just a belief.  It is enforced through policy.  Essentially the policy says it is not possible to have an organization with 100 employees that are all high performers.  Instead, you might mandate through policy that 10 of them must be underperforming, 10 must be overperforming, and the remaining 80 are average or near-average.  Yet when you hire, you insist that you hire only the best.

This doesn't make any sense, and in my opinion it is a dangerous practice.

First off, you aren't fooling anyone, especially not the intelligent, highly-educated type of thought worker that tends to be evaluated this way.  You wanted smart people, you hired smart people, and now you have to pay the consequences:  You can't implement obviously flawed policy like this.  They will pick up on it and it will cause them to lose faith in your organization.

Second, it encourages exactly the wrong type of behavior.  Once they realize that their actual performance measurement has less to do with their evaluation against an objective metric than it does against their peers, employees will be incentivized to game the system.  This may manifest itself in many ways:  refusing to help teammates or to work well as a team; manipulating the assignments given to them and others to maximize their relative performance; taking opportunities to point out to you (the manager) how excellent they are in comparison to others or how rotten the others are in comparison to themselves; attempting to make others look poorly or to make themselves look good in public, e.g. meetings; trying to hire people who they know to be less competent than they are; avoiding promotions (and thus responsibility) for the sake of cherrypicking in a job function that they can excel in; etc.  None of these helps your organization to become better.

Third, it encourages employees to leave.  Good employees.  Employees that passed your interview process.  Employees that are exceeding the objective metrics, but don't rank at the right of the curve.  They know they can choose a different company with lower hiring standards and at least perform at the top.  If you are really hiring only the best, then this person is among the best, and they will be hard to replace.

Fourth, this system encourages sucking up.  By definition, it is an entirely subjective measurement.  As a manager, you are likely to be persuaded by those who have perfected the art of sucking up and give them better evaluations.  You might do this without even realizing it.

So, what should you do about it?

Well, if you are empowered to do something about it, I think you should avoid doing it altogether.  Evaluate your employees based on an objective scale.  Period.  Hire great people, expect greatness from them, and then stop doing dumb things that encourage them to not be great.  Just get out of the way and revel in the greatness.

The main argument I've heard in favor of the curve is budgetary.  "We budget 10% of employee salary for annual bonus.  High performers get 18%-20%, low performers get 0%-2%, and the rest get from 5%-15%.  The average is 10% so we meet budget."  The corollary argument is that the bonuses should not be spread evenly across the team.  More money for the high performers.

That's fine, but didn't you try to hire ALL high performers?  If so, wouldn't you say you expect ALL of them to be in the 18%-20% range?  Why not instead budget your bonus pool for the high performance amount across the board?  You should still evaluate each employee's performance, but now you aren't being constrained by budget, so you can do it objectively and fairly against a published metric, the one you've been using in one-on-one's all year long.  If an employee underperforms, you can still give a 2% bonus or none at all.  Take the money you saved and use it next year or something.

If you aren't really empowered to do anything about it, my suggestion is to press onward anyway.  Be excellent anyway.  Don't let the system cause you to be non-excellent.  Be a good team player.  Try to surround yourself with the best people.  Take the assignments you are given and do your best with them.  Discuss with your manager any concerns you have about whether you are getting the opportunity to show what you've got, but move forward and do the job right even if the system doesn't reward you.  I believe good things come about from good works, sooner or later.  If that doesn't work, I guess you can always go work for someone else who's a bit more reasonable.

You can also blog about it.

3Nov/100

Guest Post: How to Launch a Privileged Process on OS X

By: Dan Reese

For security reasons, Apple recommends that GUI applications should never run with the privileges of the root user.  GUI applications normally load several types of plugins and input managers automatically. If a malicious plugin was installed then it could cause security problems when the privileged application was launched.

In addition, system services that run with the privileges of the root user (such as launch daemons) need to avoid using certain technology frameworks provided by Apple. These frameworks are not safe to use in a service that runs with the privileges of the root user.

If you need your GUI application to do something that requires root privileges, Apple recommends you split your application into two parts. First, create a GUI that runs as a normal user. Then when you need to do something with root privileges, you launch a separate helper process or tool. Splitting your application avoids security holes while keeping things very easy for your users.

Two Steps

Launching a privileged process is done in two steps:

1) Request authorization. The operating system will ask the user for permission to run a privileged process. The user will need to enter an administrator’s username and password.

#import <Security/Security.h>

OSStatus PreauthorizePrivilegedProcess(AuthorizationRef *authRef) {
   AuthorizationItem item = { kAuthorizationRightExecute, 0, NULL, 0 };
   AuthorizationRights rights = { 1, &item };
   AuthorizationFlags flags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize;
   return AuthorizationCreate(&rights, kAuthorizationEmptyEnvironment, flags, authRef);
}

2) Launch the process. If the user authenticates correctly, you can use the authorization reference created above to launch the helper process.

OSStatus LaunchPreauthorizedProcess(AuthorizationRef *authRef, NSString *path) {
   OSStatus status = AuthorizationExecuteWithPrivileges(*authRef, [path UTF8String], kAuthorizationFlagDefaults, NULL, NULL);
   AuthorizationFree(*authRef, kAuthorizationFlagDestroyRights);
   return status;
}

Please note that the authorization reference created in the first function is released in the second function. If you want to launch several privileged processes in a short amount of time, you can comment out this line and and release the reference on your own afterwards.

Some of Apple’s sample code (and other examples) has an extra step where they copy the authorization reference. This is only necessary if you have a previously created authorization reference that you want to add elevated privileges to.

Just One Step

If you don’t need to update your GUI between these two steps, then both actions can be combined into one step.

#import <Security/Security.h>

OSStatus LaunchPrivilegedProcess(NSString *path) {
   AuthorizationRef authRef;
   OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef);
   if (status == errAuthorizationSuccess) {
       status = AuthorizationExecuteWithPrivileges(authRef, [path UTF8String], kAuthorizationFlagDefaults, NULL, NULL);
       AuthorizationFree(authRef, kAuthorizationFlagDestroyRights);
   }
   return status;
}

I consider this code to be in the public domain. Please feel free to copy and paste.

(This guest post is originally authored by Dan Reese and reprinted by permission.  It is subject to the copyright terms at the original location.)

Filed under: Uncategorized No Comments
21Oct/100

How To Ruin Your Own Vacation

You know the feeling.  The feeling you get as you are heading home from work on the last day before your vacation.  That feeling of the weight and stress and pressure of delivering excellent software on time just floating away off your shoulders.  Nothing to look forward to for the next two weeks but fun and relaxation.

Right?

Or are you worried you are going to get a call?

It's the nature of the beast.  We plan to escape, but sometimes that call just can't be avoided.

Sometimes it can, though.  Sometimes you get called because you did something boneheaded, something you could have avoided that would have made your vacation more like, uh, a real vacation.

Some time ago I was working through a bug that was assigned to me at work.  After a bit of digging, I realized the bug was being caused because two methods in a related class had recently been deleted.  Putting those methods back in the class would fix my bug, but was that the right thing to do?

I assumed not.  I work with smart people, so I assumed that there was a good reason for removing those methods.  So I dug into the source code control system to determine which checkin had removed those methods, who had performed the checkin, and why.

I found the commit in question, noticed who had done it, and looked into the commit notes.  Here's essentially what I saw:

Description of problem:  Code was broken.  Description of fix:  Solved problem.

Meat Loaf says "two out of three ain't bad," but that doesn't apply in this case.  Note that our checkin system automatically adds the "Description of problem" and "Description of fix" tags so the commit notes weren't nearly so verbose as it appears.

Obviously this was of no help to me in determining why the change was made, and without a reference to a bug database record I couldn't look up the bug to find out about it either.  So even though the developer in question was on vacation that day, I had to call him:  I couldn't wait for him to get back for the answer.

So, there you have it:  One way to ruin your own vacation is to avoid taking any time at all to provide useful commit notes.

Notice that even typing the notes that were put into this commit was an utter waste of time.  I don't know about you, but I don't make a habit of checking in fixes to code that isn't broken.  So the statement "Code was broken" is a statement of the obvious.  Of course the code is broken; why else would you be checking in a fix?  Saying the code was broken is redundant and unnecessary.  Likewise for "Solved problem"; why would you be checking in if you didn't solve the problem?

The single most effective change that could be made here would be to simply reference the bug database record.  Even if the problem description were simply changed to say "Bug #3165150" that would be enough.  Annoying, but enough.  With that I could at least look up the bug in the bug database and maybe figure out why the change was required.  But seriously, how long does it really take to add a few notes about what changed and, more importantly, why?

I've also seen commit notes like this:

- removed GetLastWidgetStatus() method

- modified signature for UpdateWidget()

- added null check to SyncWidget()

Gosh, really?  You needed to tell me that?  I thought that's what diff tools were for.

Here's my suggestion for creating Awesome and Useful commit notes:

  • Include a description of the problem.  Use the title from the bug record as a guideline.  You might want to be a little more verbose, but often it isn't necessary, as long as you...
  • Include a reference to the bug record.  A clickable link is best, if possible; if not, at least a record ID so the bug can easily be found.
    • At this point some of you may be saying, "What if there is no associated bug record?"  In that case, the answer is, "WHY ON EARTH ARE YOU DOING WORK WITHOUT AN ASSOCIATED BUG RECORD?!?"
      • I mean, seriously.  If for no other reason, you need a record so your boss knows what you are doing!
    • Horrible Example:  "Code was broken."
    • Bad Example:  "WidgetManager class not working."
    • Good Example"  "WidgetManager not correctly updating widgets on DisplayChanged event; see bug #5150316."
  • Include a description of why you made the changes you made, not just THAT you made changes or a simple enumeration of the changes.
    • Horrible Example:  "Fixed code."
    • Bad Example:  "removed GetLastWidgetStatus(), modified signature for UpdateWidget(), added null check to SyncWidget()"
    • Good Example:  "The UpdateWidget() method had no knowledge of the event causing the call so it wasn't handling the DisplayChanged event properly; I added a parameter to UpdateWidget() to provide this information which allows us to handle the event correctly.  Also added a null check to SyncWidget() which would have caught the bug.  Removed GetLastWidgetStatus(); nobody is calling it anymore."

See?  That's not so bad.  Just a few minutes out of your life to show your love and caring to your team members when you are gone.  Just a few minutes out of your life so you can really enjoy that vacation without worrying whether the phone is going to ring.

21Oct/100

Automounting a VHD at system boot on Windows 7

I'm playing around a bit more with my test machine at work, and I've been thinking, as excellent as my last setup was, it could be even better.

One way to make it better was to avoid duplicating installation data and instead to put that kind of stuff on a shared VHD that all the other machines can access - physical and virtual.

To start out I recreated a multi-boot-from-VHD setup as I had before.  In addition, I created another VHD to be used in common among them; let's call this "shared.vhd".

Once I've installed the OS into the VHD, I can worry about trying to get the OS to mount the shared.vhd at boot time.  There's three main steps involved.

The first thing to do is create a diskpart script.  This is simply a text file that will be passed in as an argument later to the diskpart command.  The script simply selects my shared VHD and attaches it.  Here's the contents of my dpscript.txt file:

select vdisk file=D:\shared.vhd

attach vdisk

exit

In my case the shared.vhd file is located on D: — your mileage may vary.

The next thing to do is create a batch file that will run diskpart with the script we just created.  I made mountvhd.bat with a single line:

diskpart /s C:\dpscript.txt

Both dpscript.txt and mountvhd.bat are located in my C: root folder, although that also is just down to personal preference.

Anyway, at this point if I run my batch file from a command prompt (with administrative privileges) I can see it select and attach the virtual disk file, so I know the script is working.

The last thing to do is set this up to run at startup time.  There's a number of possible ways to do this but not all of them seemed to work well for me.  For example, using the Task Scheduler to create a task that runs at startup time should work, but it doesn't seem to.  However, adding this batch file as a startup script through Group Policy worked.  Do the following:

  • From an administrative command prompt, type "mmc" to bring up the management console.
  • Under the File menu, choose "Add/Remove Snap-In".
  • Choose "Group Policy Object Editor" in the left pane and click the "Add" button in the middle.
  • Accept the defaults in the dialog.
  • Click OK to dismiss the Add/Remove Snap-Ins dialog.
  • In the tree view on the left of the main window, expand Local Computer Policy, then Computer Configuration, then Windows Settings, and select "Scripts (Startup/Shutdown)".
  • In the main window, select "Startup".
  • Click the "Properties" link to bring up a dialog for managing startup properties.
  • Choose "Add" to add your new startup script.
  • Browse for the batch file you created, click OK, then click OK again to exit the Startup Properties window.
  • Close mmc.  If prompted to save, do so.

Now when you reboot your machine, that VHD should be mounted as an additional volume.

3Sep/100

Multi-booting Windows 7/2008R2 From VHD

One very useful feature of Windows 7 and Windows Server 2008 R2 is the ability to boot the OS directly from a virtual hard disk file (VHD).  This can make it pretty straightforward to be able to run a number of different versions of Windows on a single machine.

I just finished converting my test machine to a boot-from-VHD scenario; before that, I was using a native Windows Server 2008 R2 install with Hyper-V.  Here's some of my observations about the tradeoffs (remember, I DO NOT speak for Microsoft):

  • Boot-from-VHD is not virtualized; you are just running the OS out of a mounted VHD file
    • Because of this, you might expect boot-from-VHD to be a bit faster than a virtualized OS.
    • Since a lot of our work is based on virtualization technologies, it seems weird to test it in Hyper-V (a VM within a VM) and sometimes I wonder if issues I see are a result of my environment.
  • With Hyper-V, you can run all your test operating systems at once; boot-from-VHD is one OS at a time
  • VMs in Hyper-V have snapshotting, so it's easy to roll back to a pristine state

There's a few other minor tradeoffs in the boot-from-VHD scenario, but not enough to fret about too much.  So I thought I'd give it a try.

To start out, just plop in your Windows 7 media and start a clean new installation of Windows 7.  Or, if you are like me, you can pixie boot it.  Start the Windows 7 installation.  Once you've passed the language selection screen, hit SHIFT+F10.  This brings up a WinPE console.  Type "diskpart" in the console to bring up the disk partitioning tool.

If you need to, reformat your primary drive:

  • sel disk 0
  • cre part pri
  • format fs=ntfs quick
  • assign

Now, create a VHD for each OS you want to install (put in a value for maxfilesize, in megabytes):

  • create vdisk file=c:\vhdname.vhd maximum=maxfilesize type=expandable
  • select vdisk file=c:\vhdname.vhd
  • attach vdisk
  • cre part pri
  • format fs=ntfs quick

Exit diskpart and WinPE.  When you get to the destination media selection screen, where you decide which volume to install your OS to, select the first VHD in the list, not your base drive.  The size should be close to what you specified.  IMPORTANT:  Ignore the warning that Windows can't install to that disk - it will work just fine.

After you finish installing your first OS, you can insert the media for the next OS and restart.  Go into setup the same as before, and just like before, enter WinPE after the language selection by pressing SHIFT+F10.  This time you don't need to create the VHDs.  They are still there, you just need to attach them again:

  • select vdisk file=c:\vhdname.vhd
  • attach vdisk

I attached all of mine in the same order as before.  I don't know whether this is the right thing to do or not but it seems to have worked okay.

After exiting diskpart and WinPE, you should see the mounted VHDs listed in the media selection screen again.  This time install to the second VHD in the list.  You should be able to tell the difference because the first one shows less available space than the other VHD(s).  Again, run through the install as before.

Now once you finish you can boot to any of the options in your boot loader menu, if you can distinguish them.  You may wish to edit the boot loader config.  Do the following:

  • Launch an elevated command prompt
  • Run bcdedit.  Take note of the identifiers (GUIDs) for each of your machines - you will need this information momentarily.
  • To change the description of an entry, type bcdedit /set {identifier} Description "a meaningful description" where:
    • identifier is the GUID of the machine you want to change.  {current} and {default} work for the machines they pertain to in bcdedit
    • a meaningful description is the text you will use to identify this machine in the bootloader
  • To set a different entry as the default, type bcdedit /default {identifier}
  • To set the timeout value for the bootloader, type bcdedit /timeout <seconds> where <seconds> is the number of seconds you want to wait
  • For help with bcdedit, type bcdedit /?

Using this technique, I set my machine up for a triple-boot with Windows 7 32-bit, Windows 7 64-bit, and Windows Server 2008 R2.  And, within Windows Server 2008 R2, I should be able to run Hyper-V, where I can run additional Windows 7 test VMs with snapshotting.  The best of both worlds!