<CharlieDigital/> Programming, Politics, and uhh…pineapples

30Jan/14Off

Stateless vs. Appccelerate.StateMachine

Posted by Charles Chen

I've been investigating workflow engines lately (specifically, state machine libraries) and it's come down to Stateless vs. Appcelerate.StateMachine.

First, a digression on why I'm avoiding Windows Workflow Foundation (WF).  It's true that there's tons of documentation, support from Microsoft, perhaps lots of experienced developers, but I count myself as one among many who feel burned by our experience with WF.  I've used the first release of WF on FirstPoint and mostly ended up regretting it for the poor performance and complexity (making it hard for new developers to pick it up).  I've also used the first release on various other SharePoint projects since then on top of Nintex and, again, it's been dogged by hard to trace bugs, poor performance, and stuff that's generally cumbersome (like deployment, for instance).

Microsoft seems to have addressed a lot of these issues by totally rewriting WF in .NET 4.0, but this in and of itself raises a serious question: how stable is the framework?  Sure, Microsoft provided a migration path from legacy WFs to new WFs, but it's still a headache.  Aside from that, even just looking at the APIs, it's clear that it's extremely heavy and does nothing to alleviate the poor practices which are possible with WF.

Thus enters my search for alternatives including Amazon Simple Workflow.  In the end, I've narrowed it down to Stateless and Appccelerate.StateMachine.

To test the intuitiveness, ease of use, and performance, I wrote a simple example with both of them.  I modeled the phone example from the Stateless documentation and ran it in a loop of 1,000,000.

The loop looks like so:

internal class Program
{
    private static void Main(string[] args)
    {
        var stopwatch = new Stopwatch();

        stopwatch.Start();

        for (int i = 0; i < 1000000; i++)
        {
            var phone = new Phone();

            phone.CallDialed();
            phone.CallConnected();
            phone.PlacedOnHold();
            phone.TakenOffHold();
            phone.HungUp();
        }

        stopwatch.Stop();

        Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);
    }
}

The implementation of the phone in Stateless looks like so (common parts omitted for brevity):

namespace StatelessTest
{
    public class Phone
    {
        private readonly StateMachine<State, Trigger> _phone = new StateMachine<State, Trigger>(State.OffHook);

        private readonly Stopwatch _stopwatch = new Stopwatch();

        public Phone()
        {
            _phone.Configure(State.OffHook)
                  .Permit(Trigger.CallDialed, State.Ringing);

            _phone.Configure(State.Ringing)
                  .Permit(Trigger.HungUp, State.OffHook)
                  .Permit(Trigger.CallConnected, State.Connected);

            _phone.Configure(State.Connected)
                  .OnEntry(StartCallTimer)
                  .OnExit(StopCallTimer)
                  .Permit(Trigger.LeftMessage, State.OffHook)
                  .Permit(Trigger.HungUp, State.OffHook)
                  .Permit(Trigger.PlacedOnHold, State.OnHold);

            _phone.Configure(State.OnHold)
                  .SubstateOf(State.Connected)
                  .Permit(Trigger.TakenOffHold, State.Connected)
                  .Permit(Trigger.HungUp, State.OffHook)
                  .Permit(Trigger.PhoneHurledAgainstWall, State.PhoneDestroyed);
        }

        private void StartCallTimer()
        {
            _stopwatch.Start();
        }

        private void StopCallTimer()
        {
            _stopwatch.Stop();
        }

        public void CallDialed()
        {
            _phone.Fire(Trigger.CallDialed);

            //Console.Out.WriteLine("Dialed");
        }

        public void CallConnected()
        {
            _phone.Fire(Trigger.CallConnected);

            //Console.Out.WriteLine("Connected");
        }

        public void PlacedOnHold()
        {
            _phone.Fire(Trigger.PlacedOnHold);

            //Console.Out.WriteLine("On Hold");
        }

        public void TakenOffHold()
        {
            _phone.Fire(Trigger.TakenOffHold);

            //Console.Out.WriteLine("Off Hold");
        }

        public void HungUp()
        {
            _phone.Fire(Trigger.HungUp);

            //Console.Out.WriteLine("Hung Up");
        }
    }

    // Define enums here
}

The implementation of the phone in Appccelerate.StateMachine looks like so:

namespace StateMachineTest
{
    public class Phone
    {
        private readonly PassiveStateMachine<State, Trigger> _phone = new PassiveStateMachine<State, Trigger>();

        private readonly Stopwatch _stopwatch = new Stopwatch();

