Senior Enterprise Meetings Architect Wanted

We are looking for a very technical enterprise meetings architect for a large, well established organization in the Washington, DC area. You need to have extensive meetings orchestration experience and be an expert with PowerPoint-centric meetings architecture. You should also have some experience with multimedia animations playback. Advanced direct, teleconferencing and mixed-setting slide or teleprompter reading skills also desired.

A qualified candidate should be an expert in all aspects of the PowerPoint slide development process, including advanced transition and animated playback techniques. Candidates must possess dynamic monotonal verbal script delivery skills and be able to work well within large and sparsely attended meetings. Candidates must be able to translate business meeting requirements into technical meeting architectures and designs while leading a team of meeting engineers in the rapid development, testing and deployment of complex, content rich PowerPoint presentations.

Candidates must have a real passion for PowerPoint and be self-directed, confident and able to perform the task of expanding relatively simple content in thousands of pages of written documentation to accompany large slide decks packed with dense, monotonous text. Candidates should have a face and be able to articulate the written word clearly and in bold tones. Candidates should also be familiar with modern pointing devices such as laser pointers in addition to traditional uses of the stick and index finger to provide emphasis when presenting the finished meeting product.

Meetings Architect Specific Duties:

  • Mastery of building and maintaining enterprise meetings frameworks in response to business needs.
  • Mentor meetings development staff while implementing best practices and improving meetings design and development processes.
  • Work closely with business principals to understand enterprise meetings requirements.
  • Translate meeting requirements into workable meetings architectures.
  • Present tested, production ready meetings to executive staff for deployment in the field.
  • Accompany executive presenters in the field to provide advanced PowerPoint backup and support in critical presentation delivery scenarios.

Required Skills and Experience:

  • Ability to apply a broad array of skills and technologies to solve meeting presentation problems.
  • Ability to utilize PowerPoint, all versions, and Windows Paint and screen capture tools.
  • Ability to rapidly convert a one page outline or two minute conversation into a 60 slide presentation and 230 page accompanying notes and documentation handout.
  • BS in Library Science or English or equivalent technical training and professional work experience.
  • A minimum of 8+ year's cumulative experience developing enterprise meetings on the Microsoft PowerPoint platform and other technologies i.e. Windows Paint, etc.
  • Ability to troubleshoot and diagnosis complex PowerPoint problems.
  • Strong composition and obfuscation skills, as well as excessively verbose written and verbal communication skills.

Submit your resume today!

Visual Studio LightSwitch Beyond the Basics

Before you make up your mind about LightSwitch prior to beta release, watch the new video on Channel 9. Before you decide that LightSwitch is for non-developers, watch Joe Binder in this video extend a LightSwitch application with a Silverlight user control and a custom WCF RIA Service.

The key point, I believe, made in the video is that EVERY LightSwitch application is essentially a 3-tier application. The extension of the Data Access tier with WCF RIA Services makes it possible to extend those tiers into the enterprise infrastructure easily.

lsoverview

The demo also makes a very important point. When you write a real LightSwitch application, you will be writing code. While LightSwitch might be appealing to non-professional or hobbyist or business types, whoever uses it successfully will in fact end up writing code. Will they have to be an expert developer. Not if they have support from the enterprise pros that build the infrastructure for the business.

I still want to see and play with the beta before making up my mind, but what I’ve seen so far looks very promising.

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.