Microsoft Visual Studio LightSwitch Unfairly Judged Before Beta Released

Two days ago, Microsoft unveiled Visual Studio LightSwitch. I heard about it first on Somasegar's blog and have followed the chatter and the growing list of blog posts and comments. I watched the Channel 9 preview video and the VS Live keynote video introducing LightSwitch. And then I watched them again making notes.

I'm deeply disappointed in a number of bloggers I regularly read and their many commenters that have parroted their sentiments. I won't name them here. Their negative reactions demonstrate an ill informed prejudice and predisposition to discount all 4GL tools without careful analysis and thoughtful evaluation.

Based on my careful notes of the demo videos and "official" blog posts about the tool, these bloggers and many commenters have made statements and critical judgments of LightSwitch that are demonstrably false or grossly inaccurate. And the first early beta is not even available yet. This rush to judgment ill becomes the professional stature and experience of these otherwise well respected members of the .NET development community.

From a certain point of view, I understand the nearly autonomic reaction of these .NET development community leaders. Professional developers have long dealt with the problems that so often plague solutions created by a host of desktop 4GL tools such as Access, FoxPro, FileMakerPro, PowerBuilder and many others. These tools have been highly successful in the business world seeking to just get something working that they could afford. In enough cases to be considered a plague by many professional developers, these solutions have far exceeded their limits as the business grew and ran into some of the hard and harsh limitations of these tools.

Many professional developers have been put into that crucibal of having to tell the business owner that their pet solution will not scale, has to be completely rewritten, and the effort will cost mega dollars to get a similar solution that will scale and grow with their business. The business owner doesn't want to spend the money, so he insists that the developer just make the 4GL solution work. Happy developers then fire their client. Needy and miserable developers then swallow their pride and spend more hours in frustration dealing with a 4GL too they come to hate more often because the solution wraps around a database that was designed by someone who thinks of dinner when you say the word table.

Scott Adams owes his fame and fortune in no small part to the advent of ill conceived 4GL tools and the more horribly designed solutions created with them by the pointy haired bosses who fancy themselves tech savvy.

So I understand the rush to judgment, but the facts are not there to support the negativity and biased ignorance I've seen in so many recent blog posts and comments.

Anyone can actually take the time to watch the videos and read the official blog posts and carefully consider what they have learned. Any professional presented with a tool for solving a problem that has never been satisfactorily solved in the past who automatically dismisses the latest attempt does himself and those who respect his opinion a disservice.

Here is what I've learned after reviewing the demostrations and taking detailed notes and carefully considering the possibilities without making invalid comparisons to the host of 4GL tools on the market today.

  • LightSwitch is NOT a 4GL in the traditional sense of closed source, desktop bound, proprietary database, with few if any extension points.
  • LightSwitch is a set of .NET assemblies and Visual Studio designers and project templates that produce a model based on XAML from which a Silverlight 4 and WCF RIA Services solution is generated.
  • LightSwitch is a .NET solution and can be extended in Visual Studio Pro (and up) with standard Silverlight control projects and server side support projects.
  • LightSwitch supports three data sources: SQL Server (and SQL Azure), Sharepoint 2010, and most importantly WCF RIA Services. In fact, SQL Server access in the 3-tier solution is done via WCF RIA Services and Entity Framework. I was not able to determine exactly how Sharepoint access is supported under the covers but would assume that the same solution is generated, with WCF RIA Services providing access to the Sharepoint list libraries and other Sharepoint data on the host server.
  • There is certainly an incoherent marketing message from Redmond on the subject of the target audience but it is clear that while marketing speak would have business buyers believe that they will be able to write applications without code, the fact is that some coding skill will be required to write even the simplest of applications in LightSwitch where commonly found business rules such as validations and computed values on existing data sets are required.

Based on what I've seen so far, it seems the sweet spot for LightSwitch might be the entry level developer or what one blogger called the "productivity developer" with professional support from senior developers and architects constructing back end systems, designing databases and providing safe and simple WCF RIA Services for the less experienced developer to consume to deliver line of business applications that may never need the skilled hands of the top notch developers.

I want to learn more about LightSwitch and see it and play with it before I make up my mind about its usefulness. I want to see how easy it is to extend and expand a LightSwitch application in Visual Studio Pro as promised but not demonstrated. I want to learn more about the extension points. And I want to see and perhaps participate in providing constructive and informed feedback. More importantly, I want to see what the Microsoft team does with that feedback.

