Author: rderandom

From MVC to Redux

From MVC to Redux

If you come from MVC or one of its brothers/cousins/incredible mutations, this diagram should be familiar to you:

Mvc to redux: MVC worflow

The user action triggers a call to a controller, who updates the model and refreshes the view.

THE PROBLEM: NON-DETERMINISTIC UI

This works well when you have few controllers and views, but it gets really messy as the application’s complexity increases. The complete model is exposed through several controllers, so you will need to orchestrate calls from one controller to another, making it really hard to tell where a certain change came from or which is the complete state of the application at a specific point.

The fact that views make asynchronous calls to this controllers will add an extra difficulty to your confused and ephemeral life and then you will be ready to love Redux:

Mvc to redux: Redux worflow

 

REDUX TO THE RESCUCE

In Redux, the state is an object that contains the whole model of your application, like a big tree with all your application’s data. This object has no setters, as you cannot modify the state directly. Did you see where state sits in the diagram? It can only be accessed by the Reducers.

Instead of setting properties in the state, each component can dispatch actions to the store and those actions will be translated into state changes.

The actions are plain javascript objects also, describing the intention of modifying the state, like:

{ "UPDATE_COMPANY", company: newCompanyData } 

The reducers are a set of chained functions that take this action and the current state and return a new complete state tree.

reducer(oldState, // { user: user, company: null}
  action);        // { "UPDATE_COMPANY", company: newCompanyData } 

//returns new object { user: user, company: newCompanyData }

Once the reducers have been executed, the Redux store saves this object as state, and every component listening to the store changes will now be updated.

Like in the CQRS pattern, the model used to update information(dispatch an action) is different than the model used to read it (subscribe to store changes).

ADVANTAGES:

-As you are holding the state in a single object, you can recreate the state easily and the application becomes much easier to test.
-As the reducers are pure functions (they always return the same output for a given input), you can undo and time-travel the states, which helps a lot with debugging.

 

More on…

Redux basics: https://redux.js.org/basics/actions

Event sourcing: http://microservices.io/patterns/data/event-sourcing.html

CQRS: https://martinfowler.com/bliki/CQRS.html

Unidirectional UI: https://staltz.com/unidirectional-user-interface-architectures.html

Thinking in Redux: https://hackernoon.com/thinking-in-redux-when-all-youve-known-is-mvc-c78a74d35133

Thoughts on modular CSS

Thoughts on modular CSS

There was a time when I always asked myself which level of specificity should I reach when writing my CSS code. It is so easy to nest selectors without touching the HTML markup, write top level selectors for things like ‘h2’ or ‘a’… And end up rewriting rules, re-rewriting, un-writing the rewritten…

The problem with CSS is that multiple rules can be applied to the same element. This is a problem because developers tend to write generic rules and because some of the CSS properties are inherited till the infinity and beyond. I learned from OOP (Java) that you have to use inheritance when the object that is inheriting the properties is-a parent object. This is CSS, so forget those semantical nuances; if your parent has ‘Lato’ font, you have ‘Lato’ font. I do not mind if your parent is a Cat and you are a Ford Cortina.

In most of the situations, it is a good idea to:

  • Scope or namespace your selectors to reduce the specifity (BEM)
  • Bind your styles to classes and not to HTML tags, to avoid polluting the tags in all your application with styles that are tied only to a specific component (Opt-in Typography)

BEM (block__element–modifier)

This naming convention will help you to set a very low level specificity in your selectors while communicating the HTML structure of your components by simply looking at the CSS.

<!-- CLASSIC STYLING -->

<section class="avatar">

<img src="avatar.jpg">

<span>KoolUsername99</span>

</section>



<style>

.avatar { } /* Specificity of 10 */

.avatar img { } /* Specificity of 11 */

.avatar span { } /* Specificity of 11 */

</style>

This is good… to an extent. As the SaSS documents say “Be aware that overly nested rules will result in over-qualified CSS that could prove hard to maintain and is generally considered bad practice“.

In modular applications, this works better:

<!-- BEM STYLING -->

<section class="avatar">

<img class="avatar__img" src="avatar .jpg">

<span class="avatar__span">KoolUsername99</span>

</section>



<style>

.avatar { } /* Specificity of 10 */

.avatar __img { } /* Specificity of 10 */

.avatar __span { } /* Specificity of 10 */

</style>

Looks verbose, but ends up being much more maintainable and clearer.

Opt-in Typography

This is a simple idea took from a Chris Eppstein (core team of SaSS) talk. Instead setting global styles for typographic elements like h1, he proposes to apply those styles as a class (.h1 or .title) to avoid tying presentation to the base tags.

Scrum: Survival guide for devs

Scrum: Survival guide for devs

Working as a dev in Scrum can be really hard, let’s face it. With constant deliveries and no time for tech improvements, it is easy to feel like in crazy race to nowhere. These are the facts that I found myself most annoying, and how I try to deal with them.

