Monday, June 30, 2014

This is a cross-post from the Rally Engineering Blog.

Rally publishes a public javascript AppSDK to give customers the ability to easily access their user story data within custom applications. In order to make the SDK components more reusable in different contexts and provide easier application development, there must be a clear separation between view code and model code within the SDK.

ExtJs with MVC

First off, "MVC" in this post refers to unopinionated, generic MVC. View == UI, Model == application logic, Controller == glue between View and Model. "Component" refers to a class that extends Ext.Component.

There are two popular ways to implement MVC with ExtJs applications. Sencha provides an MVC implementation distributed with ExtJs and DeftJs is a third-party library. I have experimented with both of these MVC implementations, and found them lacking.

Sencha's built-in MVC implementation requires a specific directory structure and configuration with Ext.application. These restrictions make it difficult to adapt the pattern to existing code bases.

Sencha's controllers also encourage code that listens for events fired from a Container's child Components. This is a code smell. Controller code should never "know" about child Components, because refactorring the UI structure will break the controller. Replacing a text input with a slider shouldn't force you to change controller code.

DeftJs is easier to adapt to existing code, but there are some odd object lifecycle issues that make it difficult to work with. Components must mix in Deft's Controllable class and DeftJs controllers must be configured when a Component is defined, rather than when it is instantiated. If you find the need to re-use a Component with two different controllers, you will need to create two separate classes, each defined with a different DeftJS controller.

A Deft controller's init method is not called until after the Component has been rendered, which makes things rather challenging if the controller needs to hook into any pre-render events such as staterestore or render.

Plugins as Controllers

I've found that standard Ext Plugins are a great alternative to Sencha and DeftJs controllers. Plugins fit nicely into the Component life cycle. They can be configured at instantiation time, so reusing the same UI with different behavior is trivial.

Multiple Plugins can be configured for a single Component. This may seem like an odd property for a controller, but it's actually quite nice to split code into multiple controllers for Components that have many different behaviors.

A Plugin's init method is called during the Component's constructor call, so it can respond to any Component events fired during or after the Component's initComponent call. A Plugin's destroy method is called during the Component's destroy call, which allows for easy cleanup of listeners and models orchestrated by the Plugin.

So how does it Work?

Wire up controller Plugins just like any other Plugin.

    /**
     * Controller Plugin
     */
    Ext.define('MyViewController', {
        extend: 'Ext.AbstractPlugin',
        alias: 'plugin.myviewcontroller',

        /**
         * @cfg {Ext.data.Store}
         */
        store: null,

        init: function(cmp) {
            // add listeners to respond to UI events
            cmp.on('save', this.onSave);
        },

        onSave: function(cmp, data) {
            // respond to UI events by calling public view and model methods
            cmp.setLoading(true);
            this.store.add(new this.store.model(data))
            this.store.sync({
                success: function() {
                    cmp.setLoading(false);
                    cmp.showNotification('Record Saved');
                }
            });
        }   
    });
    /**
     * View Component
     */
    Ext.define('MyView', {
        extend: 'Ext.Component',
        alias: 'widget.myview',

        items: [{
            xtype: 'button',
            label: 'Save'
        }],

        initComponent: function() {
            this.callParent(arguments);

            this.addEvents(['save']);

            // button click is abstracted into semantic event to avoid
            // controller having to know UI implementation details
            this.down('button').on('click', function() {
                this.fireEvent('save', {...});
            });
        },

        showNotification: ...
    });
    // instantiate view with controller configuration
    var cmp = container.add('myview', {
        plugins: [{
            ptype: 'myviewcontroller',
            store: myStore
        }]
    });

Components architected with a plugin controller like the example above become easier to maintain and easier to consume. This method of adding controllers to components is relatively painless to adapt to existing code. We are actively refactoring legacy code within Rally's SDK to use this architecture.

4 comments:

  1. Paykasa, günümüzün gelişmiş teknolojisinin meydana getirdiği bir ödeme şeklidir. Sizlerde bu platformdan alışverişlerinizi güvenli bir şekilde gerçekleştirmek için kullanışlı bir paykasa kart seçebilirsiniz. Online olarak hızlı Paykasa Fiyatları Paykasa kart ve bu sistem online alışveriş siteleri, oyun siteleri ve daha birçok alanda kullanılırken müşterinin aklında hiçbir soru işareti olmaması için tasarlanmış bir ürün. Piyasadaki diğer kartlar gibi standart 3-5 tane kod değil tüm ara kodları bulmak mümkün. Bu sayede güvenlik hat safada sağlanmaktadır. Bu uygulamanın temel amacı kredi kartı kullanmak için güvenilir bulmadığınız mecralarda kolaylıkla alışveriş yapabilmeniz ve oyun oynayabilmenizdir. Alışveriş yapacağımız site her ne kadar güvenilir olsa da ödeme seçeneğinde tereddütten kurtulmamız biraz zor olmaktadır. Alışverişlerinizi Paykasa ile Hızlı Ve Kolay Yapabilirsiniz. Vermiş olduğumuz kart limitlerinden bir tanesini belirledikten sonra iletişime geçerek müşteri temsilcisine satın alınacak paykasa kartın söylenmesi gereklidir. Kayıtsız 2 dakika da paykasa al seçeneği ile sizlere sunulan kart sayesinde istediğiniz miktarda alım yapabilme şansına sahipsiniz. Ülkemizde kısa süre içinde çok fazla yaygınlaşan ve herkesin alışveriş konusunda tercih ettiği ödeme kart tabi ki yeni olduğundan dolayı fiyatlarında değişikliklerin olması da gayet doğal ve sıradan bir iş haline geliyor. Taklit edilemez ve kopyalanamaz. Paykasa kartı yaklaşık bir dakikada satın alabilirsiniz. Sitemiz, güvenlik önlemleri ve alışveriş seçeneklerinde olması gereken tüm özelliklere sahip iken sunduğu fiyatlarla da müşterilerinin ihtiyaçlarını güven içinde karşılamalarına yardımcı olmaya devam etmektedir. Pek çok firma olmasına rağmen bu firmalardan sadece 4-5 tanesi işini doğru yapmaktadırlar. Güvenilirliğini de bu sayede %100 oranında müşterilerine sunmuş oluyor.

    ReplyDelete