Bottom line. It's far too soon to judge. Let's get the beta and provide Microsoft with some constructive feedback instead of the diatribes I've seen so much of in the last couple of days.

Add Reference Search with Visual Studio 2010 Pro Power Tools

My absolute favorite feature of Visual Studio 2010, so far, is the javascript Intellisense support via the <reference> tag. Add the following line to your .js file and you get jQuery Intellisense.

    /// <reference path="/scripts/jquery-1.4.1.js" />

My second favorite feature, so far, was just added with the Visual Studio 2010 Pro Power Tools just released by Microsoft the other day. It is the Add Reference Search feature. Behold…

addrefsrch

There are a bunch of very cool features added by this small but powerful extension pack, but not having to scroll through a list of assemblies to find the one I’m looking for is a godsend.

You can read about all the goodies on the download page, but two other honorable mentions are:

Ctrl+Click is now the equivalent of right click and selecting Go to Definition. Booyah!

Ctrl+Alt+] on a selected block of assignments will align the = operator making your code block far more readable.

I highly recommend this extension. Thanks Microsoft!

Google’s Folly

If you leave your door unlocked and someone enters your house for nefarious purposes, can you blame your lock manufacturer? Will you switch to a new brand of lock? Or if you open the door and pickup the the strange package you weren’t expecting from your doorstep, take it into your home and open it, do you sue the contractor or architect who built your house when it explodes? Do you declare your house to be unsafe and abandon it to live in a shed?

Well, it seems that if you’re Google, you do.

PC World reports today that Google has announced by leak that they will abandon Windows, blaming Microsoft for the Chinese invasion they suffered in January. Anyone with the slightest bit of brains knows this is an economic and political stunt and has nothing to do with security. The Trojan that Google claims allowed the Chinese hackers into their computers was, according to Symantec, entirely preventable.

Now, five months later we learn that rather than admitting the embarrassing fact that they either left the door unlocked (had un-patched machines) or invited the hackers in (opened attachments on vulnerable machines), Google is announcing that they will toss out their rival’s OS to spite their own face. Instead they will jump on the Linux for the Desktop and Mac OS bandwagon.

That’s fine. It’s a free country. But Google is just as big a target now as they were then and any honest security expert will tell you that Linux and Mac OS vulnerabilities exist and are ripe for exploitation. When Google is attacked again after having put its head in the sand, who will it blame then?

The bottom line is that you cannot blame your security failures on the lock manufacturer or the contractor who built your house if you’re not even willing to lock the door or question the anonymous package left at your doorstep. This is Google’s folly. They have opted for an effectively placed marketing jab against an opponent while leaving their left flank exposed for another Chinese hack attack. When it comes, will they blame the President of the United States or the Secretary General of the U.N.? Or will Google take responsibility for its own security?

Convert Pressure to Deliver into Positive Energy and Thinking

Lately I've become alarmed at the negative level of my thinking at times with respect to my work which can then spill over into my personal life. I've been wondering how I can more consistently harness all the latent energy in the pressure to deliver within the constraints of limited resources, tight deadlines and even tighter budgets and convert that to more positive thinking.

I know the value of positive thinking and the resultant self-reinforcing confidence. It leads to greater achievement, productivity and happiness. And yet negative thinking can so easily overwhelm us when the deck seems stacked against us.

I was pondering this question when I remembered a post from Seth Godin called The Problem with Positive Thinking. Here's part of it:

“All the evidence I've seen shows that positive thinking and confidence improves performance. In anything. ... Key question then: why do smart people engage in negative thinking? Are they actually stupid? ... Negative thinking protects us and lowers expectations. ... If positive thinking was easy, we'd do it all the time. Compounding this difficulty is our belief that the easy thing (negative thinking) is actually appropriate, it actually works for us. The data is irrelevant. We're the exception, so we say. Positive thinking is hard. Worth it, though.“ (Seth Godin, September 2009)

Tomorrow, I will actively think more positively. I will lay aside negative thoughts and entertain only the positive. I will convert and harness the energy of the pressure to deliver and channel that energy into positive, productive valuable thinking. Wish me luck!

Generic Asynchronous Wrapper for .NET

Recently I extended a previous blog post and published it on Code Project under the title Generic WCF Service Host and Client. An astute reader asked about calling a service method asynchronously, something I had not given much thought.

