Archive for the ‘Software Development’ category

August 30th Links: ASP.NET, ASP.NET AJAX, IIS7, Visual Studio, Silverlight, .NET

September 7, 2007

 

Here is the latest in my link-listing series.  Also check out my ASP.NET Tips, Tricks and Tutorials page for links to popular articles I’ve done myself in the past.

ASP.NET
  • ASP.NET Charting with NPlot: Olav Lerflaten has a great article on 4GuysFromRolla.com that describes how to use the free NPlot chart engine for .NET to create professional scientific charts of data using ASP.NET.

  • Export GridView to Excel: Matt Berseth has another excellent post on how you can export data to Excel from within your ASP.NET application.

  • Using Coordinated Universal Time (UTC) to Store Date/Time Values: Scott Mitchell has a useful article that describes how to use the UTC format to store date/time values within a SQL database so that it is transportable across timezones.  This is important to think about if your business operates in multiple geographic locations (or if your hosted web-server is located in a different time zone).

  • Fixing Firefox Slowness with localhost on Vista (or XP with IPv6): One annoying issue I’ve run into with Firefox is that sometimes – when doing localhost development – it can take several seconds to connect back to a local page.  It turns out this slowness is caused by a Firefox IPv6 issue with DNS resolution.  Dan Wahlin has a good pointer on how to fix this.

ASP.NET AJAX
  • ASP.NET AJAX Exception Logging: Kazi Manzur Rashid has a nice article that shows how to create an effective error logging system with ASP.NET AJAX to catch and record client JavaScript errors.

IIS 7.0
  • Developing IIS7 Modules and Handlers with the .NET Framework: Mike Volodarksy from the IIS7 team has an excellent step-by-step blog post that describes how you can now write HttpModules and HttpHandlers using managed code that participate in all requests to a web-server.  This enables you to easily do scenarios that previously required custom C++ ISAPIs to achieve.

LINQ
  • LINQPad: Joseph Albahari has an incredibly awesome LINQ query expression tool that you can use to quickly try out LINQ expressions.  Think of it as SQL Query Analyzer – but with LINQ expressions as the queries.  Definitely a useful free tool to add to your toolbox.

Visual Studio
  • The SQL Data Tools in VS 2008: Rick Strahl talks about some of the new database schema comparison, data comparison and SQL Refactoring features within Visual Studio 2008.

Silverlight
  • Recreating ITunes in Silverlight: Jose Fajardo has an absolutely fantastic blog with a ton of Silverlight content on it.  One of the projects he has been working on has been recreating Apple’s ITunes Media Player using Silverlight.  Check out his multi-part blog series that discusses step-by-step how he built it.  Absolutely brilliant.

  • New Halo3 Video using Silverlight: The new Halo3 preview video was recently posted to the web – using Silverlight 1.0 to build a custom viewer and stream a HD version of it.  Click here for a lower resolution version if you are on a slow network.

  • Sudoku for Silverlight: David Anson has built a cool online sample using Silverlight that helps you play the popular Sudoku game.  Useful for both Sudoku addicts and developers wanting to learn Silverlight.  

  • Font Embedding and RSS data in Silverlight: Tim Heuer has a cool blog post that shows how you can create your own font-type and embed it within your Silverlight 1.0 application.  He then has his application retrieve dynamic content from an RSS feed and use the custom font to display it.  You can run the finished application online here (all of the text here is dynamic – not a screen-shot).

  • Silverlight Drag and Drop JavaScript Framework: Roberto Hernandez-Pou has a nice article and sample that describes how to implement a drag/drop mechanism for Silverlight 1.0 (using JavaScript).  This article is in both Spanish and English – scroll down if you are looking for the English version.

  • Pascal Support for Silverlight: RemObjects Software now has a project template for VS 2008 that enables you to write Silverlight 1.1 .NET applications using Pascal.  It is kinda wild to see a screenshot of FireFox on the Mac, running a Silverlight application, written with a Pascal code-behind file built with VS 2008. 

.NET
  • LLBLGen Pro V2.5 released: Last week Frans Bouma released the latest version of LLBLGen Pro, which is an excellent ORM implementation for .NET.  New features include richer auditing, authorization, and dependency injection support.

  • IronLisp: A new codeplex project has recently started that provides the beginnings of a LISP implementation for .NET which is built using the new DLR (dynamic language runtime) framework for .NET.  Earlier this month I was thinking to myself “I really need to spend some time using LISP or Scheme”.  Now I can do it on .NET.  Sweet.

Hope this helps,

Scott

August 30th Links: ASP.NET, ASP.NET AJAX, IIS7, Visual Studio, Silverlight, .NET

Advertisements

Extend Model View Presenter to ASP.Net 2.0

September 7, 2007

 

using ASP.Net 2.0 advanced features

Extend Model View Presenter to ASP.Net 2.0

