Blog Banner

Entrepreneurial Engineers

Sociable Labs was founded on the lean startup model and the idea that everything we create should be tested and validated to have real ROI. This means that we question everything we do with “how is this is improving our product and providing real ROI to our customers”.

In product management and engineering we strive to follow this approach in a number of different ways. When we design a new application we do extensive usability testing to determine if users actually find value in it. When we tweak an existing feature we follow experiment-driven-development and perform real-time A/B testing to determine if that change creates lift – if not it gets dropped. When we refactor code our engineers focus on those areas that provide the most ROI to our business and are most beneficial to our customers – not all software is created equal.

In a sense we are elevating our engineers beyond coders to “entrepreneurial engineers” who blend their engineering skills with business accumen, make design decisions based on real metrics and create software and technology backed by real ROI.


Wiring up Model-View-Presenter UIs using Google Gin

We make heavy use of Google Web Toolkit in our dashboard systems: Analytics, management, configuration, and so on. In order to make these applications clean, testable, and modular, we apply the Model-View-Presenter pattern. However, MVP alone is not a particularly good pattern – views are tied to presenters by a controller class and have a circular dependency with their presenters. Changes to the system can require altering multiple moving parts.

This is where we’ve applied Google Gin as a way to create a more loosely coupled implementation of MVP. We still have to put up with the view/presenter circular dependency, but it is cleaner and more manageable now.

Here is how:

First, the GWT module initializes the dependency injection cascade by asking an injector we wrote for the controller class:

    private final AppGinjector injector = GWT.create(AppGinjector.class);
    public void onModuleLoad() {
        injector.getDashboardController();
    }

Read the rest of this entry »


Refactoring away Singletons with Google Guice

We’ve been engaged on a number of projects lately, such as integrating the and jsTestDriver on the front-end and rolling out Guice and ASM on the back-end.

One of the most enjoyable aspects of these projects has been refactoring the Singletons in our system: We see the typical implementation of Singletons as an anti-pattern that creates tightly bound systems with tangled dependencies.

Rather than showing our own code, I wrote a simple project to illustrate one way we get rid of Singletons. The Main function starts up a pair of Singletons, lets them do some work, and prints out the details:

        EventListenerService.get().initialize();
        EventGeneratorService.get().start();
        Thread.Sleep(100);
        for(Event e : EventListenerService.get().getRecordedEvents()) {
                System.out.println(e.info);
        }

Read the rest of this entry »


Server Side changes for Facebook’s OAuth 2.0 upgrade


This is our second post on OAuth 2.0, and covers server-side changes. To see our previous post on changes to Facebook’s Javascript SDK, read here.

Facebook is upgrading their platform authentication system to OAuth 2.0. During the transition time, both the new system and the old system are supported, however, starting October 1st, 2011 the old authentication system will no longer be supported. Any apps that depend on it will stop working.
Read the rest of this entry »


JavaScript changes for Facebook’s OAuth 2.0 upgrade


Facebook is upgrading their platform authentication system to OAuth 2.0. During the transition time, both the new system and the old system are supported, however, starting October 1st, 2011 the old authentication system will no longer be supported. Any apps that depend on it will stop working.

Update: Facebook missed their original cutoff date, however as of December 13, 2011, all apps are now forced to OAuth 2.0 and apps that depend on the older system no loner work.

Facebook initially announced this on May 10th, and later put out updated information once the various SDKs had been upgraded to support the new system. However, details on what code changes were necessary to support the new system were fairly limited.

This post covers every change we’ve come across so far to support OAuth 2.0 with FB’s JS SDK

Read the rest of this entry »


On Layering

While we only sell a single product – our Social Commerce suite of applications, internally, we’ve had to build a number of commercial-grade systems, some of which could be seen as products in and of themselves.

Product 1: First of all, in order to deliver components into remote websites at massive scale, we’ve had to build a sophisticated platform that can deliver content across the web, and integrate data from multiple websites while remaining cross-browser compliant. This platform is built on Java, AWS, CloudFront, Memcached, and other sophisticated “shoulders of giants” systems.

Product 2: Next, in order to deliver analytics over these components, which can be loaded thousands of times per second, we’ve had to develop an analytics platform based on Pig, Hive, Hadoop, S3, and Postgres. This is a layered system, providing multiple tiers of services. We’ve also had to develop our own link shortener.

Product 3: The most visible of our products is our suite of social applications. These build on top of the other two products to deliver trackable, scalable, personalized social content to users. This system, built using JavaScript, YUI, Freemarker, Java, Ehcache, Memcached, and Postgres, sits on a complex multi-tenanted graph database that tracks social graphs and provides deep personalization data.

By treating each part of the system as a standalone product, and building each one to the highest level of performance and API quality, we ensure that new products can be rapidly built by leveraging existing technology investments, which allows us to innovate at a business level – where, at the end of the day, it really counts.


On Shortcuts

Startups are often kick-started with a prototype. Perhaps not much more than tape and baling wire, this prototype can get the company users, noticed, funding.

Success is when the moment of true danger is, and the test of top-notch engineering and product leadership: Success is when you need to grow and evolve your system.

If you have the luxury to throw away your initial code and start from scratch, you’re in an unusually good position. If you aren’t, then the decisions made at the prototype stage have a profound impact on your forward velocity. A badly written prototype, full of cut corners and shortcuts is going to severely impair your ability to write new features, to find and fix bugs, to write a world-class test system.

