++

In Spring 2003, I was looking around for what would be my first professional job after getting my degree. One interview stands out not only because it’s where I ended up but also because I gave what might be the most terrible answer of my career.

Most of my coursework was in C++, so most of the technical questions were on syntax and defining terms like polymorphism. Somewhere along the way, one of the interviewers asked me what ++ does. I looked at him, thought for a moment, and said something to the effect of, “I don’t know. I don’t think I’ve ever seen that before!”

I’ve come up with all kinds of explanations for this. I had been up late the previous night watching news of the Iraq invasion. I had gotten up early because the office was an hour from campus. Previous questions might have put my mind on some strange track where an increment operator wouldn’t apply. Maybe it was all just an extremely vivid nightmare that I’ve mistaken for reality!

I’ve certainly had other moments where I’ve looked back and realized that I could have done better, but it’ll be hard for anything to knock this one off the top spot.

What’s your most treasured goof?

Posted in Stories | Leave a comment

Thoughts On Transparent Compensation Policies

As always, this is just me and doesn’t reflect the opinions or beliefs of my employers, my family, my dog, my family’s dogs…you know the drill.

A few days ago, I noticed this come across Twitter.

 

I started expressing my thoughts in response tweets, and then I got to a point where it was just too big for Twitter.

An Argument For Transparency

At the risk of appealing to authority with “Spolsky says,” I think he has some great points in his old post about Fog Creek Compensation.

Many companies try to obfuscate the rules they use for determining compensation in hopes that they won’t get caught paying some people too much and others too little.

Wait. “Get caught”? That makes it sound so criminal! Wide swings are understandable, aren’t they? It’s just business, isn’t it? Everything is negotiable. A business has a fiscal responsibility to minimize its costs wherever it can, and that includes salaries!

So the best hire you’ve ever met comes in with no clue how to negotiate and hastily accepts a lowball offer. A smooth talker shows up and extracts twice the pay for questionable quality. The latter is told, “Be sure not to speak of this to anyone – we can’t to give this deal to all of our folks, but you’re worth it!” Everyone is happy until…

We feel that in the long run, this can only hurt us through negative morale, high turnover, and destructive office politics.

It doesn’t matter what policy is in place to keep people quiet, teammates become friends and friends talk. The awkward moment comes when they think they’re equally valuable to the business, so one talks money. The other says “Ha, right. Maybe we’ll make that much in a few more years!” Then the first says, “What? You’re not making that now?” The first feels guilty, and the second feels slighted. It’s bad news all around1.

Could it get worse? You bet! Imagine an entry level new hire with a big mouth lets his salary slip to the team. Imagine that it’s higher than a few of the senior devs who stuck with the business through some really tough times. Imagine the resentment1, and realize that it’s not just the victim who stews on this. The whole team feels it2.

This transparency policy is a good thing that forces Fog Creek management to keep things fair.

In the above situations, management believes that the “don’t tell!” policy is actually being observed, so they continue with their shenanigans while developers seethe in angst. The developers try to address the situation, but they have to pull punches so as not to admit that the policy has been broken. Management takes it in stride and continues with their shenanigans. They ice the cake with the standard “We just can’t afford to give you a raise – you’re already paid higher than many others so please don’t discuss your salary around them!” Rinse, repeat, resign4.

An Argument Against Transparency

Well, if you make it all public, you’re basically inviting and expediting all the negative consequences above, aren’t you? When you instruct your people to keep quiet, you’ve at least got a chance. If levels and salaries are made known, you’ve guaranteed the losing scenario!

Unless…

It’s that third quote from Spolsky that does the trick. This time, I’m adding emphasis and a footnote of my own.

This transparency policy is a good thing that forces Fog Creek management to keep things fair5.

Take a look at the “Determining Levels” section of that post again. There are different facets (years of experience, education, enabling the team, skill, role) that give overlapping guidelines about what level a person could be in. This lets everyone understand why they’ve been put in a certain level, and it provides guidelines on what they can do to push toward the next.