I decided that I wanted a way to support asynchronous calls on the generic WCF client without having to modify my service contract (interface) or implementation class libraries. I also wanted a way to do asynchronous calls with as little client code as possible, which meant support for a simple event based solution.

So I went to work experimenting. If you want the WCF version of the solution, visit the Code Project article and you can get the updated code there just as soon as I get an update published.

In this post, I'll present a more generalized version of the solution I created. The GenericAsyncWrapper<T> class is the heart of the solution. Take any instance of T (any class) and GenericAsyncWrapper<T> puts an event based asynchronous wrapper that allows you to call any method on the instance asynchronously.

I'm not going to explain how standard delegates are used to make asynchronous calls. If you want to brush up on the basics, check out Microsoft's How to call a Visual C# method asynchronously along with thousands of other online resources. I will show some examples of using standard generic delegates to do the asynchronous calls to compare with the use of the generic wrapper's event model.

Here's my test class. It does nothing, as you can see, but it does allow me to test my wrapper.

internal class MyTestClass
{
  public void DoNothingNoParams()
  {
    Console.WriteLine("MyTestClass.DoNothingNoParams called on thread: {0}", 
      Thread.CurrentThread.ManagedThreadId);
  }

  public string DoSomething(string input)
  {
    Console.WriteLine("MyTestClass.DoSomething called on thread: {0}", 
      Thread.CurrentThread.ManagedThreadId);
    return "Output of DoSomething with " + input + " as input.";
  }
}

And here's the test code. Just a simple console app that first shows the test class being called directly, then using standard generic delegates and finally using the wrapper. One advantage you may note is that with the wrapper, you also get all your original input params back.

class Program
{
  static void Main(string[] args)
  {
    Console.WriteLine("Main called on thread: {0}", Thread.CurrentThread.ManagedThreadId);
    Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++");
    Console.WriteLine("synchronous calls");
    var mytest = new MyTestClass();
    mytest.DoNothingNoParams();
    string output = mytest.DoSomething("my name is Tyler");
    Console.WriteLine(output);

    Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++");
    Console.WriteLine("Action<> and Func<> delgate calls");
    Action action = new Action(mytest.DoNothingNoParams);
    action.BeginInvoke(new AsyncCallback(ActionCallback), "test1");

    Func<string, string> func = new Func<string, string>(mytest.DoSomething);
    func.BeginInvoke("my name is Arnold", new AsyncCallback(FuncTTCallback), "test2");

    Thread.Sleep(1000);

    Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++");
    Console.WriteLine("asynchronous wrapper calls");
    var wrapper = new GenericAsyncWrapper<MyTestClass>(mytest);
    wrapper.AsyncCompleted += new EventHandler<GenericAsyncWrapperCompletedEventArgs>(wrapper_AsyncCompleted);
    wrapper.AsyncInvoke("DoSomething", "test2", "my name is Bob");
    wrapper.AsyncInvoke("DoNothingNoParams", "test1", null);

    Console.ReadLine();
  }

  static void FuncTTCallback(IAsyncResult result)
  {
    Console.WriteLine("FuncTTCallback called on thread: {0}", Thread.CurrentThread.ManagedThreadId);
    Thread.Sleep(250);
    Func<object, object> deleg = ((AsyncResult)result).AsyncDelegate as Func<object, object>;
    if (deleg != null)
    {
      object returnValue = deleg.EndInvoke(result);
      Console.WriteLine("FuncTTCallback return value: {0}", returnValue);
    }
  }

  static void ActionCallback(IAsyncResult result)
  {
    Console.WriteLine("ActionCallback called on thread: {0}", Thread.CurrentThread.ManagedThreadId);
    Thread.Sleep(250);
    Action deleg = ((AsyncResult)result).AsyncDelegate as Action;
    if (deleg != null)
    {
      deleg.EndInvoke(result);
    }
  }

  static void wrapper_AsyncCompleted(object sender, GenericAsyncWrapperCompletedEventArgs e)
  {
    Console.WriteLine("wrapper_AsyncCompleted called on thread: {0}", Thread.CurrentThread.ManagedThreadId);
    if (e.Error == null)
    {
      Console.WriteLine("methodName: {0}, userState: {1}, result: {2}", 
        e.MethodName, e.UserState, e.Result);
      if (e.InValues != null)
      {
        for (int i = 0; i < e.InValues.Length; i++)
        {
          Console.WriteLine("   value[{0}] = {1}", i, e.InValues[i]);
        }
      }
    }
    else
    {
      Console.WriteLine(e.Error.ToString());
    }
  }
}