The key is to know where to take shortcuts, and this applies even beyond the prototype stage: Never, ever take shortcuts on architectural correctness or code quality. Take shortcuts on features, on configurability, on performance. Don’t make every part of your system configurable, but architect it so that it can be. Don’t try to write a massively complex sharding system – rely on a single, robust database with a hot replica. Don’t attempt to give users three ways of doing anything in your system; focus on the path of least resistance.

At each step of the way, build just enough code to validate assumptions and test ideas, but build it right.


On Career Paths

Many of us grow up with the myth that in order to “move up” you must become a manager. Perhaps this is true at some companies.

It certainly is not true here.

There are so many skills that we value – communication, design, problem solving, technical. People can also have terrific leadership skills but not want to manage people. They may enjoy writing code more, or influencing across different groups, or solving difficult design or marketing problems.

So we have two career paths at Sociable Labs. For managers there is a management path. For individual contributors there is an IC path. Thus, a principal engineer can be more highly compensated than their manager. This is not only a fair approach, it is also extremely flexible, allowing folks to grow and be recognized for that growth without running into a prescriptive career path roadblock.


On SaaS and the Law of Large Numbers

Among our design mantras is that everything that can go wrong, will go wrong.

Is the concurrency model not perfect? Under the onslought of 10,000 hits per second, it’ll break.
Is the caching model not thought through completely? It too, will break.
Is there a single point of failure anywhere in the system? It will bring your system down.

We’ve learned to be, and to hire, perfectionists, because shortcuts do not work in a sophisticated, high volume environment. We’ve learned that every solution must be thought through and peer reviewed because any sufficiently complex system cannot be fully understood by a single person. We deploy at least two (typically four) instances of anything.

We are moving towards a model where the system is so loosely coupled that we’ll be able to shut down every single one of our database servers, and have the system continue running with no visible interruptions or loss of data. We can already shut down any web server with no visible effect to the system, as well as seamlessly launch new instances.

We’ve learned to rehearse, to “dry run” all significant operations, and to challenge each other to approach the theoretical limits of operational goodness – to have zero downtime even for significant system changes.

All this requires very different thinking from traditional enterprise systems. It is even different from running traditional high-volume websites, because we are responsible for very different websites across far flung, geographically diverse domains, each with highly isolated data stores running on a shared fabric.

We love the enormous amounts of learning this involves, the need to constantly improve ourselves and our systems to handle constantly increasing loads. If you’ve built a high-scale SaaS system and evolved it over time into a best-of-breed solution that is truly stable under enormous load spikes. If you’ve learned to be a real engineer under these conditions – to understand how to solve problems thoroughly and deeply and to consider issues of monitoring, scale, failure, analytics, concurrency, availability and consistency, then there are few systems you cannot be confident that you cannot build.


On Velocity

Silicon valley moves blindingly fast – Facebook releases new code every Tuesday. Mozilla is on an incredibly aggressive three month release cycle. Open source projects appear like mushrooms after rain and some spread like wildfire.

Sociable Labs release trains go out every two weeks. To maintain this sort of speed, we have a number of systems in place, from automated test suites, smoke testing, regression prevention to architectural and cultural fixtures.

I’d like to cover a few of these fixtures, specifically versioning, complexity control, and decision making.

Versioning
Code is easy to change – drop a new dll, jar file, or code file into place and your CPU has a new set of instructions to run. Data, however, lives forever, and is much more difficult to change. A company can be hampered by the costs of making changes that require data changes. To get around this, thought must be paid at the very beginning of system design to where data lives, and how it is to be quickly and efficiently versioned. The classic problem in this space is database schema migration: Addition of new columns is fairly easy, but renaming columns, splitting or joining columns, refactoring one table into many, or many into few, changing data types – these are complex. Our deployment pipeline accounts for this versioning and has done so since our first prototypes. Configuration management is just as important, however: As we ramp up new customers, customer configuration data rapidly gets more complex, and refactoring and normalizing configuration parameters is critical if we are to keep increasing the power of the system without carrying a heavy debt of legacy complexity. For this, we drive knowledge of versions and how to migrate them into the core of the product, so that any configuration version can be loaded and quickly and transparently migrated to the latest schema without loss of fidelity.

Complexity Management
It is a counterintuitive principal, and one not often seen, that as systems grow, they should become architecturally simpler, rather than more complex: While algorithms may grow in complexity, for example, moving from linear algorithms to non-linear, feedback-driven systems, the execution environment for those algorithms needs to become simpler. Code that starts our as a big ball of mud must evolve into something more beautiful or it will die. Putting in place not only best-practices such as dependency injection, but an engineering culture that understands at a gut-level when a particular code change is going to make the system more brittle, and when it is time to refactor. By having a shared desire for simplicity, and a deep skill at making it happen, enabled by experience, judgement, and collaboration, we drive platform velocity by enabling new code to slot into the system in natural, elegant ways.

Decision Making
We’ll keep this one short and sweet: Decisions have to be made thoughtfully, but quickly. Good decision making is a direct result of clear communication, trust, and a culture of collaboration, where people actively seek out feedback and accept it with an open mind. Priorities are shared and clear: First our customers, then our company, then us.


Follow

Get every new post delivered to your Inbox.