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

24Feb/14Off

Leadership and Innovation

Posted by Charles Chen

From Peopleware, 3rd Edition:

The propensity to lead without being given the authority to do so is what, in organizations, distinguishes people that can innovate and break free of the constraints that limit their competitors.  Innovation is all about leadership, and leadership is all about innovation.  The rarity of one is the direct result of the rarity of the other.  (p. 101)

23Feb/14Off

Why I Always Brace Everything

Posted by Charles Chen

Everything.

Braces

Filed under: Dev No Comments
7Feb/14Off

How to Rock That Interview

Posted by Charles Chen

My sister-in-law pinged me for some tips to prepare for a long, multi-session interview coming up.

I've been on both ends as interviewer and interviewee (mostly interviewer) and I seem to have been pretty successful as far as interviews go, so here are my tips (your mileage may vary):

  1. There is no preparation. It's like an exam. Either you know your stuff or you don't. Zen out and accept that you may not be able to answer/know everything and that no amount of last minute cramming new material will help. The more you worry about the material the bigger of a problem you are creating for yourself because you'll just be more anxious.
  2. Have faith in what you do know. Whatever it is that you do know, you need to be able to communicate it effectively. You need to communicate your knowledge, your skills, and your character effectively.  You are in an interview because someone likes your resume and the experience that you have so you have to be able to communicate that experience effectively.
  3. Say "I don't know" if you don't know. I interview a lot of people and one of my pet peeves is when I give a tough question and the interviewee won't just say "I don't know". Sometimes, the questions are designed to be hard so if you don't know, don't dance around it and be frank so you don't waste anyone's time.
    1. If you really think it's an interesting question, you can say "Hmm, I don't know, but I've never thought about it like that..."
    2. Or "I don't have a background in that topic, but it's interesting, how would you approach it?"
    3. Or "Oh, that's an interesting question; I've honestly never thought about that before". That leads me to my next tip...

    This is, in fact, a trait that I am looking for in an interview because it lets me know that if an individual gets stuck, he will quickly raise his or her voice and let me know so I can help them get unstuck and that this individual is willing to ask for help.

  4. Make it conversational. The more you treat it like a grilling, the more it will feel like you're over a fire. I treat every interview like a conversation and treat every question like a conversational discussion. The interviewer is a conversation partner and not a superior or an interviewer. This also leaves a lasting impression on them because they feel like you are someone they can easily talk to and people like to work with people they can talk to.  Also, you are always free to turn the tables and interview your interviewer; remember, an interview is a two way street: they want to know if they should hire you and you want to know if you really want to work with these people.
  5. Dress sharp, watch your posture, and give a strong first impression. Harvard studies have shown that posture has a strong influence not only on how others perceive you but also how you perform. Stand up straight. Sit straight. Shoulders back. Project confidence but also look relaxed. Use hand gestures to help communicate. Make eye contact -- don't lock it, though -- that's freaky. Using full body communication is important but remember not to fidget. Basic stuff.
  6. Remember names and call people by names. When you meet someone and greet them, they will present themselves and always call them by their name immediately. Interviewer: "Hi, I'm James"; you: "Hi, James, I'm Lindsay, pleased to meet you". It's subliminal, but people like to hear their names and it helps you make an impression in your brain so you know who he was. At the end, repeat the interviewer's name: "James, I really appreciate your time".
  7. Don't forget to drink water. When you talk a lot, your mouth and throat will get dry and if you don't hydrate, it will impact your ability to speak. Hit the restroom when you get a chance, even if you don't "need' to go because if you get the urge during a discussion, it will distract you.
  8. And final tip is to create mental checkpoints. One thing that happens with me is that because I treat an interview as a conversation, it is easy to lose the original question or topic in a long discussion. So you have to make a mental checkpoint and be able to bring the discussion back to the original topic to answer the question. You don't want to be in a position where you have to ask "Sorry, what was the question?"
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)

26Dec/13Off

Setting Batch Variables Dynamically

Posted by Charles Chen

One of the challenges of managing builds and deployments of source on multiple developer machines is that it can be complicated to contain and manage different variations in developer environments.

For example, often times, it is useful to know the server name or the connection string information so that local settings don't make it into source control.

How I've often tackled this is to add a batch file that every developer executes when getting the source for the first time.  This batch file asks for various settings and then saves the results to a text file which is then read back when executing other batch files.

Here is an example of such a batch file:

@ECHO OFF

ECHO ================================================================
ECHO Creates the developer specific local configuration for builds
ECHO that will allow developers to use local settings for specifc
ECHO aspects of the deployment.
ECHO ================================================================

:SPURL
SET SPURL=
SET /P SPURL=Enter SharePoint site URL (ex. http://mymachine:2345/): %=%
IF "%SPURL%"=="" GOTO SPURL

ECHO ----------------------------------------------------------------

:SQLCONN
SET SQLCONN=
ECHO Enter SQL connection string to the IC membership database 
ECHO (ex. Server=VM1;Database=IPDB;User ID=membershipUser;Password=P@ssw0rd;Application Name=HeCoreServices):
SET /P SQLCONN=
IF "%SQLCONN%"=="" GOTO SQLCONN

ECHO ----------------------------------------------------------------

ECHO SPURL=%SPURL% > build-configuration.txt
ECHO SQLCONN=%SQLCONN% >> build-configuration.txt

ECHO Completed; created file build-configuration.txt

PAUSE

This batch file will prompt the developer for two settings: the URL of a site and the connection string that the developer is using locally (which can vary by the database name, login, etc.).  The contents get written to a file called build-configuration.txt that looks like this:

SPURL=http://mymachine:2345
SQLCONN=Server=VM1;Database=IPDB;User ID=membershipUser;Password=P@ssw0rd;Application Name=HeCoreServices

This file is excluded from source control and developers can, of course, manually edit this file as well to create local settings.

Now when I'm ready to use these settings in another batch file, I can invoke it like so:

@ECHO OFF

SETLOCAL ENABLEDELAYEDEXPANSION

FOR /F "tokens=*" %%n IN (build-configuration.txt) DO (	
	ECHO %%n

	SET %%n
)

ECHO %SPURL%
ECHO %SQLCONN%

PAUSE

There are other ways to do this as well, but the downside to most approaches is that you have to know how many parameters you have or use less meaningful names.  This approach will let you set variables to your heart's content and read them in dynamically at execution.

Filed under: Awesome, Dev, Self Note No Comments
5Dec/13Off

A Simple Way to Improve CAML Query Performance

Posted by Charles Chen

There are many ways to improve the performance of your CAML queries, but I've recently found that in some cases, it's as easy as switching the order of your filter operations.

In this case, I was searching across a list of 1,000,000 items for a set of 41.

The list consists of tasks with, among other fields, a Status and Assigned To field.

Both of these fields were indexed, but the following query was still running in the 10 second range:

<Where>
    <And>
        <And>
            <Neq>
                <FieldRef Name='Status' />
                <Value Type='Choice'>Completed</Value>
            </Neq>
            <Neq>
                <FieldRef Name='Status' />
                <Value Type='Choice'>Terminated</Value>
            </Neq>
        </And>                                             
        <Eq>
            <FieldRef Name='AssignedTo' LookupId='TRUE' />
            <Value Type='Int'>159</Value>
        </Eq>
    </And>
</Where>

One small tweak and the same query ran in 1.5s:

<Where>
    <And>
        <Eq>
            <FieldRef Name='AssignedTo' LookupId='TRUE' />
            <Value Type='Int'>159</Value>
        </Eq>	
        <And>
            <Neq>
                <FieldRef Name='Status' />
                <Value Type='Choice'>Completed</Value>
            </Neq>
            <Neq>
                <FieldRef Name='Status' />
                <Value Type='Choice'>Terminated</Value>
            </Neq>
        </And>                                             
    </And>
</Where>

All that was done was to shift the order of the query conditions.

The first query reads as "All tasks that are not Completed and not Terminated and Assigned To user 159".

The second query reads as "All tasks that are Assigned To user 159 that are not Completed and not Terminated".

I didn't trace the generated SQL, but it's not hard to imagine that the SQL now performs an initial filter on the data set against the user ID and returns a much smaller data set for subsequent operations (filter by Status).

So the lesson learned is that for large lists, you need to follow Microsoft's guidance on large lists, but also ensure that your queries are written to take advantage of the indexes and reduce the data set as early as possible (preferably against an indexed field.).