I thought I was wrong once, but I was mistaken.

When’s the last time you admitted to being wrong? That’s the last time you learned something. And it was probably an important lesson.

Much of what we stuff into our memories throughout our life is assumption. Other stuff applies at one time, but likely doesn’t apply now. Insisting we “know” something is usually just clinging to our assumptions. And as my father told me: you know what happens when you assume, right? Other times, insisting we are right is also pretty much acting like the world stopped turning when we learned that one thing. Oh sure, the universe ceased to change at just the moment you became aware of this fact you’re clinging to.

Sure, you learn new techniques, new recipes, new routes to work all the time. But what I am referring to here is a real change of perspective, something that actually makes you better, and lets you do something you didn’t know you could do. By trying to avoid being wrong, we are denying ourselves an opportunity to learn, to be informed, to grow.

Do you ever wonder why it’s so much easier for kids to learn new things than for adults? What if the reason is that adults just think they know everything, whereas small children don’t have an ego or an image to defend by being “right?” Kids know they don’t know – they know they are wrong, and they are OK with it because when they learn the new thing, they will be better off.

I think we are afraid of being wrong for a variety of reasons. First, we get negative feedback for that in many cases: work, school. Being wrong is treated as a failure, so we eventually see it that way. Second, there’s cognitive dissonance when an idea we cling to is challenged. Cognitive dissonance is painful, and we feel better when there is only one idea in our minds, instead of two conflicting ideas. Unfortunately, it’s easier to reconcile our minds by letting what we already “knew” win out, rather than inspecting and changing our minds.

So look for an opportunity to say “I was wrong.” When someone challenges your understanding of something, learn something and you might find that you were, in fact, wrong. But you won’t be wrong anymore, now will you? And you don’t even have to admit to being wrong, in so many words. Instead, you can say “today, I learned…”

So tell me: am I wrong? If so, how? I want to learn from this.

“If You Don’t Transform, You’re Stuck”

How have you transformed to adapt to the changing world?

I had the fortune of hearing Xerox CEO Ursula Burns in an NPR interview this morning: “If You Don’t Transform, You’re Stuck.” Burns saved Xerox from failure and irrelevance by transforming the company. Not only is Xerox surviving, it’s thriving.

Xerox is an example of what applies to every company, ever: “what got you here won’t get you there.” That is to say, the things that brought you (and your company) success until now are not the things that will bring you success in the future. In the case of Xerox, it was paper; now it’s digital logistics services.

What made you successful in the past? Don’t assume that will continue to do so. In fact, I challenge you to question whether it will.

The lesson here is to not rest on the laurels of your success. The momentum that propelled you last year can become an albatross.

Transformation isn’t a one-time thing: you have to keep adapting. How are you transforming now to adapt to the changing world?

Google+ and fear of failure

Aside

I’ve only spent 5 minutes with it, so I can’t speak to how strong of a social networking offering Google+ is. But I can say: what impresses me most is that Google is publicly proving that they are not afraid of failure.

How many attempts has “the Goog” made at social networking? Wave, Buzz and Orkut, at least. And those are the ones that were released publicly. Google Wave came and went pretty recently; they didn’t wait to try again. You also can clearly see where the the lessons and successes that came out of these failed attempts.

Don’t be afraid to try and fail.

Craftsmanship Kerfluffle

Aside

Have you been following the “Craftsmanship” kerfluffle? You should.

Here’s a lot of what’s been said, for my own ease of sharing:

Dan North’s original post, that stirred the hornet’s nest.

Martin Fowler’s take (with links to many other responses) (review his links at the bottom, first).

I don’t have anything useful (or even pithy) to add yet, but I will say I’m thrilled to see so much passion and (so far) level-headed debate, discussion and discovery going on.

Real Agile Genius Videos

2 years ago, I made a video with the Dev team at VersionOne, to seed an “Agile Advert” contest for the 2008 Agile Conference. That video was…

Mr Hit-and-Run Build Breaker

The one that started it all

It so well received, we eventually got around to making a follow-up. This time, we made one to coincide with VersionOne’s release of the Analytics (custom reporting) feature:

Mr Metrics Drill Sergeant

A few months ago, we finally made the ‘series finale':

Mr Standup Long-Talker

Here they are, in a single YouTube playlist

These were a lot of fun (I wish I had time to edit a “blooper” reel); I hope I get to do more stuff like this.

Work More Effectively From Home

If you’re like me, you don’t work from home that often. While I work mostly on my computer, I do collaborate a whole lot, so it’s not typical (I’m a software developer).  Or perhaps you’ve never done it.  However, there are days where I can’t go to the office, and it is advantageous to be able to be productive from home.  Here are a few lessons I’ve learned (mostly the hard way).

Ahead of time: Equipment

Prepare by getting a work setup at home similar to what you use in the office. For example, I am accustomed to using an ergonomic keyboard, a decent mouse, and an external monitor.  My tiny laptop keyboard and touchpad aren’t going to cut it, and I’m certainly more productive with a 2nd monitor – especially one bigger than the 15″ display on my laptop.