Now here's the real magic. The GenericAsyncWrapper<T> class and its attendant event args class.

public class GenericAsyncWrapper<T> where T : class
{
  private T _instance;

  public GenericAsyncWrapper(T instance)
  {
    if (instance == null) throw new NullReferenceException("instance cannot be null");
    _instance = instance;
  }

  public T Instance { get { return _instance; } }

  public event EventHandler<GenericAsyncWrapperCompletedEventArgs> AsyncCompleted;

  public void AsyncInvoke(string methodName, object userState, params object[] inValues)
  {
    if (string.IsNullOrEmpty(methodName)) throw new NullReferenceException("methodName cannot be null");
    MethodInfo mi = this.Instance.GetType().GetMethod(methodName);
    if (null != mi)
    {
      Func<MethodInfo, object[], object> func = new Func<MethodInfo, object[], object>(this.ExecuteAsyncMethod);
      func.BeginInvoke(mi, inValues, new AsyncCallback(this.FuncCallback), 
        new GenericAsyncState() { UserState = userState, MethodName = methodName, InValues = inValues });
    }
    else
      throw new TargetException(string.Format("methodName {0} not found on instance", methodName));
  }

  private object ExecuteAsyncMethod(MethodInfo mi, object[] inValues)
  {
    return mi.Invoke(this.Instance, inValues);
  }

  private void FuncCallback(IAsyncResult result)
  {
    var deleg = (Func<MethodInfo, object[], object>)((AsyncResult)result).AsyncDelegate;
    var state = result.AsyncState as GenericAsyncState;
    if (null != deleg)
    {
      Exception error = null;
      object retval = null;
      try
      {
        retval = deleg.EndInvoke(result);
      }
      catch (Exception e)
      {
        error = e;
      }
      object userState = state == null ? null : state.UserState;
      string methodName = state == null ? (string)null : state.MethodName;
      object[] inValues = state == null ? null : state.InValues;
      GenericAsyncWrapperCompletedEventArgs args = new GenericAsyncWrapperCompletedEventArgs(retval, error, methodName, userState, inValues);
      if (this.AsyncCompleted != null)
        this.AsyncCompleted(this, args);
    }
  }

  private class GenericAsyncState
  {
    public object UserState { get; set; }
    public string MethodName { get; set; }
    public object[] InValues { get; set; }
  }
}

public class GenericAsyncWrapperCompletedEventArgs : EventArgs
{
  public GenericAsyncWrapperCompletedEventArgs(object result, Exception error, string methodName, object userState, object[] inValues)
  {
    this.Result = result;
    this.Error = error;
    this.MethodName = methodName;
    this.UserState = userState;
    this.InValues = inValues;
  }
  public object Result { get; private set; }
  public Exception Error { get; private set; }
  public string MethodName { get; private set; }
  public object UserState { get; private set; }
  public object[] InValues { get; private set; }
}

You can download the code here GenericUtils.zip (7.33 KB). If you find it useful, I'd love to hear from you. If you think this was a total waste of time, turn the TV back on.

Analysis Paralysis: Ten Strategies for Getting Off the Thought Pot