        public Phone()
        {
            _phone.In(State.OffHook)
                  .On(Trigger.CallDialed).Goto(State.Ringing);

            _phone.In(State.Ringing)
                  .On(Trigger.HungUp).Goto(State.OffHook)
                  .On(Trigger.CallConnected).Goto(State.Connected);

            _phone.In(State.Connected)
                  .ExecuteOnEntry(StartCallTimer)
                  .ExecuteOnExit(StopCallTimer)
                  .On(Trigger.LeftMessage).Goto(State.OffHook)
                  .On(Trigger.HungUp).Goto(State.OffHook)
                  .On(Trigger.PlacedOnHold).Goto(State.OnHold);

            _phone.DefineHierarchyOn(State.Connected)
                  .WithHistoryType(HistoryType.None)
                  .WithInitialSubState(State.OnHold);

            _phone.In(State.OnHold)
                  .On(Trigger.TakenOffHold).Goto(State.Connected)
                  .On(Trigger.HungUp).Goto(State.OffHook)
                  .On(Trigger.PhoneHurledAgainstWall).Goto(State.PhoneDestroyed);
        }

        private void StartCallTimer()
        {
            _stopwatch.Start();
        }

        private void StopCallTimer()
        {
            _stopwatch.Stop();
        }

        public void CallDialed()
        {
            _phone.Fire(Trigger.CallDialed);

            //Console.Out.WriteLine("Dialed");
        }

        public void CallConnected()
        {
            _phone.Fire(Trigger.CallConnected);

            //Console.Out.WriteLine("Connected");
        }

        public void PlacedOnHold()
        {
            _phone.Fire(Trigger.PlacedOnHold);

            //Console.Out.WriteLine("On Hold");
        }

        public void TakenOffHold()
        {
            _phone.Fire(Trigger.TakenOffHold);

            //Console.Out.WriteLine("Off Hold");
        }

        public void HungUp()
        {
            _phone.Fire(Trigger.HungUp);

            //Console.Out.WriteLine("Hung Up");
        }
    }

    // Define enums here
}

And here are the results:

2014-01-30_095250