Now, a keyboard and mouse aren’t going to break the bank, especially if you are less picky (and carpal-tunnel prone) than I am. But for many folks, shelling out a few Benjamins for a display you don’t use every day can be hard to swallow. A few things to keep in mind: It doesn’t have to be as big, fancy, or new (many manufacturers have outlet sites with good deals) as what you use every day at the office. It’s tax deductible. If you use it enough, you might get your employer to spring for it. Doesn’t hurt to ask. My current set-up uses a pair of CRTs I got for (literally) nothing several years ago. I’ll modernize opportunistically, or when I work from home more.

Ahead of time: Space

The kitchen table or living room sofa* can suffice for an hour or two, but ideally, you can set aside a place in your house that is more-or-less designed with work in mind.  Ideally, you can create a space to work that is free from distractions, but perhaps stimulating and inspiring. This may be your greatest constraint. My current arrangement has me in the basement, which is less than ideal in terms of atmosphere, but the most out-of-the-way in terms of distractions.

You should be able to work there for long periods. Think about seating (consider getting a decent office chair), ergonomics (a desk that’s the proper height), temperature, lighting, and noise .
Keep in mind what non-computer facilities you use at the office that might be helpful working at home.  I like to have a dry-erase board handy, but I don’t find myself using sticky notes as much as I do at the office. Do you need a telephone, or perhaps a headset for your cell phone or VOIP (e.g. Skype).

Be Prepared

If your employer gave you a laptop, be in the habit of taking it home!  Unless of course, working at home is not part of your arrangement.  In that case, you don’t need to read this, do you?  You don’t necessarily need to lug it back and forth every day, especially if you don’t use it off-hours, and you’re 100% confident you’ll be back in the office the next business day.  The key is to be in the habit of thinking about taking it with you. If there is a strong likelihood you’ll need it, take it.  Things that make it more likely you’ll have to work from home without warning are:

  • Weather.  If, like me, you live in the south where the temperature annoyingly waffles above and below freezing during winter days, you’ll have at least one day during the winter season where you can’t (or aren’t allowed to) drive to the office.
  • Kids.  If you have ‘em, plan on being surprised with an illness or school closing.
  • Other dependents in your household. Children aren’t the only ones who have unforeseen needs. It’s life, plan on it.
  • Long commute. You see the traffic report that the world is a parking lot between you and your office. How much sanity would you gain if you could say “I’m just going to work from here until it lets up”, and actually be able to work effectively?

Dress the part

One of the perks of working from home is not having to dress like you’re going to the office. This is especially nice if you have to dress up much for work. However, for many folks I know, it helps to go through a morning routine just like you were going to the office. Shower, shave, dress, eat, etc. This can help you be in mental “work mode.”

What have you learned trying to work at home? What works for you?

*I finished this post on the sofa. Love technology :).

Multi-Project (Portable) Areas Walkthrough

With MVC2, the MVC team introduced Areas, a way to decompose and organize a large MVC application into smaller sub-applications.  The guys who work on MvcContrib built on top of this the concept of Portable Areas.

The Asp.NET site has an intro video on Areas here.

Eric Hexter gives a good overview of portable areas here, and he talks about it with Jeffrey Palermo on the Polymorphic Podcast here.

Eric and Jeffery wrote pretty thorough walkthroughs of portable areas, but they’ve since been outdated by some API changes in MvcContrib.  When a teammate and I attempted to create and consume our own portable area from scratch, we were thwarted by this, and the fact the the above examples also walk through other, unrelated MVC/MvcContrib features.  It took us about a day-and-a-half of trial-and-error to get our own from-scratch portable area, and the necessary steps turned out to be relatively simple, so I thought I’d capture those here.

Note: The MvcContrib project has a Portable Areas Sample in the codebase, at http://mvccontrib.codeplex.com/.  As of this post, the sample works perfectly, but we needed to create our own, from scratch for a new project.  There also appears to be a portable area project template in the works, too, which would be helpful.

Caveat:

I used MVCContrib 2.0.47.0(unreleased) to build this example.  There were some API changes from the latest MvcContrib release (2.0.36.0, 4/14/2010).  I pushed the result to http://github.com/pjboudrx/PortableAreasWalkthrough

Overview/Checklist

  1. Build The Area (Models, Views & Controllers)
  2. Portable Area Registration
  3. Embedded Views and Static Content
  4. “Areas” folder with a Web.Config

2 Projects

To develop the portable area, we found it best to have a related ‘host’ MVC project in the solution, in addition to the portable area project itself.  This gives us an environment to test our portable area.

‘Parent’ Project: MVC2 Web Application

Add a reference to MVCContrib.

‘Portable’ Project: Class Library

Add references to MVCContrib, System.Web.Mvc and System.Web.Routing

Build the portable area

This is equivalent to taking a single area and moving under the root of the project.  You have a folder with the area name.  In that folder: Controllers, Models, Views folders.  For example, my portable area is named ‘CoolComponent':

Portable Area Registration