In Spolsky’s scheme, if I’ve got 4 years of experience and a Bachelor’s, should I be surprised that I’m Level 11? If I want Level 12, I can wait a couple of years, or I can try to become an “Enabler” to get that boost. If I care more about the money than the title, I could strive for the “Superstar adjustment.” Now I’m earning the salary of an “11.5”, but the whole team has agreed that I deserve it.

Continuing in this scheme, if I look at Sally and she’s a level 14, I know why. It’s not because she negotiated better – it’s because she’s got 10 years, a PhD, and regularly offers up “lofty thoughts” about how the business can excel.

Whether the scheme itself is perfect6, just having a scheme at all establishes a framework. I know what I’m making. I know what Sally is making. She knows what I’m making. The whole team knows what everyone is making, and we all know why. More importantly, we know that politics won’t change it. Now we can all focus on getting things done. We can turn our attention to competing with our competitors instead of with ourselves. In doing so, we naturally grow in age, skill, and business strategy – all of which move us toward the next level.

So, what’s my answer?

This post certainly makes it sound like transparency is the hands down winner in my mind, but I can still argue it either way. If you’re building a new business, starting out transparent sounds like a great idea. For an existing business, transitioning into it will be much more complex. Like I told Darin and Jim, in my first response on Twitter,

 

If there is currently a labyrinth of arcane calculations and manipulations that no one understands, suddenly going transparent is going to bring a lot of disappointment. Even if it leads to a positive effort to put everyone where they should be, trust in management could already be broken if someone feels they’ve been cheated.

Looking at another scenario, let’s pretend it’s already completely fair when everything is unveiled. If the team has a surplus of immature or conceited folks, they could be upset with their relative position once the curtain is drawn. If Buck thinks he is heaven sent but suddenly realizes he’s in the middle of the pack, Buck might start looking. Then again, it sounds like maybe this team is already toxic.

So, Jim, I’m going to bring this back to your original question, broken into three parts.

  1. How would I feel if my salary was public knowledge? Meh.
  2. (and everyone else’s)? This is the complicated bit. I’m really not sure that I’d be interested enough to look at it. I think I’m paid fairly and my family is happy, so what does it matter if Mickey or Minnie make more3? If I did look, I’d like to think that I’d reflect on it and come to humble acceptance in any case. I’d hope that the rest of the team would do the same. I’d be more concerned with the potential aftermath than with the transparency itself (i.e., don’t care if salaries are public, do care whether the team self-destructs or grows to a new level of maturity).
  3.  Would this solve or cause more problems? Let S be the number of problems solved and C be the number of problems caused. (S > C) || (C > S) will be true as for any S, C where S != C.

Obviously, my perspective is based on my experiences. I’d love to hear what others think based on what they’ve seen. Comments section below, after an uncommonly long set of footnotes.

1 Have I seen this happen firsthand, heard it from a coworker, heard it at a conference, or cut it from whole cloth? I will never tell ;-)

2 I suppose that part about the whole team feeling it depends on the team. I’ve been lucky to have pretty much always been on fantastic teams where we all get along and sing kumbaya together at lunch. Alright, I made up the kumbaya thing, but really, brothers and sisters in arms and all that jazz.

3 This doesn’t necessarily mean that I’d be disinterested in earning more myself. Having more to put into savings, investments, early retirement – nothing against that. But that’s my situation. Mickey and Minnie’s are, at best, nothing but objective data points for a discussion about my own earnings.

4 I’m about to change jobs. It has absolutely nothing to do with this kind of situation. I want to make that abundantly clear.

5 Remember from your logic classes that this doesn’t mean an absence of the policy implies an absence of fairness. This is not the only way to keep things fair, it’s just one way.

6 I’m not sure that I entirely agree with Spolsky’s criteria, but to be fair, the post was from 2000. A lot has changed as people have greater access to training outside of a university setting. I’ve seen a person with a Master’s who could not solve problems more complex than untied shoelaces, and I’ve seen a person with no degree whatsoever blow my mind.

Posted in Uncategorized | 3 Comments

Updates pushed to asfac master

Integrating asfac into a real production codebase brought some necessary enhancements to our attention. The following updates have now been pushed to master.

Register and Resolve with Class Scope

Suppose you have an IDoWhatever interface, and you have some concrete implementations like DoWhateverToFoos and DoWhateverToBars. They both implement IDoWhatever, but the former is to be used for Foos while the latter is for Bars.

You can now use the Class object or any instance of the Class as the registration scope. In particular, this came in handy when we had command handlers for various command classes.

// Standard
factory.register(FooCommandHandler, IHandleCommands, FooCommand);
var handler:IHandleCommands = factory.resolve(IHandleCommands, FooCommand);

// Fluent
factory.inScope(FooCommand).register(FooCommandHandler).asType(IHandleCommands);
var handler:IHandleCommands = factory.fromScope(FooCommand).resolve(IHandleCommands);

Resolve with Fallback Scope

We also had some cases where a class wasn’t registered in the specific scope being requested, but it was registered in the default scope. For example, a default command handler doing some logging might not find the registered ILogger in its own scope. It is now possible to specify to asfac that you’d like to take a look in the default scope in the case where a resolution cannot be performed from the specified scope.

// Standard
factory.register(ConsoleLogger, ILogger);
var logger:ILogger = factory.resolve(ILogger, "SomeScope", true);

// Fluent
factory.register(ConsoleLogger).asType(ILogger);
var logger:ILogger = factory.fromScope("SomeScope").resolveWithFallback(ILogger);

Bug Fixes

We also found a few bugs that are now fixed (with accompanying tests, of course!). Basically these were all chalked up to scoped registration using the fluent syntax.

Consider this code:

factory.inScope('foo').register(Bar).asType(IBaz);
factory.register(Widget).asType(ISprocket);

We found that Widget was actually registered in scope ‘foo’, and we expected it to be in the default scope. We hope asfac users agree. If you did indeed want to register many things into a common scope, you can do it like this:

var scopedRegistrar:IRegister = factory.inScope('scope');
scopedRegistrar.register(Bar).asType(IBaz);
scopedRegistrar.register(Widget).asType(ISprocket);

var scopedResolver:IResolve = factory.fromScope('scope');
// you get it…

If you’re using asfac, please let us know what you think. If you run into any problems, please log an issue on github. Thanks!

Thanks Adobe

Also, thanks to Adobe for tweeting about asfac. However, we want to clarify that the video embedded in Joey’s original asfac post is not us creating asfac. It’s Jon Skeet hacking out IOC concepts in C#.

Posted in Development | Tagged , , , | 1 Comment

Roy Osherove’s SOLID Kata–String Calculator Redux

Roy Osherove recently posted a challenge to refactor a simple StringCalculator using SOLID principles. Sounds fun to me!

Here’s his original gist showing a StringCalculator.

Responsibilities

This thing is doing at least two things, and I contrived a third.

  1. It is parsing string input into a set of integer values
  2. It is performing the sum operation
  3. It is defining a default result in the absence of valid input

I think perhaps it should only be responsible for the second of these. It is a calculator, so parsing should certainly be outside of its scope. We will save the definition of the default result for later. First, let’s separate parsing.

Creating IntParser

The first thing I did was create an IntParser with a single method. This method accepted a string of input and returned an IEnumerable of int values.

public class IntParser
{
    public IEnumerable Parse(string input)
    {
        int x;

        foreach(var part in input.Split(','))
        {
            if (int.TryParse(part, out x))
                yield return x;
        }
    }
}

Integrating IntParser

The simplest thing to do next was to accept an IntParser as a constructor parameter for the StringCalculator class. Now instead of the Add method checking the input and deciding how to get ints from it, it simply delegates that responsibility to the dependency.

public class StringCalculator
{
    public int DEFAULT_RESULT = 0;

    private readonly IntParser parser;

    public StringCalculator(IntParser parser)
    {
        this.parser = parser; // you could guard against null if you want
    }

    public int Add(string input)
    {
        var ints = this.parser.Parse(input);

        // Uh-oh. The way I’ve implemented this, I still pass the tests
        // but I have eliminated the explicit check for empty=>0.
        // It is only 0 by an implementation coincidence.This is however
        // irrelevant to the SOLID part of this exercise, so I'll leave it
        return ints.Sum();
    }
}