Here are my observations:

  1. Stateless is about 4x faster than Appccelerate.StateMachine
  2. Stateless syntax is a little bit more intuitive for creating hierarchies
  3. Appccelerate.StateMachine documentation is much more thorough and much more complete than Stateless
  4. But Stateless has more downloads (thus more users) and more presence on StackOverflow (should you need it)
  5. Appccelerate.StateMachine has some cool features around logging and extensibility, but quite honestly, I don't think they are needed given that if you use a composite pattern around your state machine, you can really manage that yourself much more concisely.
  6. The external persistence infrastructure of Stateless is simple, but not very intuitive or well documented
  7. The Appccelerate.StateMachine Nuget package did not work with the package manager console and Visual Studio 2012, requiring me to manually download and compile the source (which I don't mind, but raises some doubt)

All said and done, I think we will use Stateless as it is a very barebones and highly performant state machine, which is perfect for our needs.  Look for more Stateless posts in the future!

Attached is the sample code: StateMachineTest

Filed under: Dev, Uncategorized, WF No Comments
28Jan/14Off

Why I Wear the Same Pair of Jeans Every Day

Posted by Charles Chen

From NPR Marketplace Morning Report, a fun look at tech fashion and what it says about the wearer:

Silicon Valley, of course, is known for its casual dress, which means t-shirts, jeans and sneakers. But don't be fooled, techies care a lot more about fashion than they let on. Or put another way, there’s a lot of code in the Silicon Valley dress code.

In fact, engineer Alexey Komissarouk boasted he could tell if people were in tech and what they did by just looking at their dress. I met him a few months ago at the FWD.us hackathon and I asked him to show me his super power. He agreed and we met in downtown Palo Alto.

Before we got started, Komissarouk explained that the Silicon Valley is full of tribes: there are the engineers, designers, product managers, salespeople, entrepreneurs and VCs. And each tribe has its uniform.

The engineers? T-shirts, jeans and hoodies, of course.

“Hoodie signals young talent,” said Dan Woods, a techie we stopped on the street.

Woods walked by us and Komissarouk nudged me and said, “That guy, he’s a VC.”

The tip off? A zippered v-neck sweater.

“That’s like classic VC and then you got the button down underneath it, that’s like the classic uniform,” Komissarouk said.

We stopped Woods and asked him. Turns out, he did work in venture capital, which is about when he got the sweater.

Turns out the uniform is a long time tradition in tech, says Erik Schnakenberg, a co-founder of Buck Mason, a start-up that sells men's clothing online.

"I wear a pair of jeans and a black t-shirt almost everyday," Schnakenberg said. "It's one less thing to think about."

In the fast-moving world of tec, the idea is to show that your'e not wasting precious time on something as vain as fashion. Schnakenberg  says the uniform hasn't changed much but tech is attracting a lot more of the cool kids and they care about fashion.

It's also why I keep my head shaved myself.  One less thing to think about when I roll out of bed.

President Obama is known to have strategies to minimize the non-essential decision making:

...at work it’s strictly blue or gray suits. “I’m trying to pare down decisions. I don’t want to make decisions about what I’m eating or wearing. Because I have too many other decisions to make,” he tells Lewis. “You need to focus your decision-making energy. You need to routinize yourself. You can’t be going through the day distracted by trivia.”

27Jan/14Off

More Thoughts on Planning Office Spaces for Development

Posted by Charles Chen

A proposed rule of thumb for planning office spaces for development:

  1. Buy cheap desks.
  2. Buy expensive chairs.

Our office has it all wrong.  We have desks that are solid as a rock but probably $600+ and seats that are $99 Office Max specials (just a guess).  I suspect that this is the case with most offices where the planners spend a fortune on desks, dividers, cabinets, and so on (just go look up the prices of cubicle partitions from Hon or Steelcase) and go cheap on the seating.

The problem is that the majority of an office worker's time is spent sitting.  Splurge on the chair instead.  Don't go too cheap on the desks; Ikea Galants are perfectly stable, durable, lightweight, easy to hack, easy to refactor, cheap, and assembling them is a great team building exercise 🙂

There is no exception to this rule.  If you want sit-to-stand type desks, just get something like this:

Kangaroo Elite Sit-to-Stand

Kangaroo Elite Sit-to-Stand (yeah, it's $600, but a sit-to-stand desk easily costs $1000+)

As an added bonus: if you have top candidates coming into the office for interviews, they are far more likely to be impressed by fancy chairs than fancy desks.

17Jan/14Off

Thoughts on Spatial Conditions for Optimal Collaborative Efficiency

Posted by Charles Chen

(Or in other words, how to arrange your office space)

As I have been working in the office more, I've started to think more about how to organize the office space to enhance the collaborative nature of our work.

A few weeks back, we were re-arranging our desks and I noticed how heavy they were and how un-conducive they were to refactoring.  They are L-shaped desks with the two sections held together by two meager screws and a metal plate.  Yet they were so heavy and unwieldy as to make them extremely difficult to move.

The thought occurred to me then why Ikea Galants are almost universally the office desk of choice for startups: they're cheap, they're sturdy, they're easy to move, they're open, and they're extremely hackable.

Google image search results for tech startup office.

Google image search results for tech startup office.

But beyond just the hardware, I've been thinking about how to improve our team's ability to collaborate as we are in a period that requires highly coordinated design and development to hit our very tight timeline.  One of the first things we did was cluster the core team members into one area of the office so that it's easy to turn around and talk to anyone and so that all members of the team can hear and jump in on any design discussion.

This has downsides, of course, as it can get noisy and it can be difficult for other members who need to concentrate.  However, my thought is that we should reuse the office rooms for private "thinking" or call areas with standing only desks (no seats) so that individuals who need temporary peace can move into an office but not get too comfortable.

My other thought has been that it is extremely important for the leaders, founders, CEO, president -- whomever, to sit with the team.  The reason is that these decision makers need to know what's going on -- especially so in a startup -- and it's difficult to do so if their time is spent behind closed doors away from the action.  Of course, there are times when important phone calls must be made or private discussions must be had, but again, the concept is to reserve the closed door rooms specifically for this purpose and only with standing desks.

An even bigger intangible is that having the leadership on the floor sets the tone for the team.  In fact, I sit with my back facing my developers so that each of them can see what I'm working on and what I'm not doing.  I'm not on Facebook, I'm not randomly browsing sites, I'm not sitting idle.  I think this has a motivational effect and helps the team realize that we're all in this together to make the magic happen and that I'm not asking any more of them than I am of myself.

One final important lesson I've learned is that walls are stupid:

IMG_20140117_085727882

15Jan/14Off

Thoughts on Goal Oriented Leadership

Posted by Charles Chen

I've been thinking heavily on the topic of leadership for several days now and trying to understand what works and what doesn't.  I am currently in the midst of a massive and daring undertaking and putting tremendous demands on my team to deliver.

My challenge has been to keep that pressure from them and help streamline this process so that they can focus on delivering and hitting our milestones.  To achieve this, I've tried to step up my leadership and intensity.

I started with a daily stand-up meeting where we got around and discussed our plan for the day, but after just a few days, I thought to myself that it was too limiting if I set the goals for the team and dictated what they did.  Who's to say that I have the best idea on how to hit our goals?  Instead, I only set our team goal and let each member of the team set their own goals for the day.

The effectiveness of this approach is multifaceted:

The first is that it allows communication of the overall team goal.  All members of the team need to know the goal and the mission to succeed; they have to see the bigger picture so that they know that there is a condition for victory and success.

The second is that it allows them to be responsible to their own expectations.  Because the goals are set by themselves, if the goals are not achieved, it cannot be blamed on someone else setting unrealistic goals; each member is thus motivated by an internal force and not an external force.

The third is that you will get better ideas simply by having more brains work on the problem of identifying the goals that need to be achieved for success.

A goal oriented leader doesn't tell people to do things, but rather lets them set their goals and move all obstacles out of the path of achieving those goals.  The idea is to transform yourself from a manager of tasks to a coordinator of goals: communicate a team goal, let the members set their own goals, and what a leader should do is align all goals to the mission.

(Also, it helps to keep the team well fed)