Extend Model View Presenter to ASP.Net 2.0

September 4, 2007

 

using ASP.Net 2.0 advanced features

Extend Model View Presenter to ASP.Net 2.0

August 1, 2005: “Controlling your boss for fun and profit”

August 30, 2007

 

I. M. WrightThere’s a great gesture you can do to show just how little you care about someone who is wallowing in self-pity. You lightly rub the tips of your thumb and forefinger together saying, “This is the world’s smallest violin playing, ‘My Heart Cries for You.’”

That’s how I feel when people complain about their helplessness in the face of the seemingly invincible power of their manager. “Oh, management will never give us the time to improve our build or change our practices.” “I wish our manager took this training. That’s the only way we’d ever take up inspections. (See “Review this” in Chapter 5.)” “I’m really uncomfortable with our product’s current direction and group’s organization, but there’s nothing I can do.”

Grow up, you weenies. Based on your pathetic excuses for inaction, nothing would ever get done. Don’t you think your bosses say the same thing regarding their bosses? If you don’t make desired change happen, it doesn’t happen. Period. The difference between you and someone powerful is not your level of control; it’s your willingness to act.

I have no hand

“Yeah, but my boss won’t listen to me,” is the common retort. “She has all these reasons why we can’t change.” Well, good. At least you’ve made the transition from being pathetic to being ignorant. You’re trying to do something about your situation; you’re just inept. Relax, most people are.

Unfortunately, influencing without authority rarely comes naturally; it is an acquired skill. When trying to enact a solution, most people jump right in. They go straight to their bosses with their idea, only to get shot down. Sometimes people even do a tremendous amount of preparation, writing a long white paper or presentation, only to be summarily rejected.

What you may not understand is how to prepare appropriately, how to present your idea effectively, and how to get your idea enacted. Let’s break it down.

Eric Aside

I gave an internal talk on this topic. Registration filled in minutes. The moral: many people want to know more about influence without authority.

Know the enemy and know yourself

Start with appropriate preparation. I’m going to list a bunch of steps, but they can all be done in less than a day (minutes for small issues).

First you need to scout the landscape. Only fools walk into a minefield without a map. Most people know how they want things to be, but that’s an endpoint, not directions to get there.

§ Understand your proposal.

What is risky about your idea, and how do you mitigate the risks? What can change about your idea, and what are the core principles you can’t compromise? Be realistic and honest with yourself.

§ Understand your history.

What were the reasons for your current processes and organization? Could you regress by changing them?

§ Understand your enemies.

Who prefers the current state and why? Are any of them strong enough or passionate enough to make change difficult? How would you placate them or even draw them to your side?

§ Understand your friends.

Who is unhappy with the current state and why? Do they like your idea? How strong, considerable, and passionate is your body of support?

§ Understand your management.

How is your management being measured or judged? What benefits would be worth the risk from your manager’s point of view? Can you increase the benefit to management or reduce the risk?

It sounds complicated, but if you have been paying attention to how your coworkers interact, you and a friend or two can scout the landscape in a candid short discussion. Talking to a few people is often necessary to unearth the history or understand the issues. Regardless, scouting is essential to success.

They succeed in adapting themselves

Now that you know what you’re up against, you need to adapt and refine your original idea accordingly:

§ Choose who to please, who to placate, and who to ignore.

Sure, you want to please everyone, but sometimes it’s better to just make sure nobody gets upset and focus on the few you really need to make happy—like your boss. Some folks will be fine if you just keep them from harm. Others can be ignored if they follow whatever your boss decides or simply don’t care.

§ To please people, focus on the benefits in their terms and negate the risks.

Use your scouting information to frame the benefits in ways that impress the key players. If your manager cares about efficiency, talk about productivity gains; customer satisfaction, talk about quality and connection; on-time commitments, talk about predictability and transparency. To negate risks, talk about backup plans, go/no-go decision points, redundancy, and/or clear prioritization.

Eric Aside

This is the negotiation step of removing threats and fulfilling needs I talked about in “My way or the highway—Negotiation,” which appeared earlier in the chapter.

§ To placate people, neutralize whatever they find threatening.

Use your scouting to uncover what’s scary. If it’s risks, negate them. If they have a competing solution, embed it and give them ample credit and the limelight (“It’s our idea”). If they have extra requirements, satisfy them either immediately or in the “next version.”

In the end, you’ll have a plan with a bunch of backers, no one will be apprehensive enough to fight it, and you’ll be aligned with what the key decision makers care about. Now you’re ready to present it.

Selling water to fish

Selling water to fish really isn’t that hard, assuming their credit is good. You simply need to show them what life is like without water. The same thing goes when you are driving for change. You need to frame the problem before you talk about your solution.

The focus is on the key players, usually management. In the same way you use your scouting information to frame benefits in key player terms, you frame the problems in terms that speak to key player concerns. This should be the first slide after the title in a very short deck.