Do you have a hard time making decisions? Even the most decisive of us can get caught in the headlights of the oncoming project train, unable to choose left, right or straight ahead. Here’s a few strategies that I’ve found useful and sometimes forgotten about while stuck on the software development analysis thought pot.

  1. Ready, aim, fire! Research, evaluate, decide. Hesitation breeds doubt. Doubt is the father of indecision. Make a reasonable degree of confidence your standard and avoid looking for absolute guarantees. There are none.
     
  2. Put away fear of failure and accept the fact that there is more than one acceptable outcome to life’s challenges, including your project. Learn from mistakes but don’t be too afraid to make new ones.
     
  3. Begin. Make a start. Act. No journey or decision can ever be taken without the first step. Make a small decision, take action and then improve on your progress by evaluating regularly. Take digestible course correction decisions. Don’t derail your project by overcorrecting and rolling the bus at full speed.
     
  4. Set a decision deadline and stick to it. Lay out an incremental research and evaluation plan with a list of questions you need answers to in order to make your decision. If you don’t have a perfect answer, enumerate what you have anyway and incorporate it into your final decision.
     
  5. When the problem is too big and the decision too overwhelming, break it down into smaller, more specific pieces. Apply the strategies you find effective on the more manageable elements. Do that until you’ve put all the pieces together and before you know it, the puzzle will be complete.
     
  6. If the outcomes of the decision, regardless of the choice, are equally acceptable, flip a coin. Move on. Don’t waste time dwelling on equally acceptable paths to different but relatively satisfying conclusions.
     
  7. Go crazy. Make a choice even if you don’t have a reasonable level of confidence. Get off the ice berg and start swimming. Something will happen and that will lead to something else. It might turn out to have been a mistake, but at least you’ll have momentum on your side. A moving car is far easier to turn around than one that is parked.
     
  8. Put things into perspective. This project decision you’re worrying about, the one keeping you up at nights. Can it compare with watching your kid’s school play? Will your client attend your kid’s wedding? Or your funeral? Beyond successful completion or abject miserable failure on the project, will the outcome have a permanent impact on your life in the long term? Will it matter to your grandkids? Perspective can be a powerful decision making tool.
     
  9. If you can’t take the plunge off the high dive, run an experiment. Try out your decision on a smaller scale. See what happens. Take the results and boldly make the real decision.
     
  10. Change your point of view. Look for a distraction. Take a walk in a Japanese garden. See a movie. Read a good book. Take your wife on a date. Go to church. Do something to get away from it all, even if just for a few hours. Then come back with a few oxygenated brain cells and make a decision. Ready, aim, fire!

What strategies have you found useful when stuck, unable to make a critical choice on a project? I’d love to hear from you.

Update: I know these are generalized platitudes, but sometimes a good platitude can spark the inspiration one needs to find a specific solution to a real problem.

Prevent Reflection and Disassembly of Silverlight Class Libary Code

Over the weekend, I began to think about how to better protect proprietary algorithms and other sensitive code in a Silverlight application, keeping the assembly away from prying, snooping eyes. I decided the best way would be to keep the code in memory and never have it committed to the hard drive. A little research and a little coding and badda bing (er, badda google?).

The solution turns out to be rather simple. You need four projects: the Silverlight app, the web app, the contract (interface) and the implementation Silverlight class libraries. The Silverlight app references the contract library which pulls it into the XAP. The implementation library references the contract library to implement the interface, of course. And the web app does its thing, supplying the XAP file to the browser and most importantly supplying the protected bits via a stream that presumably is protected by SSL, authentication and authorization mechanisms, items I've conveniently left out of this post and the sample code for brevity.