#1 Management not involved

Very hard one. If management is not involved, you will not be doing really Scrum. And sell Scrum to management is impossible it you do not support it with metrics or very un-questionable success stories. I have read stories about changing processes without stating that you are going on an Agile direction, and when the changes are made, reveal the intention behind. I think is not the normal thing: if mangament does not want to hear about Agile, probably is beacuse it is the type of management that does not allow teams to change their processes easily. But if you feel you can makes changes, but your company is just against Scrum/agile thingie, maybe it makes sense to try this approach.

 #2 Pressure -all the time

Delivering tested features in 15-days cycles is exhausting, and if there are hard deadlines, dealing with management while delivering can put devs under a lot of pressure. You have to estimate carefully to avoid throwing yourself to the lions, and to get used to renegotiate the scope of the stories with the PO. If you came across some undefined behavior, do your best to create a follow-up story for that use case and concentrate on the originally defined scope. If you end with some extra hours at the end of the sprint, you can pick another story (or read a blog post, maybe ^^). QAs are your friends. Involve them in the discussions with the PO, to keep them aware of all the story details and avoid any misunderstandings that can delay the acceptance phase.

#3 Micrometrics & violent transparency

You will be analyzed at the end of each sprint (or even more often) and compared to your teammates and to the rest of Scrum teams. It is ok. Burndowns are more visual than the percentages we gave in the old times, but it is the same. Just try to raise your problems/blockers early (in the daily or even before if it is critical). If you think that you are regularly performing poorly, talk with the Scrum Master. He or she probably has clearer view of the big picture and can give you some useful insights.

#4 The long-term goal is missing

With the backlog changing all the time and the pressure to always keep your eyes on the next tiny story to deliver, it can be hard to see the big picture or the long term goals of the project. Get involved in the plannings and retrospectives and ask the PO to provide and update a roadmap. When possible, do attend the demos that include stakeholders or final users, or at least try to get feedback from the assistants.

#5 No career plan / no expertise recognition

Scrum does not have roles. Everyone in a Scrum Team is just that: a Scrum Team member. In addition to this, you have to give reports each day, which, apart from killing creativity, feels a little bit like being constantly observed. And this usually happens only in the early stages of a developer career, although usually you never put a team of juniors to work in Scrum. This “junior feeling” usually depends on how the Scrum Master filters the pressure and how much ownership of the increment implementation he gives to the team. Try to win the leadership of the areas that you master: take the opportunities of giving guidance to the rest of the team in those areas to become a reference.

#6 – Technical debt

It is really frustrating to see technical debt grow as the sprints pass, and this can be a hard one to fight for if management or PO really do not understand/care about the impact of poor code quality. If the team and the PO can reach an agreement of a discrete amount of story points that are destined each sprint to code improvements, that would be great. These story points can be assigned to each developer, leaving into his hands the refactoring of the code that he is delivering, or you can assign the whole amount to an experience dev and let him refactor and re-test complex component or implement some transversal improvements. Also, it is very important to maintain a good level of Unit testing coverage and to add a static code analysis as part of the integration build.

 

***

Waterfall is broken. I really like Scrum and I think some of the ideas of the Scrum Guide are very useful, but I think we can do better and with less hypocrisy.

 

Backbone + React

Backbone + React

Some time ago a teammate and I implemented some POC with Backbone and React and from the beginning I thought it would be interesting to combine these two frameworks, as Backbone only provides a lightweight base for scaffolding the app and React seems a very powerful library to build the UI. But the first implementation I tried made use of JSX, from React Tools, which has been deprecated in favor of Babel (Facebook’s React Blog).

This post documents my second attempt of integrating Backbone with React in a web application that uses RequireJS to define modules and Grunt to preprocess the JSX files and wrap everything up.

Backbone + React example I

You can download the full source code of this example at Github.

Backbone + React example I

 

This is the folder structure. The “src” folder contains all the source files, that will be proccessed by a Grunt build script, putting the resulting file structure inside “dist” folder.

 

 

 

 

 

Ok, let’s see the code…

  <body>
        <script data-main="js/main" src="../node_modules/requirejs/require.js"></script>
  </body>    
  • index.html: Will only load require.js and refers to main.js as our application’s entry point. All the HTML content of the different views of the app will be located in React components. We will compose these views with Backbone.
'use strict';
require.config({
    // shim: scripts that do not call define() to register a module
    shim: {
        underscore: {
            exports: '_'
        },
        backbone: {
            deps: [
                'underscore',
                'jquery'
            ],
            exports: 'Backbone'
        },
        backboneLocalstorage: {
            deps: ['backbone'],
            exports: 'Store'
        }
    },
    paths: {
        'jquery': '../../node_modules/jquery/dist/jquery',
        'underscore': '../../node_modules/underscore/underscore',
        'backbone': '../../node_modules/backbone/backbone',
        'text': '../../node_modules/requirejs-text/text',
        'react': '../../libs/react',
        'ReactDOM': '../../libs/react-dom'
    }
});