A few important notes here:

§ Anything about you or your ambitions will poison the proposal.

The proposal needs to be about the key players, the team, and the customers, not about you and your desires for fame, glory, or a high rating.

§ To target your presentation on the key players, you must slip inside their skin.

Use their terms, talk about benefits to them, and address their concerns. While the solution may have been spawned by what you care about, the solution will belong to the team, not you. It will be owned by the key players, not you. You must leave your feelings out of it.

Eric Aside

Generally speaking, slipping inside the skin of key players and leaving your own feelings behind is the hardest step. It’s also incredibly important to success.

§ If you talk about the solution first, no one will care.

If you skip over the problem, there is no impetus to change. If you talk about the solution and then the problem, people will fixate on the problem and forget your solution. Always start with the problem and then move on to talk about the solution.

§ You must keep your presentation short—very short.

Change drives discussion and debate. The debate will expand to fill any allotted time. If you can’t get through your ideas in two or three slides, you’ll lose all sway over the argument.

Eyes on the prize

Your second and possibly third slides speak to your vision of the future state. The vision should be clear, concise, and practical. The goals should be clearly stated in terms of benefit to the key players. Simply put, you cannot reach a destination if you don’t know where you’re going.

You’ll likely have many more slides with all sorts of data and detail about your vision and proposal. You might even have a 30-page white paper. That material is important to document the basis for the change, but relegate supporting material to appendix slides and resource links. You must be crisp to be successful; everything else is there for reference only.

Your last slide addresses how you get from the current state to the future state, or how to reach your destination. There are only two sections to this slide:

§ The issues section, which addresses how risks and concerns are mitigated. It’s where to put your backup plans, go/no-go decision points, redundancy, and/or prioritization.

§ The next steps section, which addresses who does what and when. Too often people focus on what needs to be done and not enough on who will do it and when it will happen. Without specific people assigned and specific target dates, the change flounders.

That’s it: a title slide, problem statement, future state, and transition slide. Now you are prepared to bring your idea forward. For smaller ideas, you can do all this in an e-mail message, but the preparation is the same.

Eric Aside

A number of people doubted you could put all this information on three slides and asked me for an example. My best example was a Microsoft confidential proposal that put all the information on one slide. It had vertical and horizontal lines dividing the slide into four quadrants: problem (four bullets in the upper-left quadrant); solution (three bullets in the lower-left); issues (six bullets in the upper-right); and next steps (four bullets in the lower-right).

Engage

You are now ready to engage with the key players. There are dozens of ways to do this, and none is dramatically better than the others. Sometimes the landscape may suggest one approach over another. In general, there are three basic types of approach:

§ Talk to key players one at a time.

This works well when the key players don’t get along or each has different key issues. It’s more time-consuming, but it’s usually a safe and effective approach.

§ Meet with the key players together.

This works well to build consensus and bring out hidden issues. It’s also a bit faster, but it works best if some consensus already exists about the problem and the issues. If necessary you can start with the first approach to gain that initial consensus, and then seal the deal with a meeting.

§ Target only the top player.

This works well when the top player is particularly strong or the organization is particularly compliant. Use this approach when no one really matters but the top player.

Go through your deck and be prepared to own the process you’ve created. Remember that it’s not about you—it’s about the team, the product, and the customer. Let people discuss and debate as much as they want, as long as they stay focused on the problem you identified. If new issues or risks arise, be sure to note them and devise mitigations.

Dare to dream

This whole process may seem like a great deal of trouble, especially when there’s no guarantee your solution will survive, let alone thrive. You may feel that it’s not worth it; that the status quo is acceptable or at least tolerable. Maybe that’s true, or maybe you’re spineless.

Just don’t start complaining about how powerless you are or how management won’t listen to you and doesn’t care. If the current state is acceptable, then accept it and move on. If it isn’t, then do something about it. Regardless of what happens, you will drive awareness of the problem and likely cause change. In addition, you’ll gain leadership experience and perhaps even gain leadership responsibility. In the end, you will become more powerful by matching your willingness to act with the courage to focus on your team instead of yourself.

August 1, 2005: “Controlling your boss for fun and profit”

September 1, 2005: “Go with the flow—Retention and turnover”

August 30, 2007

 

I. M. WrightReview season is here. As entertaining as that can be for managers and employees alike, it’s just a primer for what follows: musical product groups. The music starts when review numbers are released. A whole bunch of engineers get up out of their office chairs and try to find an available chair in a different group. The music stops when all the interesting positions get filled. The same game gets played at the end of product cycles, but product cycles aren’t quite as predictable (different problem).

It’s tough on the folks left without chairs. Often they get alienated from their current teams for trying to jump ship. Tough luck? I don’t think so. Managers should encourage their people to pursue new opportunities, including people they like. Anything less is selfish, stupid, and shortsighted, not to mention destructive, delusional, and deplorable. When managers make business decisions that put their interests ahead of Microsoft’s, they’ve clearly stopped working for Microsoft. I think Microsoft should stop paying them.