What have we achieved here? Well, the StringCalculator class is now immune to changes in how we handle or parse input. As long as IntParser will deliver some set of integers, it can add them. Is it SOLID now? While it’s better, we still have a long way to go. Let’s assess:

  • SRP – check, we have definitely separated the parsing
  • OCD – fail, this is neither open to extension nor closed to modification; if we wanted to handle new input formats, we cannot easily replace IntParser without changing StringCalculator
  • LSP – defer, as we see no subtypes we cannot analyze the effects of substitution
  • ISP – defer, as we have no interfaces, we cannot analyze their division
  • DIP – fail, we are depending on the “concretion” of IntParser

The Abstraction of IParseInts

Extracting an interface from IntParser, we get the IParseInts interface. StringCalculator can now depend on this interface instead of the specific IntParser implementation.

At this time, let’s also rename IntParser to a more specific IntsFromCommaSeparatedString. This name is somewhat lengthy, but naming is hard and it’ll do for now.

public interface IParseInts
{
    IEnumerable Parse(string input);
}

public class StringCalculator
{
    public int DEFAULT_RESULT = 0;

    private readonly IParseInts parser;

    public StringCalculator(IParseInts parser)
    {
        this.parser = parser;
    }

    public int Add(string input)
    {
        var ints = this.parser.Parse(input);
        return ints.Sum();
    }
}

What does this gain us? Well, now when we write unit tests around StringCalculator we can mock out IParseInts and have a reliable set of ints, even if our parser implementation regresses.

We are also able to extend our system to handle new formats without changing the existing calculator or parser. We’d simply pass the appropriate parser into the constructor. We could add a CanHandle(input) method to our interface and pass all registered parsers into the calculator, and let it ask on a case by case basis which one is appropriate. There are many ways to go here so I will leave it as an exercise for the reader or for a future blog post.

So our responsibilities are separated (SRP), we can extend the system to new formats without changing the existing implementations (OCD), our interface is small and specific to a task (ISP), and the calculator depends on an abstraction rather than a specific concrete class (DIP). We still have no subtypes, but whatever.

IDefault

The other responsibility I contrived above was the determination of the default value. Something about having this as a public const was bothering me.  What if callers wanted to use a different default value, or perhaps even result in an exception if no sum could be calculated. How would they determine whether “0” was because the numbers added to zero, or because the input failed?

So I made an IDefault interface and let StringCalculator depend on this as well. I made two implementations, the SimpleDefaulter which returns default(T) directly, and the ExceptionDefaulter which throws. (As an exercise, you could add a constructor to ExceptionDefaulter which accepts the message to use on the Exception, or a Func<Exception> that will construct the Exception on demand, or a Func<string, Exception> that would do the same but be able to utilize the string input…the sky is your limit).

public interface IDefault
{
    T GetDefault(string input);
}

public class SimpleDefault : IDefault
{
    public T GetDefault(string input)
    {
        return default(T);
    }
}

public class ExceptionDefault<TValue, TException> : IDefault
    where TException : Exception,new()
{
    public TValue GetDefault(string input)
    {
        throw new TException();
    }
}

public class StringCalculator
{
    private readonly IDefault<int> defaulter;
    private readonly IParseInts parser;

    public StringCalculator(IParseInts parser, IDefault<int> defaulter)
    {
        this.parser = parser;
        this.defaulter = defaulter;
    }

    public int Add(string input)
    {
        var ints = this.parser.Parse(input);
        if (!ints.Any())
            return this.defaulter.GetDefault(input);

        return ints.Sum(x => x);
    }
}

One might have been tempted to add this behavior to the IParseInts interface – after all, the default is only used in the case when the parsed ints are empty. However, we have practiced ISP by creating a separate, specific interface. Some systems might need defaults without parsing, or vice versa. Now either interface can be implemented without the baggage of the others!

Going Further?

We could go pretty crazy, but I think it’s good enough for now. A couple of things I might do differently if I wanted to spend more time on this? Here is one thing that immediately comes to mind. In the above, “a,b,c” and “David” will behave exactly the same as “”. The default will be executed whether the set is empty or invalid. Thoughts regarding this:

    • This is currently an implementation detail of our IntParser class. It eats parts that cannot be parsed as ints.
    • We could change the spec of that implementation, but probably the “business” will want this to be consistent regardless of the parser or input format so…
    • We could have an IValidateInput interface, or add an IsValid to the existing IParseInts interface. IValidateInput is probably a more strict following of ISP, but could be overkill. In either case, I think the concrete implementation would have the responsibility of implementing both methods – the choice in my mind is simply whether it has to implement two interfaces or just one.

Update: Another thought is that while we have opened things up to support multiple string formats, we still only support string inputs. We could abstract this to instead of having IParseInts which parses a string, have something like IProvideInts, and instead of .Parse, have .RetrieveAll. The add method would then either accept an IProvideInts parameters instead of a string, or it would just directly accept the set of ints (having been obtained previously by the caller).

Conclusion

So here is my final gist.

I hope you enjoyed reading about this experience as much as I enjoyed going through the exercise. This is nothing groundbreaking but perhaps it will help SOLID click for someone. Also, I’d be very interested in any comments about what I might have missed or mistaken, or links to your #solidkata exercises so that I can learn how others approach the task. Happy coding!

Posted in Development | Tagged , , | 2 Comments

Did both ESRI and MapBox steal from Fitbit?

Note / disclaimer: I work for 3-GIS, and we work a lot with ESRI. This blog post does not necessarily represent the views of 3-GIS, ESRI, MapBox, Fitbit, or any other entity. These thoughts are my own and are hopefully unbiased. I’m just a web developer and don’t have a stake in this. I simply find the implications for web development and site design to be interesting.

“ESRI, shame on you guys!”

The other day, I saw several tweets regarding ESRI’s new ArcGIS for Developers website.

James Fee even wrote a blog post about the emulation of MapBox. From his assessment of the situation:

I’d like to think there wasn’t malicious intent here, just that those who created it want to be like MapBox and Developement Seed. Still, when the 800lb (363kg) gorilla does things like this, you can’t but help call it a dick move.

I was on my phone at the time. Clicking through to both websites, all I thought was…

All Bootstrap Everything

Upon investigation of the sources, it seems that not all of these sites are indeed using Bootstrap specifically. However, I think the style is evident. The Bootstrap style has become so ubiquitous on today’s web that there are even sites dedicated to helping you un-Bootstrap your Bootstrap.

The Simpsons Already Did It

If we follow the evolutionary chain of ESRI to MapBox, then surely we must follow MapBox’s back to Fitbit. Note that all three share the design elements listed below, and note that you could probably find countless more sites that share the same.

  • a tall header
  • rounded buttons
  • pleasant typography
  • lots of scrolling down
  • a feeling reminiscent of a grid system (or actual use of a grid system)
  • columns of links at the bottom

There was one tweet that pointed out the use of cartoon maps in circles.

MapBox's cartoony map icon

MapBox’s cartoony map icon

ESRI's cartoony map icon

ESRI’s cartoony map icon

I want to be clear that even the idea of “cartoon” icons in circles is not a groundbreaking design technique. Fitbit has that too (decision for color vs. silhouette notwithstanding); they just didn’t need a map in their domain.

Fitbit's cartoony icons

Making It Your Own

Here are a few of the obvious differences between the sites

  • MapBox uses ALLCAPS NAVIGATION, Mixed Case Navigation for ESRI
  • Social links are presented quite differently
  • MapBox has an introductory video, while ESRI has various text areas
  • Signup placement is raised for MapBox, inline for ESRI
  • MapBox colors their footer, ESRI does not
  • MapBox put their logo on the left, ESRI on the right

Now admittedly any of these changes taken individually would be trivial, but when taken together, I find it unlikely that ESRI said, “You know, MapBox is pretty. Let’s steal their CSS!” I think it is much more likely that ESRI said “You know, on our new site, let’s go with the prevalent patterns taking over the web today, and incorporate a tall scrolling site with rounded buttons.”

Benefit of the Doubt

Hey internet, let’s try to play nicely together. Like I said in the note/disclaimer, I have no dog in this fight. I’m just a developer, currently developing for the web.

I will give those pointing fingers some benefit of the doubt. Perhaps I missed design elements that truly were plagiarized, rather than just being common to today’s web. Perhaps they really haven’t seen so many other sites with Bootstrap qualities, and honestly thought MapBox’s site design was novel.