Start with the AppManifest.xaml (in Dinorythm.xap)
Note that the manifest contains only the Silverlight app and the contract class library along with the other assemblies required for the Silverlight Navigation Application (find what you need at Scott Guthrie's informative Silverlight 4 Released blog post).

<Deployment 
    xmlns="http://schemas.microsoft.com/client/2007/deployment" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    EntryPointAssembly="Dinorythm" 
    EntryPointType="Dinorythm.App" 
    RuntimeVersion="4.0.50401.0">
  <Deployment.Parts>
    <AssemblyPart x:Name="Dinorythm" Source="Dinorythm.dll" />
    <AssemblyPart x:Name="DinoContracts" Source="DinoContracts.dll" />
    <AssemblyPart x:Name="System.ComponentModel.DataAnnotations" Source="System.ComponentModel.DataAnnotations.dll" />
    <AssemblyPart x:Name="System.ServiceModel.DomainServices.Client" Source="System.ServiceModel.DomainServices.Client.dll" />
    <AssemblyPart x:Name="System.ServiceModel.DomainServices.Client.Web" Source="System.ServiceModel.DomainServices.Client.Web.dll" />
    <AssemblyPart x:Name="System.ServiceModel.Web.Extensions" Source="System.ServiceModel.Web.Extensions.dll" />
    <AssemblyPart x:Name="System.Windows.Controls" Source="System.Windows.Controls.dll" />
    <AssemblyPart x:Name="System.Windows.Controls.Navigation" Source="System.Windows.Controls.Navigation.dll" />
  </Deployment.Parts>
</Deployment>

 

DinoContracts a Silverlight 4 Class Library (in Dinorythm.xap).
To any nosy disassembler looking for the secret sauce code, all they will get is the interface and perhaps a few domain classes if you need them.

namespace DinoContracts
{
  public interface IMySecretCode
  {
    string DoSecretWork(string input);
  }
}

 

SecretAlgorithms a Silverlight 4 Class Library (NOT in Dinorythm.xap)
This library has a project reference to DinoContracts and copies it's output to the Dynorythm.Web/App_Data folder.

namespace SecretAlgorithms
{
  public class MySecretCode : IMySecretCode
  {
    public string DoSecretWork(string input)
    {
      return "results of my secret code";
    }
  }
}

 

Dinorythm.Web an ASP.NET MVC 2 project
Obviously this code is not production ready. You need some security here, but what you see here will get you the result you seek. Securing this action method might be a good topic for another blog post.

namespace Dinorythm.Web.Controllers
{
  [HandleError]
  public class HomeController : Controller
  {
    //...other code removed for brevity

    public FileContentResult Secret()
    {
      string ctype = "application/octet-stream";
      string fileName = "SecretAlgorithms.dll";
      byte[] dll = GetFile(fileName);
      return File(dll, ctype, fileName);
    }

    byte[] GetFile(string fileName)
    {
      string path = HostingEnvironment.MapPath(@"~/App_Data/" + fileName);
      byte[] bytes = System.IO.File.ReadAllBytes(path);
      return bytes;
    }
  }
}

 

Dinorythm a Silverlight 4 Navigation Application
This app has a project reference to DinoContracts but knows nothing about the SecretAlgorithms project. The secret code in this demo won't win any awards but it might help you conceive (and me to remember) of how to get the job done with your real intellectual property.

namespace Dinorythm
{
  public partial class About : Page
  {
    public About()
    {
      InitializeComponent();
    }

    // Executes when the user navigates to this page.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
      WebClient down = new WebClient();
      down.OpenReadCompleted += new OpenReadCompletedEventHandler(down_OpenReadCompleted);
      Uri location = new Uri(System.Windows.Application.Current.Host.Source, @"../Home/Secret");
      down.OpenReadAsync(location);
    }

    void down_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
      AssemblyPart part = new AssemblyPart();
      Assembly asm = part.Load(e.Result);
      IMySecretCode secret = (IMySecretCode)asm.CreateInstance("SecretAlgorithms.MySecretCode");

      if (secret != null)
        this.ContentText.Text = secret.DoSecretWork("help me");
      else
        this.ContentText.Text = "was null";
    }
  }
}

Help credits go to Tim Heuer for some comparison with cached assemblies and to the practical help from a Silverlight Tip of the Day.

A Note About Security: I am not a self-proclaimed security expert. I'm sure there are ways to defeat this approach, but I suspect that doing so would be more trouble than it would be worth. But certainly this would be more efficient than simple or even complex obfuscation. Then again one could obfuscate and then dynamically download and instantiate in memory. That ought to really throw a would be intellectual property thief for a real loop. (Also note, I've never tried obfuscation in a Silverlight class library, so perhaps it's not even possible. Hmm... Another research and blog topic.)

If you find this code useful, I'd love to hear from you. Download Dinorythm.zip (313.34 KB) here.

Why I Would Like to Work for Warren Buffett

In his annual letter to shareholders, Warren Buffett wrote (emphasis added):

“We tend to let our many subsidiaries operate on their own, without our supervising and monitoring them to any degree. That means we are sometimes late in spotting management problems and that both operating and capital decisions are occasionally made with which Charlie and I would have disagreed had we been consulted. Most of our managers, however, use the independence we grant them magnificently, rewarding our confidence by maintaining an owneroriented attitude that is invaluable and too seldom found in huge organizations. We would rather suffer the visible costs of a few bad decisions than incur the many invisible costs that come from decisions made too slowly – or not at all – because of a stifling bureaucracy.

There are times when working in an enterprise can be frustrating because there are individuals who deliberately and regularly hinder your work while hiding behind the plausible deniability and comfortable safety of that stifling bureaucracy of which Warren Buffett so sagely speaks.

The question is what to do when you find yourself in that situation. There can be only three answers, I believe. Either you succeed in spite of the efforts of well seasoned bureaucrats and hope that attrition wins the day or you fail while trying or even give up somewhere along the line, resigning yourself to failure. The third alternative is that you find another ball field and another team on which to play and never look back.

Which one would you choose?