Don’t tell me, “Oh, but the project depends on this person. It’s necessary for me to alienate him and stifle his personal development. It’s for the good of the company.” That’s a crock-load of dung. What you’re trying to tell me is that you didn’t plan for turnover, and now that it’s come, you want to avoid all the work to recover, recruit, re-educate, and reassign people. In other words, you’re brain dead and lazy, but you’re making up for it by being selfish and self-serving. Only ignorant nimrods are unprepared for turnover.

Eric Aside

Okay, I’ve held back till Chapter 9, but I have to say it, I love re-reading these columns. Writing them has always been a cathartic experience. Reviewing them for this book has allowed me to relive the satisfaction of unmitigated rage directed at behavior I truly despise. It’s nice in its own twisted way.

I’ll just walk the earth

Good managers should expect around 10% turnover a year. Bad managers should expect more, but they probably don’t recognize it, and I certainly don’t care.

If you’re a good manager of a group of 20, you should expect two people to leave your group each year, sometimes more, sometimes less. Even a lead with five reports should expect at least one person to leave every couple of years. People leave for all kinds of reasons, many of which have nothing to do with you or your team: friendships on other teams, new technologies, a change of scenery, and relationships outside work to name a few. You shouldn’t take it personally.

Nice dam, huh?

But how should you deal with turnover? Some managers go to extremes to prevent it:

§ They blow tons of money on extravagant morale gifts and events, when having more frequent, cheap events would be far better.

§ They promise larger roles and promotions—promises they don’t completely control, promises they can’t keep.

§ They deny permission to interview for everyone on the team, which poisons morale and makes the team feel like indentured servants.

Eric Aside

Microsoft has since changed its rules so that managers can no longer refuse to allow their employees to interview. Only vice presidents still have that privilege.

Trying to prevent turnover is like building a dam to prevent a river from flowing. It works for a short time until the dam breaks or overflows and your team gets washed away in a torrent of transfers. What’s worse, such measures lower morale and make your team less attractive to the new members you’ll soon need.

Flowing like a river

Instead, the best way to deal with turnover is to expect it and embrace it. How? Think flow, flow, floooooooow.

Think of your team as a river instead of a lake. A lake stagnates. There’s no energy or impetus to change. The same is true of groups that stagnate. They cultivate mediocrity and complacency; they abhor risk. A river is always running and changing with lots of great energy. You want a river.

A river depends on the flow of water, and your team depends on the flow of people and information. You can think of the people divided into three groups: new blood, new leaders, and elders ready for a new challenge. Here’s how those groups should balance and flow:

§ The largest group should be the new blood. Not all of them will become technical or organizational leaders.

§ Sometimes you’ll have more new leaders than elders, sometimes the reverse, but ideally you should maintain a balance.

§ For flow, you want a steady stream of new blood becoming your new leaders, and new leaders becoming elders.

§ The key to flow is new blood coming in and elders moving out. For this to work, you WANT your elders to transfer before they clog the stream and disrupt the flow of opportunities for others.

Not all technologies flow at the same rate. Central engines, like the Windows kernel, flow slowly, while web-based services, like MSN Search, flow quickly. You need to adjust for your situation, but even the most conservative technologies do change and flow.

How do you successfully encourage and maintain a healthy flow?

§ Keep a constant supply of new people.

§ Instill information sharing as a way of life.

§ Shape the organization and roles to create growth opportunities.

§ Find new challenges for your elders.

Fresh meat

For a constant supply of new people, nothing beats interns and college hires. Obviously, you’ll also recruit industry candidates and internal transfers, but interns and college hires should be your primary choice for their fresh perspectives and long-term potential.

Your number of annual college hire slots should be at least 5% of your total staff, counting open positions. So if your team has 20 devs, you want at least one college hire slot, more if your team is increasing headcount. Even in a flat headcount organization there is still at least 5% attrition, so look for young talent to fill openings even if none are currently available. College hires sometimes don’t start for nine months; anything can happen over that time, so plan ahead.

Interns are the next best thing to college hires, but they take an extra year to join your team. Therefore, you want as many intern slots as college hire slots. DO NOT plan on shipping interns’ code. At best, they should be pair programming shipping code. However, DO NOT give interns menial labor either. Instead, give interns strong mentors (people who’ll be your next leads) and exciting projects (buddy them up on the coolest features or incubation work). You want to measure them as future full-time hires and convince them that there’s no better job in the world than working for you at Microsoft.

Sharing is caring

When you have new folks on your team, you want them to grow into your new technical and organizational leaders. The only way this happens is through sharing information and knowledge. There is a cornucopia of ways to do this. Here are just a few:

§ Keep an online knowledge warehouse of how your group works. It can be a big, versioned Word doc; a SharePoint site; or a wiki—whatever works best for your folks. The key is to make it easily accessible and up to date. The first month’s assignment for a new person should be to update the content.

§ Use buddy systems for all projects and assignments. The arrangement can be anything from mentoring to assigned reviewer and backup to full-on pair programming. The key is to have no one working alone, no information isolated.

§ Get people together regularly, ideally daily, to discuss progress and issues. Nothing encourages sharing of information like regular high-bandwidth communication, even for as little as 15 minutes a day.

Buddy systems are particularly important for growing your new leaders and transitioning your elders. It’s never safe for an elder to leave if you lose key knowledge and capability in the process. By constantly sharing information, you release the stress-inducing stranglehold on your elder team members, and you make flow and transition a positive and natural experience.

Room to grow

Just like with repotting plants, you need to give your people room to grow. You can encourage this through how you structure your organization, how you issue your assignments, and how you design and promote growth paths for people to follow.

First think about growth paths. The new career models provide excellent and detailed guidance. How do growth paths apply to your team? You should know every employee’s desired growth path and current stage. Then you and your leaders should discuss if those desired growth paths are available for everyone, and if not, how will you adjust?

Often how your group is organized blocks your employees’ growth. All your senior people may be on one team and newbies on another. Change it, fix it, rebalance, reshuffle. The longer you leave your org unbalanced, the more trouble you’ll cause and risk you’ll carry.

Restructuring your organization can create dozens of new opportunities for growth. It’s critical to take advantage of them. Give your people assignments and new responsibilities that stretch them out of their comfort zone. Naturally, buddy them up with more experienced partners to reduce the risk and enhance the learning, but don’t just have the same people do the same things. Choose the assignments based on desired growth paths, and everyone wins.

I must be traveling

Of course, no one can move up if your most senior people stay put. Unless your group is expanding, the only way to make room for growth is to have your elders transfer out. Luckily, that’s exactly what they need. If they’ve been in your group long enough to reach the senior positions, then the only way for them to keep growing is to take on new challenges elsewhere.

Because you’ve focused on flow, losing your senior employees is no big deal. They’ve already shared their knowledge and experience. Their project buddies are already familiar with their work. Now all they need to do is find a good fit elsewhere with you supporting them every step of the way. This kind of loyalty and support will not only be appreciated by your senior people, but will be returned in loyalty and respect by the whole team.

Remember, the whole team watches how you treat your most senior folks. It’s an indicator of how you’ll treat them some day. Nothing wins over a staff like seeing the elder members being treated fairly and generously; leaving the group with praise, well-wishes, and a great future ahead. The message: “Stay with this team and you’ll be well rewarded.”

Surrender to the flow

When you fight turnover or let it catch you unprepared, you risk your project and the effectiveness and health of your team. When you embrace turnover, it becomes just a natural consequence of life. No fear, no worries, just healthy flow for an effective team.

What’s more, driving for flow of people and information in your team creates growth for Microsoft people and value for Microsoft customers. Less stress, more opportunity, greater flexibility, compounded knowledge, higher morale, and a stronger team. What more could you possibly ask? It’s time to surrender to the flow.

September 1, 2005: “Go with the flow—Retention and turnover”

Deep Dive into TDD Revisited

August 30, 2007

 

Hi, everyone. I haven’t posted any serious technical content on this blog for a long time now. The reason for this is that I’m now a pointy haired boss most of the time. I spend my days teaching, mentoring, coaching, and occasionally pairing with someone on another team. I miss coding… I really do.

However, I’ve been digging into Interaction Based Testing over the past few weeks, and I’ve found it fascinating. The road I took to get here involved trying to learn more about what Behavior Driven Development is, and why so many people I know and respect seem to like it, or at least appreciate it. One of the techniques that BDD uses is something called Interaction Based Testing, or IBT for short.

Interaction Based Testing

IBT is different from traditional TDD in that it is defining and verifying the interactions between objects as they take place, rather than defining and verifying that some input state is being successfully translated to some output state. This latter kind of testing, called State Based Testing, or SBT for short, is what I had always done when I did TDD (for the most part). IBT involves using a Mock Object Framework that allows you to set expectations on objects that your class under test is going to call, and then helps you verify that each of those calls took place. Here is a short example:

[TestFixture]
public class IBTExample
{
    [Test]
    public void SampleITBTest()
    {
        MockRepository mocks = new MockRepository();

        IListener listener = mocks.CreateMock<IListener>();
        Repeater repeater = new Repeater(listener);

        listener.Hear("");
        LastCall.On(listener).Constraints(Is.NotNull()).Repeat.Once();

        mocks.ReplayAll();

        repeater.Repeat("");

        mocks.VerifyAll();
    }
}