The portable area registration class must reside in the namespace <RootNamespace>.<AreaName>; for example: “PortableArea.CoolComponent” Example

namespace PortableArea.CoolComponent
{
	public class CoolComponentRegistration : PortableAreaRegistration
	{
		public override string AreaName
		{
			get { return "CoolComponent"; }
		}

		public override void RegisterArea(AreaRegistrationContext context, IApplicationBus bus)
		{
			base.RegisterArea(context, bus);
			context.MapRoute(
 				"CoolComponent_Default",
 				AreaName + "/{controller}/{action}/{id}",
 				new {controller = "HelloWorld", action = "Index", id = UrlParameter.Optional });
 		}
 	}
 }

What’s going on here?  First, the simple stuff.  The “AreaName” property just fills in a spot in the template pattern established by PortableAreaRegistration for use elsewhere.  The call to “context.MapRoute()” is the same as a call to “routes.MapRoute()”; only this time, the AreaName is fixed in the URL pattern.  Standard MVC Area stuff.

The line with all the juice is the call to “base.RegisterArea().”  The base method does several things for us:

  1. Sends a “PortableAreaStartupMessage” on the Application Bus
  2. Registers routes and a controller for embedded Images, Styles, and Scripts, to make the Area fully portable
  3. Registers the Embedded View Engine, so your embedded .aspx view templates can be found at runtime

Add controller(s) and view(s)

Because your portable area is just a class library, you may not see VS templates like you’d expect.
Note: views must be embedded resources.

Consume the Portable Area

Make sure you have an “Areas” folder in the Parent project, and copy Web.config from “Views” to “Areas” if it does not already exist.


Add a reference to the Portable Area project
Global.asax.cs: Add calls to ‘RegisterAllAreas’ and ‘RegisterEmbeddedViewEngine’ (Example)

protected void Application_Start()
{
	// This registers areas, both in-project and portable
	AreaRegistration.RegisterAllAreas();

	// This ensures the views embedded in the Portable Area can be found
	PortableAreaRegistration.RegisterEmbeddedViewEngine();

	// Typical MVC route registration call
	RegisterRoutes(RouteTable.Routes);
}

Test it!

Browse to /CoolComponent/HelloWorld/Index

Area-aware links in the Parent Project

If you want to link (or RenderAction) to the portable areas routes, you will need to ensure ‘area’ is in the route data.

Example

<!-- Ensure 'area' is in the route data  -->
<%=Html.ActionLink("Use the Cool Component", "Index", "HelloWorld", new {area="CoolComponent"}, null) %>
<!-- Ensure 'area' is in the route data  -->    <%=Html.ActionLink("Use the Cool Component", "Index", "HelloWorld", new {area="CoolComponent"}, null) %>

Portable Images, Scripts and Styles

(Thanks to Steve Harman for this additional insight.)

To make a fully self-contained portable area, static content such as css, images and javascript needs to be embedded in the assembly, and found in a special way, just as the view templates are.  To do this:

  1. be sure to call “base.RegisterArea()” in your Portable Area Registration
  2. Include the static files as embedded resource in the conventional location:

A Concept Falls in the Woods…

ForestIf a concept in your software is not actually represented in your code, does it really exist?

As a simplistic example, if your customer or user thinks of your application in terms of “notes”, but there is no code that describes anything called a “note”, that concept is not represented in your code.  One significant thing an agile development team can do to make a code base more agile (supple) is to ensure that there is a high degree of correlation between how we describe and think of our software, and how it is implemented.

This is another way of looking at Ubiquitous Language, a fundamental concept of Domain Driven Design.  Oversimplified, the nouns and verbs of your system need to be aligned with the nouns and verbs used to talk about the system.  But even more essential is the alignment of concepts: words may need to be translated, but it is infinitely more complex to reconcile disparate concepts.

Why is this important?  For one thing, aligning the implementation with the picture in the customers’ heads reduces a lot of friction in communication while developing features.  Additionally, a system that doesn’t reflect the mental model that bore it will eventually prove rigid and resistant to new features to: the customer may want something that, while perfectly compatible with his idea of what the system does, is impossible to implement.

When a concept changes dramatically for the sake of a feature (e.g. a major change or addition), we expect it will be a large effort.  However, if the concept doesn’t change much, but the code does, it’s an indication of a departure in the code from the concept.

How does this happen?  Basically, the developer conceives different abstractions than the customer, and these are never resolved.  This can be caused by poor communication, insufficient design or premature generalization.  Most often, we are driven as engineers to provide value by ‘translating’ the customers needs into implementation instead of fostering and maintaining a ubiquitous language.

Then, down the road, when the customer expects to extend or enhance a concept that’s poorly represented, there are no cohesive parts in the code to target.  As a result, the developers find themselves doing “shotgun surgery” all over the application to try to get the application to behave as the customer expected.

The value we provide between concept and delivery is not a one-way translation: it’s a dialog.  Moreover, the apparent simplicity of this idiom should not cause us to pass it over for more complex and seemingly sophisticated solutions.