On the other hand, maybe we can extend a similar courtesy to ESRI and restrain ourselves from wishing death upon them.  Perhaps they are just last in line to pick up on this style. I maintain that MapBox was certainly not the first. If accusation becomes our default response, what will we all have to do for our next site design?

Posted in Design | Tagged , , , , , | Leave a comment

The Story of asfac

Asfac is a simple IoC container for ActionScript and this is the story of how it came into being.

Genesis

It is all Jon Skeet‘s fault really. I rediscovered this gem of a video he recorded with Rob Conery for a series on TekPub. In the video Jon creates a functioning IoC container in matter of minutes.

I was unfamiliar with the concept of containers at the time, but the basics looked simple enough. So I set out to learn more by implementing a container for ActionScript. Why ActionScript you might ask? I wanted to explore the concepts without directly copying Jon’s code. My first stab at the container lives as a Gist and is a pretty straight port of Jon’s code. A good start perhaps, but I wanted better.

Work in Progress

Asfac represents my first project written with a TDD approach and an excuse to try out new development processes. After getting Dave on board, we paired going back and forth one writing a failing test; the other writing the code that would make it pass. This went on for a while until we had gotten the equivalent of Jon’s container working in ActionScript. I was excited. Not only did TDD keep me very focused on individual requirements but pairing was great for keeping me on task.

With a functional container written, Dave wanted to see how far we could push it. He had already been using containers in his .NET work and wanted to bring some sugar over. So we started making our wish list of functionality; things like a fluent interface, scoped registration, and property injection.

We then entered all this information into GitHub. We took advantage of the issue tracking for logging bugs and enhancements, worked in feature branches during development, and issued pull requests for the other to code review. Basically what I consider to be a healthy development process.

Stick in the Mud

With development of all the functionality wrapping up there was only one task left to accomplish, Documentation. We knew that asfac certainly didn’t need a book to use, but it did need to be documented. Dave opened an issue and created a branch. He reorganized the sample code in the read-me this time with better descriptions. We started reviewing the API documentation in the AsDoc comments and then it all stopped. Months passed with a releasable version of asfac sitting around waiting to be documented.

The new year has a way of stirring some self reflection. Over the winter break I started making a mental list of where I could improve over the next year. One area that seems to be on every year’s list is ‘finishing’. Why wait another year to see if I could get better at it? Start finishing now!

I cloned the asfac repository and gave it a proper review. I standardized things like comments being in sentence structure not as fragments, fixed variable names that had long since changed in the code, and pushed it all up to GitHub for a final look over. It only took a week to sync up with Dave and get it all merged into master.

Wrap up

So it took a while but we are at v1.0. We finished something we started. Success! So if you are using ActionScript and have need of an IoC container, then please take us into consideration with all the others and let us know how we stack up.

asfac on GitHub

Posted in Uncategorized | Leave a comment

How to Make Google Hangout Screen Share Bigger or Full Screen

I work remotely quite a bit, so I do a lot of screen sharing and remote meetings. My team uses Google Hangout a lot. We’ve evaluated a few other options, but Hangouts are good enough for now. The one thing that has troubled us is that there’s a lot of chrome (no pun intended) around the video itself, so sometimes it’s hard to see what’s being shared.

standard

Look at all that wasted whitespace! Everyone’s first thought, of course, is to just take the browser full screen.

fullscreen

That doesn’t gain us much. A couple of nights ago, I stumbled upon a rather unintuitive way to accomplish what we’ve always dreamed of. Zoom out.

zoomed

By zooming out in the browser, the sidebar and participant list shrink. The video grows to fill the remaining space.

You might still have some bars on the left/right or top/bottom due to aspect ratios, but this is the same thing you’d get watching a 4:3 show on a 16:9 TV or vice versa. The above screenshots are sharing a 1280×1024 monitor and viewing on a 1333×768. Here’s what the opposite looks like.

wide

Hope this helps someone.

Note: Going “on air” supposedly lets you take the video full screen. I haven’t tried this, as many of our meetings involve confidential business information. If your discussion is less sensitive, you could always give that a go.

Posted in Working Remotely | Tagged , , | 1 Comment