The basic problem that I’m trying to solve here is that I can write a method, Repeat(), on a class called Repeater such that when I call Repeat(), it repeats what it was passed to its IListener. The way that I set this up is more complicated than I would use in a state-based test, but I avoid cluttering my test with irrelevant implementation details (like explicit data).

What this test is doing is creating the system and setting expectations on the IListener that define how the Repeater class is going to use it at the appropriate time. The MockRepository is the class that represents the mock object framework I’m using, which in this case is Rhino Mocks. I new one of these up, and it handles all the mocking and verification activities that this test requires. On the next line, you see me creating a mock object to represent an IListener. I typically would have created a state-based stub for this listener that would simply remember what it was told, for my test to interrogate later. In this case, the framework is creating a testing version of this interface for me, so I don’t have to build my own stub. Next, I create the class under test and wire it together with the listener. Nothing fancy there.

The next line looks a little strange, and it is. It is actually a result of how this particular mocking framework functions, but it is easily understood. While it may look like I’m calling my listener’s Hear method, I’m actually not. When you create an instance of the mocking framework, it is created in a recording mode. What this means is that every time you invoke a method on a mocked out object while recording, you are actually calling a proxy for that object and defining expectations for how that object will be called in your regular code later. In this case (admittedly, not the simplest case), listener.Hear() is a void method, so I have to split the setting of expectations into two lines. On the first line, I call the proxy, and the framework makes a mental note that I called it. On the next line, I say to the framework, “Hey, remember that method I just called? Well, in my real code, when I call it, I expect that I am going to pass it some kind of string that will never be null, and I’ll call that method exactly once. If I do these things, please allow my test to pass. If I don’t do them, then fail it miserably”.

After I set up the single expectation I have on the code I’m going to be calling, I exit record mode and enter replay mode. In this mode. the framework allows me to run my real code and plays back my expectations for me while my real code executes. The framework keeps track of whatever is going on, and when I finally call my application method, Repeater.Repeat() in this case, followed by the mocks.VerifyAll(), it checks to make sure that all expectations were met. If they were, I’m cool, otherwise my test fails.

I hope that was at least a little clear. It was very confusing to me, but I sat down with a few folks at the agile conference two weeks ago, and they showed me how this worked. I’m still very new at it, so I’m likely to do things that programmers experienced with this kind of testing would find silly. If any of you see something I’m doing that doesn’t make sense, please tell me!

Here is the code this test is forcing me to write:

public class Repeater
{
    private readonly IListener listener;

    public Repeater(IListener listener)
    {
        this.listener = listener;
    }

    public void Repeat(string whatToRepeat)
    {
        listener.Hear(whatToRepeat);
    }
}

public interface IListener
{
    void Hear(string whatToHear);
}

Advantages to IBT style TDD

There are several things about this that I really like:

  • It allows me to write tests that completely and totally ignore what the data is that is being passed around. In most state-based tests, the actual data is irrelevant. You are forced to provide some values just so that you can see if your code worked. The values obfuscate what is happening. IBT allows me to avoid putting any data into my tests that isn’t completely relevant to that test, which allows me to focus better on what the test is saying.
  • It allows me to defer making decisions until much later. You can’t see it in this example, but I’m finding that I’m much better able to defer making choices about things until truly need to make them. You’ll see examples of this in the blog entries that are to follow (more about this below).
  • I get to much simpler code than state-based testing would lead me to
  • My workflow changes. I used to
    1. Write a test
    2. Implement it in simple, procedural terms
    3. Refactor the hell out of it

With ITB, I’m finding that it is really hard to write expectations on procedural code, so my code much more naturally tends to lots of really small, simple objects that collaborate together nicely. I am finding that I do refactoring less frequently, and it is usually when I’ve changed my mind about something rather than as part of my normal workflow. This is new and interesting to me.

There are some warts that I’m seeing with it, and I’ll get to those as well, as I write further in this series. I’m also very certain that this technique has its time and place. One of the things I want to learn is where that time and place is. Anyhow, here are my plans for this:

Revisiting my Deep Dive

I want to redo the example I did a couple years ago when I solved the Payroll problem in a 6-part blog series. I want to solve the same problem in a ITB way, and let you see where it leads me. I’ve done this once already, part of the way, just to learn how this worked, and the solution I came up with was very different than the one I did the first time. I’m going to do this new series the exact same way as the old series, talking through what I’m doing and what I’m thinking the whole time. I’m personally very curious to see where it goes.

Once we’re finished, I want to explore some other stories that are going to force me to refactor some of my basic design assumptions, because one of the knocks against ITB is that it makes refactoring harder by defining the interactions inside your tests and your code. We’ll find out.

Please ask questions

I’m learning this stuff as I go, so I’m very eager to hear criticisms of what I’ve done and answer questions about why I’ve done things. Please feel free to post comments on the blog about this and the following entries. I’m really looking forward to this, and I hope you readers are, too.