define([
    'backbone',
    'views/MainView'
], function(Backbone, MainView) {
    'use strict';
    return Backbone.Router.extend({
        init: function() {
            window.app = {};
            window.app.vent = _.extend(Backbone.Events);    
            new MainView();
        }            
    });
});
  • main.js: This file contains the RequireJS configuration. The shim field is used to configure dependencies for scripts that do not call define() to register a module. The paths field contains shortcuts to the different libraries that we will use. Backbone has underscore and jQuery as dependencies, so we are loading all of them, and React on its side is split into React and ReactDom.
define([
    'underscore',
    'backbone',
    'views/HeadView',
    'text!templates/main.html'
], function(_, Backbone, HeadView, mainTemplate) {
    'use strict';

    return Backbone.View.extend({
        el: 'body',
        template: _.template(mainTemplate),
        events: {},
        initialize: function() {
            this.render();
        },
        render: function() {
            this.$el.html(this.template({}));
            this.postRender();
        },
        postRender: function(){
            this.headRegion = this.$('#head-region');
            if (!this.headView) {
                this.headView = new HeadView();
            }
            var props  = {title: 'Header Title'};
            this.headView.render(this.headRegion, props);    
        }
    });
});
  • MainView.js: Is a Backbone View that will use a standard way of rendering HTML templates with underscore & text. With this configuration, we can use either React or underscore to render the HTML corresponding to a Backbone View. After MainView renders its contents, it will render the React component inside the header DOM element (#head-region), passing the title property to the component.

 

define([
    'backbone',
    'ReactDOM',
    'react',
    'components/HeadComponent'
], function(Backbone, ReactDOM, React, HeadComponent) {
    'use strict';

    return Backbone.View.extend({
        events: {},
        initialize: function() {},
        render: function(el, props) {
            //Create React Element based on HeadComponent.jsx
            this.reactElement = React.createElement(HeadComponent, {
                view: this,
                title: props.title
            });
            //Render element into DOM element passed from parent view
            ReactDOM.render(this.reactElement, el[0]);
        }

    });
});
  • HeadView.js: Here is when we start using React. The HeadView is a Backbone View that receives a DOM element as parameter in its render method. We will call React.createElement() passing to the call the JSX component and the title we received from MainView. Once the element has been created, we call ReactDOM.render() to actually insert the rendered contents into the DOM.

 

define([
    'react',
], function(React) {
    'use strict';
    return React.createClass({
    render : function() {
        return (
            <div>
            <span id="header-title">{this.props.title}</span>
            </div>
        );
    }
  });
});
  • HeaderComponent.jsx: It is a simple header that will take a string named “title” as parameter and render a span with the received string. The props field of a React element is populated with the properties passed to the React.createElement() call that is made to create that element.
module.exports = function(grunt) {

  require('load-grunt-tasks')(grunt);
  grunt.loadNpmTasks('grunt-execute');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-express');  

  grunt.initConfig({

    clean: ["dist"],

    babel: {
      options: {
        sourceMap: false,
        modules: "common"
      },
      dist: {
        files: [{
          expand: true,
          cwd: 'src',
          src: ['js/components/*.jsx'],
          dest: 'dist',
          ext: '.js'
        }]
      }
    },

    copy: {
      main: {
        files: [{
          expand: true,
          src: ['**/**', '!**/components/**'],
          dest: 'dist/',
          cwd: 'src',
          filter: 'isFile'
        }],
      },
      libs: {
        files: [{
          expand: true,
          src: ['libs/**'],
          dest: 'dist/'
        }],
      },
      node_modules: {
        files: [{
          expand: true,
          src: [
            'node_modules/requirejs/require.js',
            'node_modules/jquery/dist/jquery.js',
            'node_modules/underscore/underscore.js',
            'node_modules/requirejs-text/text.js',
            'node_modules/react/**',
            'node_modules/react-dom/dist/react-dom.js',
            'node_modules/backbone/backbone.js'
          ],
          dest: 'dist/'
        }],
      }
    },
    express: {
      all: {
        options: {
          port: 3000,
          hostname: 'localhost',
          bases: ['./dist'],
          livereload: true
        }
      }
    },
    watch: {
      scripts: {
        files: ['src/**/*.js', '!src/js/components/**'],
        tasks: ['copy'],
        options: {
          spawn: false,
          livereload: true
        },
      },
    }

  });
  grunt.registerTask('server',['express','watch']);
  grunt.registerTask('default', ['clean', 'copy', 'babel', 'server']);

};
  • gruntfile.js: A simple Grunt script to copy all the source files to “dist” folder, process the JSX files with Babel and open a light node server.

 

Next steps I plan to take are to add some user interaction, handling the events with React and implement the Backend calls with Backbone Models. And Webpack maybe.

Still there? You are awesome <3