@PubMatic

UI story at PubMatic (From 2011  to 28 Feb 2014)

The beginning

The story of PubMatic started in the year of 2006. The idea of real time bidding (RTB) engine for ad serving was very primitive and unexplored. Founders at PubMatic grabbed that early to market opportunity to create a world class RTB engine for ad serving and within few years it became a leader in digital ad serving domain.

Having started as a start-up, there were lot of challenges. In the first few iterations the emphasis was on putting back-end technology infrastructure in place and creating the base functionality for ad servers. Front-end engineering was a second priority as there were no direct customers to use the platform. Minimum web interface was created in the beginning to use the platform. Being a new phenomenon, customers could not directly use the application and thus PubMatic built Customer Services (CS) team that would actually use the web interface on behalf of customers to interact with the ad server platform. Customer services team was rigorously trained to use the interface.

Soon it was all into booming phase. As customer became acquainted with the technology, they started to directly consume the interface without the help of CS team. Customers also started to demand more features which were not originally planned on the road-map.

As a result, all these new features were being pushed to old code. Initially, there was no UI team and all the front end work was done by backend Java and C/C++ experts. Code quality was obviously not up to mark. UI code (HTML, CSS and JavaScript) started to saturate making maintenance and modifications very difficult. As it is said “If it isn’t broken, don’t fix it.” It was working but it was not possible to work with it.

So PubMatic architectural started to build dedicated horizontal UI team. The initial task of UI team was to re-factor the old code and use object oriented features of JavaScript to create maintainable code-base. The team succeeded greatly in doing this job. This worked for a while but it was not enough. In fact, it was just about scratching the surface.

PubMatic faced with too many new challenges. Things started to increase at exponential rate. Things like amount of data, new features, customer technology integration, SOA based architecture for few customers while REST based for others. As far as UI is concerned, code base was increasing day by day. There were files literally spanning 10000 lines of code. The same challenges started to reappear on the horizon. The performance started to degrade. OOP based code helped to solve the code readability issues but it was just one aspect. Many others questions were still unanswered.

Some of those UI challenges are as described. First, there was no concept of JavaScript and CSS minification. All the pages served to user were not minified. Each HTML page would have more than twenty external JS and CSS files resulting in large loading times. Second, most of the string/UI labels were hardcoded in HTML and JavaScript. PubMatic started to get customers where i18/l10 support was mandatory. It was simply impossible with current UI. Third, many third party libraries and components were used which were often incompatible with each other. To make them work, lots of boiler plate code was introduced that made the code complex. Again there were licensing issues with third party libraries. When these libraries would upgrade, other libraries would create compatibility issues breaking the working code. It was not possible to make use of latest cutting edge HTML5 solutions.

From a coding perspective, there were lots of code duplication cases. Centralized control over the UI was missing. Each page would consist of many different UI widgets from different libraries which would render on page load. The asynchronous nature of JS would create race conditions for those widgets. Developers could not assume the page render flow and had no choice but to continuously poll for widget status creating very messy and little performing code. Further, all the components were very tightly coupled with one another making modifications difficult.

In essence, the underlying problem can be described in two simple words: Scalability and Maintainability.

Quest for the framework

Around the same time, in 2011, I joined the PubMatic. The architecture group at PubMatic was trying to address these UI concerns. The task of UI team was to address these concerns. The team started to focus on scalability and maintainability aspect. The team found the solution in a presentation by Nicholas Zakas, a front end guy at Yahoo at that time. The presentation is available on SlideShare at:

http://www.slideshare.net/nzakas/scalable-javascript-application-architecture-2012

In that presentation, Nicholas proposed a JavaScript architecture based on golden rules of software engineering like loose coupling, module/component based architecture, event driven, MVC based segregation, etc. And so the journey started for the UI team to create a framework and not a library. A framework where flow of control is given to framework and not individual developer (inversion of control). A framework would take control of the application and developer will simply plug in his code and framework will magically take care of the rest. A framework would abstract out cross-browser issues, component behavior, backend API calls, loading of resources, environment separation, etc.

And thus every member of UI team started with the ambitious project of building a custom framework. 

Basic guidelines for framework

There was only one guideline for building the framework. The guideline was exclusion of any third-party library. Only exception is jQuery which is used at a core to minimize the cross browser issues.

Challenge 1: Separation of production and development environment

The first change of the framework was to address the problem production and development environment. In production, one should use compressed minified JavaScript & CSS code that would reduce loading time. Performance is more important than debugging in production. Every page typically use more than fifty JS & CSS files. Instead of sending all those files one by one, a build script is written that would compress, minify and create a single JS and CSS file per page. The build script is written in NodeJS and run during the deployment. In development, debugging is more important for developers to test and build the functionality. So in development environment, a code works as usual in uncompressed format.

Challenge 2: Avoiding duplicate code by reusability (Component driven design)

Every page would typically contain reusable piece of functionality like a date picker, text box, autocomplete, accordion, search field, dialog box, tree list, dynamic table, etc. The challenge was to identify such reusable behavior and abstract them in components. Components were more like classes in traditional senses where each component has well defined behavior and encapsulates unnecessary complexity from the developer. It was also recognized that all the components could not be determined up front and would be an ever going process that won’t cease easily. As of now, there are at least 120 reusable components in the framework. In order for every component to follow similar behavior, Component class was introduced from which every other component would inherit. Each component then would be used across all the pages. This would give a centralized control for making any changes. A change in one file would propagate through all the pages. Also not a single line of HTML is used in component to follow central control principles. Everything is rendered dynamically through JavaScript. For handling performance, extensive use of Document Fragments has been made.

Challenge 3: Loosely coupled architecture (Event driven architecture)

Since every component was individual entity in itself, a way was needed for the component to interact with each other. There were many alternatives available like message queuing, direct referencing, event passing, etc. Owing to the inherent nature of JavaScript, event driven architecture was more natural choice. In such system, each component is unaware of existence of every other component. If component B wishes to alter its state on some state change of component A then component A would simply notify that it has changed and component B will listen for those event changes. Such architecture has little performance overhead of maintaining an explicit event registry but that overhead is quite negligible from viewpoint of modern JavaScript execution engines. Also to keep loose coupling, containment is favored over inheritance. For example, a Search Field component is nothing but a Text Field component with addition Search button and some additional API. So instead of Search Field inheriting form Text Field, it contains Text Field as a contained object.

Challenge 4: View and Component distinction (Business vocabulary)

Since component can contain as many components as it needs, an entire page can be considered as one big component. But such analogy violates the theoretical accuracy of components and reusability. Component by its definition does not contain any business logic. It only encapsulates functionality and its core responsibility that has nothing to do with business logic. Whereas one application page is supposed to solve some business use case when user visits that page and thus independent components when grouped together give rise to some business use case. So to stay in line with this analogy, another core level construct of View is introduced that encapsulates a business behavior.

Challenge 5: Backend communication and API response

This was a challenge on both UI layer and backend layer. A common agreement was decided between a backend API responses and UI layer. A standard set of status messages were established. So instead of developer making Ajax calls from view/page and parsing them, these responsibilities were added to core of framework where API were exposed to developer to consume data. In this way, a view will do its job of showing the data to user and other task will be handled by respective component.

Challenge 6: Segregation of responsibility (MVC)

As View is only supposed to show the data user has requested, there should be a separate module to handle the CRUD operations on Data and thus Models were introduced in the framework. So a View will never make an Ajax call directly. He will simply request the data from Model thought events and Model will in turn do the job of getting the data. Model may pull the data from its internal cache or ask server for the data. And event module acts as a Controller in this scenario making it a perfect variation of MVC.

A Basic code sample coding standards we generally fallow to make component.

#Example. How we organize Javascript code in our application?

The following pattern is the one that I personally prefer and is called ‘module pattern’, where we separate our javascript into logical modules, or namespaces. What you’ll see below is an example of how I would separate my user module.

// Declaring my main namespace
var myapplication = myapplication || {};

// Declaring modules usermodule
myapplication.usermodule = (function() {
    // createMessage: only accessible inside this module
    var createMessage = function(message) {
        return "Hello! " + message;
    }

    return {
        // sayHello is a public method
        sayHello: function(message) {
            return createMessage(message);
        }
    }
})();

// Declaring another module
myapplication.adminmodule = (function(){
    // your code here
})()
// This is how we call sayHello
myapplication.usermodule.sayHello("This is my module");

Some explanation on the code above

Take a look at the previous code and notice how I create my module using the notation below. It makes the function to be executed immediately because of the parenthesis at the end of the command. The result of the execution will be an object which will be set to my variable myapplication.usermodule.

...
myapplication.usermodule = (function() {
    // code to be executed immediately
})();

So applying this pattern to your code you may have multiple modules and you have the control over what you want to make public and what to keep private. Besides your code will be more organized therefore easy to maintain.

Projects at PubMatic

UI Modules developed by me are listed below.

Publisher UI Modules:

  1. Campaign Module
  2. Campaign Mobile Module
  3. AdTag Module
  4. Billing policy Module on campaign page.
  5. Bulk pause resume AdNetwork & placement Pause Resume Module.
  6. Online Help & breadcrumbs Module.
  7. Unified Insight & optimization dashboard Module (HASO)
  8. UI codes revamp optimization
  9. UIBase Framework components development
  10. Revenue Lift (Reports & chart Integration)

Admin UI Modules:

  1. Bulk uploads Frequency cap & Impression cap Module.
  2. Device Detection – Device Modules, Carrier Module, Geo Module
  3. Mobile Targeting & Zip Targeting Module.
  4. Campaign manager & campaign builder Module
  5. Manage Login credentials for Indirect Network Module
  6. Manage Canned Messages & Activity Log Module
  7. Manage Activity Policy log csv download Module

For more details visit : http://www.pubmatic.com

PubMatic Product
PubMatic Product
Advertisements