— bab

Deep Dive into TDD Revisited

Jeremy Miller writes: On Software Teams

August 6, 2007

Post by Jeremy Miller:

It’s been about half a year since I threw out my My Programming Manifesto, and I’ve started to collect some things that I missed the first time around.  As always, you should be reading this as “..while there is value in the items on the right, *I, Jeremy D. Miller, sole author of the Shade Tree Developer (who is not acting as an agent of my employer in this article)* value the items on the left more.”  It’s also the case that you only have so much time and resources to complete any given project and we all want to play that time and resources against activities that create more value and minimize the time we spend on lower value added activities.  Part of my formulation below is the belief that the stuff on the left provides more bang for the buck than the stuff on the right.  In a few cases I also think the things on the left provide a more pleasant work environment than the things on the right, and that formulation simply cannot be disregarded.  Happy developers are productive developers.

Also, this isn’t even remotely complete.  This just represents some areas that I’m seeing in clients and otherwise where I think the balance between the two opposing choices are being tipped the wrong way.  Overall, let me just say that I’m an optimist in terms of people and their behavior.  Yes, I’m as snobbish as any alpha geek wannabe and I’m prone to thinking that most developers out there are bad, but I also think those same people could be much better if given a better environment.  I also see a lot of good people being held back by bad environments.  Raw talent and effort just isn’t everything.

I tried and tried to come up with pithy subtitles, but just couldn’t do it. 

Internalized Discipline over Externally Enforced Discipline

I got in a bit of an argument the other day with one of the project managers at my client (which ended with a mutually acceptable compromise).  They use Jira from Atlassian for project management and tracking.  Great right?  Atlassian is one of the most visible Agile software companies in the world.  I was objecting to their very complicated directed workflow that they enforced inside of Jira.  My point was that if you wanted Jira to accurately reflect the current status, dump the directed workflow to make the tool easier to update without jumping through the process hoops.  I also stated that I didn’t think they derived any value out of the directed workflow.  The response I got was that the developers wouldn’t test their code at all without the “quality gates” enforced by Jira.  Yet another trip down “the developers can’t be trusted (but I can).”  That last statement is what would concern me the most.

Quality gates are a very common tool in software development processes to enforce quality by making the people on the project demonstrate some sort of compliance to a standard or process before the project is allowed to proceed.  I’m not sure that I’d say that quality gates are necessarily a bad thing at all, but by themselves, quality gates are absolutely worthless in promoting software quality.  The quality gates happen too late in the project and are far too often conducted by people who are not qualified to judge the real quality.  Instead, it’s often an exercise in checking off the adherence to a defined process. 

In my experience, software quality is something that happens as a result of a team’s day to day behavior, not from externally enforced strictures.  How well you unit test the code.  How diligent the developers are about producing well structured code.  How the team refines the design as they work.  How conscientious the testers are about testing the behavior of the system.  How well the analysts can capture and guide the evolution of the requirements.  How the team strives to constantly fine tune their processes as the project proceeds.  These are the things that make for software quality.  The internal discipline and approach of the team performing the work every single day is more important that externally applied governance.  You don’t get quality with enforcement and reviews, you get it by making quality a daily exercise. 

Back to the idea of what activities pay off more.  Quality gates and external discipline doesn’t happen at the time that code is crafted, requirements are gathered, and tests executed.  It comes after the fact.  That externally enforced discipline isn’t around when things are actually getting done.  Even if the quality gate finds problems, it’s awfully late in the game.  Those quality gates still take up time and resources to do, even if they go flawlessly.  Why not redirect that time towards better testing or more code reviews? 

Quality should be the responsibility of the team doing the work, because they’re the only people who can make it happen.  One of my most deeply held beliefs about software development is that people should have the power over the way that they work, and then adequately take responsibility for that work.  The team doing the work is most likely the folks best qualified to know what they do and do not need to do. 

But Jeremy, that might be fine for you, but I can’t trust my developers to just do the right thing.  I need governance.  First, what are you doing to change their behavior?  Secondly, why did you hire them in the first place if they can’t be trusted, or can you tighten up the hiring process.  Three, is that really the case?  I’ve heard this line about not being able to trust the developers far too many times.  Why, or how, is the manager responsible, but the developers aren’t? 

As far as tools go, I’m a hold out.  I think these kinds of tools are only justified in distributed teams and even then, they better be easy to use and not cause any friction.  I think that I can create far more project transparency while only using crude project management artifacts like story cards, but upping the communication and collaboration of the team.  I think these tools are often perfume over smelly team mechanics.

Coaching over Enforcement

