Saturday, February 1, 2014

SASS & BEM: how I improved compilation speed

Recently I finished a project which was using BEM methodology and SASS.

SASS is extremely useful, partially thanks to Compass framework, but I experienced a couple of issues when using it with BEM:

First, I was disappointed because older versions won't support this nice nested rules which Less CSS provides, to create .block__element class names:
.block {
    color:blue;
    
    &__element1 {
        color: red;
    }
    &__element2 {
        color: green;
    }
}

Though recent SASS v3.3 can do this:
.block
  color: red
  &__element
    color: red
  &__element
    color: green

Second, SASS, splitted to lots of small files, happened to be extremely slow.

Project layout for Django with BEM looked like this:
    base/
        static/
            base/
                base.sass
                button-mixins.sass
                base.js
    app1/
        static/
            app1/
                base.sass # includes base/base.sass
                base.js
                b-content/
                    b-content.sass # includes app1/base.sass 
                b-header/
                    b-header.sass
                    b-header__menu.sass
                    b-header.js
                b-footer/
                    b-footer.sass
                    b-footer__ads.sass
        templates/
            app1/
                b-content/
                    b-content.html
                b-header/
                    b-header.html
                    b-header__menu.html
                b-footer/
                    b-footer.html
                    b-footer__ads.html
    app2/
        static/
            app2/
               ...
        templates/
            app2/
               ...
    app3/
        ...

So it's a complex hierarchy of SASS files including each other.

And total CSS built time for was about 18 seconds (sic!) with SASS caching enabled. Imagine how much time you spend on refreshing pages when you make your web pages.

When I joined to work on this project, my first goal was is to try to increase performance yet retain current layout, if possible.

C++ implementation of SASS looked interesting, but lacks of Compass support.

Here are rules using which I improved SASS compilation speed drastically (tested on SASS v3.2.12):

1. Import only what you need, where you need it

Never use @import "compass", import exactly what you need in a .sass file where you need it, e.g. @import "compass/css3/border-radius" where you need to do +border-radius(). Otherwise it will import too much reducing performance. Global imports will result in unnecessary imports in all .sass file hierarchy branches. Applying this rule, I reduced SASS compilation time from 18 to 9 seconds. Also, looks like if you do @import 10 times in a file, it will be included & parsed 10 times.

Same to project's own .sass files. Reducing number of imports in project's own .sass files carefully won me also 1-3 seconds depending on case.

2. Compile only one SASS file for one page.

Initial setup used Django-Compressor, to collect lots of .sass files into one page. Though Compressor may compile everything into single CSS file, it does .sass files one by one.

The solution was is to make exactly one .sass file per page you use, and import all other .sass files into it. I.e. each Django template used one all.sass file.
    app1/
        static/
            app1/
                base.sass # includes base/base.sass
                base.js
                b-content/
                    b-content.sass
                    ...
                ...
                all.sass # includes base.sass, b-content.sass, etc

This won me about 5 seconds more, as starting ruby process for each .sass file took about 100ms.

So I've got about 1 second of compilation time and the issue was solved for me.

Still not sure about Sass v3.3, release notes saying it has some speed improvements.

Sunday, September 8, 2013

Automated testing & development psychology

It's vital that you receive feedback for a work you've done - the sooner the better.

I myself too aware of situations, when you don't get enough feedback from your job in software development. Sometimes managers don't provide developers full details on their plans, sometimes they don't realize themselves. A product is not always properly tested. Frequently it's written as an experiment, a prototype, or it's not intended to be in use in the nearest few months. These situations can reduce developer's motivation.

How a developer knows that what he's done will work properly?
How he knows that he has done well today?

Job is being different.

Frontend developer is in a better position, as he checks result of his job directly. Yet in case of more complex interfaces, his product will behave differently in different cases, e.g. different devices or custom widget layouts. Even when you just do HTML and CSS, you have to be aware of smartphones and tablets quirks.

Backend developer sees nothing. If he owns great memory & imagination, and nobody distracts him with minor tasks and fixes or personal affairs, he can keep a small system (or a module) in his head, and see that he'd done all properly, and praise himself.