Too many times in my career I’ve seen situations where a team is created that doesn’t contain the adequate skills and experience to execute the project that they’re given, but there’s a quality body of some kind ready to eviscerate them for not complying to some sort of standard.  I’ve seen plenty of “Quality Assurance” teams that came into project retrospectives loaded for bear, but were sight unseen during the project’s execution.  It’s far more useful in the long run to roll up your sleeves and help your teammates do things well than it is to be the big guy up top who ensures that the other people are doing things well.

My career goal for the near future onwards is to become the sort of person who can help everyone else around him to be better.  To compare it to basketball, I want to be more like Magic Johnson circa 1988 rather than a younger Michael Jordan — even though I started the other way around.  Same thing with coaches.  I played a lot of sports when I was younger, thinner, and had intact ACL’s.  The coaches that I remember fondly are the patient ones who were great teachers.  The yellers and screamers I could do without.

Collaboration over Direction

In the following two discussions, which would you rather be a part of?

  1. This is what we’re going to do.  Use the Supervising Controller pattern here
  2. What I’m thinking is this.  I think we should use the Supervising Controller pattern for this screen because…

Most people want some form of autonomy, and many people are perfectly capable of thinking for themselves.  Giving a person exact direction is often tantamount to turning off their brain and removing free will from their work.  I’ve led teams on and off for 7 years now.  I’ve noticed a very severe trend in how developers react to the direction I give them.  If I give them very detailed instructions, down to the class and method level with UML diagrams, they try to follow those marching orders verbatim, often to very poor results.  On the other hand, when we go up to a whiteboard together and sketch out a design together, the results are far, far better.  In some part I think it’s because they understand the design better for having taken part in its formulation, but mostly because they don’t stop thinking.

It’s not just the touchy, feel-y aspect of it either.  People work better when they understand the context, reasoning, and goals behind a course of action.  I call this “understanding the why.”  When you understand the why behind your technical direction, you’re much better able to make decisions and follow that direction.

Another thing that simply cannot be avoided.  People can’t just pick up a task cold and run with it.  There’s always some bootstrapping involved before someone understands a task well enough to proceed.  Tomorrow I’m starting work on a financial report I know nothing about in a totally different architecture and codebase than what I’ve been working on (I will be positive about the opportunity to flex my legacy code slaying muscles instead of whining, I swear).  I’m not going to develop at the same speed I do in my own Jeremy friendly codebase.  I also wasn’t a part of the formulation of this little side adventure, so I’m effectively starting from scratch tomorrow. 

I think you can cut down on that ramp up time considerably by working more collaboratively between project/product management and the developers.  Nobody should ever be surprised by their work assignments.  Whether it be through iteration kickoffs, project planning, or simply discussions leading up to a task, a developer should never, ever see an unfamiliar task assignment pop up in their TODO list.  Yet another reason why I don’t like project management tools that try to take the place of human interaction.

Testers too for that matter.  Dumping new features on unsuspecting testers is one of the worst things that we developers can do to the testers.  It takes time to develop an effective test plan, and we need to accommodate this in our planning.  Get the testers involved as early as possible to ease the turnover from development to testing.  You can’t ship until the testers are done with their part (assuming that you’re on one of those advanced teams that actually includes testers), so it behooves you to make their job as easy as possible.  Besides, a tester can’t just test what you tell them to test.  They need to exercise their tester superpowers and find those pesky edge cases that you didn’t.

I don’t want to work on either side of “direction” from above.  To me, working in a collaborative environment is much more rewarding than having to be the guy at the top that makes every decision for the minions below.  It’s tiring and unrewarding to be “the guy.”  It used to be an ego boost to be the One Truck Guy, but I’ve had a chance since to work with strong developers in a collaborative setting.  It’s a much more enjoyable experience than being “the” guy.  I’m old enough now to realize that not every idea I have in regards to a design is necessarily right or the best solution.  I want feedback on my ideas.  I enjoy interaction.  “Ok, whatever you say” or “I trust you” is nice, but it’s more rewarding to have a real discussion.  Besides, I just don’t quite know what to make of a developer that isn’t opinionated.  Wait Jeremy, they’re just being pragmatic and open minded.  No they’re not, they’re just being wishy washy.

Anybody that worked with me five years ago would be laughing their butts off at the idea that I’m for more collaborative team structures rather than a hierarchy with me at the top.  People do change.  Or, you know, at least try to.

Other Stuff

I’ve tackled subjects related to teamwork before and I think it’s just as important if not more than the technology used or your individual habits.

  1. Call me a Utopian, but I want my teams flat and my team members broad
  2. Self Organizing Teams are Superior to Command n’ Control Teams
  3. Once Upon a Team
  4. The Anti Team
  5. On Process and Practices
  6. Want productivity? Try some team continuity (and a side of empowerment too) – I miss this team.
  7. The Will to be Good
  8. Learning Lessons — Can You Make Mistakes at Work?
  9. Indelible Proof of a Healthy Team

There’s more coming, someday, but I really wanted to click the “Publish” button at some point this evening.

On Software Teams