Though if he's working on multiple projects simultaneously, and distractions emerge constantly, it's impossible to work that way. If it's possible yet, a project is becoming too dependent on human factor, i.e. on intellectual strength and disposition to errors of one single person.

How it can be solved?

In case of backend & frontend, you can give both parts of the job to single person. This means he or she can check results quickly, but it won't work for complex systems. If backend and frontend is written by two different persons, too much time will be spent for bug report exchanging (I myself been in such situations, at both sides).

One can write backend together with automated tests, and this will result in immediate feedback, and a feedback system for all features for future. This gives confidence, and most important, a chance to learn on one's mistakes.

The sooner we get feedback on a job we've done, the better we realize this feedback.

What else?

I myself like to start a phase of  work with some refactoring. It's pleasant as the task is changed: your job at the moment is not a new feature, but a better code structure. You check yourself only by assuring that old features are working as before.

Another advantage is that automated tests also give a chance to see your code from another point of view, even if you're tired because of large amount of job. This may result in a better module or public API design, and better readiness for generic usage.

And again:

  • Feedback is a vital condition to learn and improve. It's just how our brains work.
  • Sooner you receive it, more you'll get from it.
  • Feedback makes you feel content.

Sunday, July 21, 2013

OOP & JS, Template method pattern

Recently I finished an app with complex Backbone.js-based interface. It resulted in hierarchy with 3 levels of hierarchy, with about 10 final classes. Here are a couple of ideas on how to manage this hierarchies and make it simpler.

A bit of fantasy

Let's describe an example app. I always wanted an universal dashboard for daily use. It could show statistics on communities I'm interested in, information on websites & servers I maintain, a weather report for the next weekend, filtered news, and so on. It also will provide some controls.

The goal is to get up in the morning, and check everything you need in 10 minutes.


Dashboard implementation

Our dashboard will be just a space, filled with widgets. Each widget shows a piece of information:

Each widget is an object. I'm using backbone.js for interface implementation, and we won't dig into it's details, but we'll examine a simple OOP pattern done with Backbone. It gives us a base class named Backbone.View, from which we inherit our widgets. Method, which displays a widget is called render():
(You can see a simple example of entire backbone.js app here)


App.views.Widget = Backbone.View.extend({
    template: <...>,
    render: function(){
        // Show widget's DOM using model's data:
        this.$el.html(this.template({model: this.model.attributes}));
    },
});


Let's assume we already have an implementation of single widget, which fetches data from server, and shows the widget:

But our goal is multiple widgets, with different functionality!

What is common among all widgets?
  1. They are tied to corresponding Backbone models with data.
  2. They can be moved, hidden, deleted, their size can be changed. This means render()method will also add some common controls.
From now, common functionality requires that we create a widget's base class:

App.views.Widget = Backbone.View.extend({
    template: <...>,
    initialize: function(){
        // redraw after model change
        this.model.listenTo(this.model, 'change', this.render);
    },

    render: function(){
        // Show widget's DOM, using model data:
        this.$el.html(this.template({model: this.model.attributes}));
        // Adding common controls:
        ...
    },
});

What's the difference between widgets?
  1. One kind of widgets just shows data: a diagram or a picture.
  2. Another kind of widgets is used for making some actions. E.g. to change a status in all social networks. The most convenient way is WYSIWYG approach, i.e. we change an input field - and it's saved automatically. We may have multiple fields in single widget, e.g. we may want to change a "product-of-the-day" in our web store, and add a discount value. All these actions must be applied immediately.
  3. Third kind of widgets is realtime-updating, like Twitter timeline, messages from social networks or support services, forum monitoring. This is similar to 1st kind, but should update in real time, using comet approach, or websockets.


3rd kind example suggests that we don't know which requirements we'll need to implement tomorrow. We can implement everything using websockets at once, but let's assume we already implemented (1) using simple GET request by timer, and decided to add websockets later, when we already implemented a dozen of (1) and (2), and made some hierarchy... and new change in functionality will affect this hierarchy. More specific, we need to connect to websocket in initialize() method:


App.views.RealtimeDiagramWidget = App.views.Widget.extend({
    initialize: function(){
        // Initialize base class:
        App.views.Widget.prototype.initialize.apply(this, arguments);
        // Subscribe to websocket:
        App.websocket.on('graph-update', _.bind(function(){
           // update Backbone model with widget's data:
           this.fetch();
        }, this));
    },
});

Also we may wish to add new controls. So we need to redefine render() method:


App.views.RealtimeDiagramWidget = App.views.Widget.extend({
    initialize: function(){
        ...
    },
    render: function(){
        // Render base class:
        App.views.Widget.prototype.render.apply(this, arguments);
        // Add new, widget-specific controls:
        ...
    },
});

We want to extend our application, but we don't know which functionality we'll need tomorrow. As we use Backbone, we'll need to change 2 methods: render() & initialize(), and change them in different ways.

Class hierarchy may become too tangled. Let's see:
  • At 1st development iteration we implement base widget class, and few child classes with simple diagrams.
  • 2nd iteration brings us editable widgets, which will automatically save values from their fields. We add a base class for them, named App.views.EditableWidget.
  • At 3rd iteration we add a zoom function to some diagrams, which requires adding new controls showing on mouse over a widget, and also add realtime-updating widget named RealtimeDiagramWidget.

With each inheritance we wrap render() & initialize() functions inside corresponding functions of child class. This brings additional disadvantage: if we need to compose or filter our data, we need to pass them to render() function of the base class somehow. We can add arguments, which looks a bit ugly:

render: function(processedData) {
    if (processedData === undefined) {
        processedData = {};
    }
    var data = processedData;
    data[model] = this.model.attributes;
    this.$el.html(this.template(data));
}

Let's draw resulting connections with blue and green color on a diagram:
Looks too complicated. Our mistake is that we don't need to redefine render() & initialize() methods in each child class. The actual thing we need to do is to change their code in child class.

And here comes Template method pattern.

Let's ditch render() method's arguments and method redefinition. If we need to change the data, just add a hook to get custom data:

render: function() {
    var data = {}

    // Add data from child class, if they're exist:
    if (this._preRenderHook !== undefined) {
        _.extend(data, this._preRenderHook());
    }

    // Old functionality:
    data[model] = this.model.attributes;
    this.$el.html(this.template(data));
}

If we need to add new controls - add a hook which adds new controls:

render: function() {
    var data = {}

    // Add data from child class, if they're exist:
    if (this._preRenderHook !== undefined) {
        _.extend(data, this._preRenderHook());
    }

    // Old functionality:
    data[model] = this.model.attributes;
    this.$el.html(this.template(data));

    // Controls:
    if (this._postRenderHook !== undefined) {
        this._postRenderHook();
    }
}

And so we get a hierarchy without complicated connections:
Obviously, in case of more complex hierarchy we'll want to redefine hooks in child classes to extend them, or to add hooks into hooks. But now we have advantage of plain structure. We also may implement a list of hooks, if needed.

The most interesting thing is that we don't think about child classes functionality when we build base class. When we define a new type of widget, we just add hooks we needed to the base class' hook list. We don't need to worry about hierarchy level.

Classical Template method pattern pattern assumes that base algorithm is already defined. But here we have a simplified kind of algorithm in a base class, which just represents order of execution of it's parts. And we can simply skip those parts if we don't need them.

Profits of such approach:
  • We can add hooks quickly, at each stage of development. They won't affect classes which are already defined.
  • We can put hooks in any place of base class, not only augment it at the beginning and end, as it happens in case of redefinition. If we have too many hooks, it can complicate method's control flow, but we still may tweak order of hooks invocation - which is widget's parts initialization order.
  • Code structure is plain. Methods are not put into each other, instead they're just added to the base class' structure. This is much simpler to read and work with.
Example of execution flow of render() method; "+" is where we add new hooks: