Guest Blog Post
Deft JS is a community-driven library of useful building blocks that enable teams to rapidly develop large-scale applications using Sencha Ext JS. The primary goals of Deft JS are to promote modularity, reusability and testability. Deft JS is a library, not a framework; a subtle distinction. As an extension library, it provides features that can be used piecemeal but become more powerful when they are combined.
Deft JS collects ideas drawn from a wide range of platforms. It fosters cross-pollination of the best ideas in front-end architecture, exposed through APIs that follow familiar syntax conventions and feel like natural extensions of Sencha frameworks. Deft JS is not intended to compete with Sencha frameworks, but rather to demonstrate complementary solutions.
As an open source project since 2012, Deft JS incorporates feedback from the developer community and delivers complementary solutions to the Ext JS framework. The Sencha community has collaboratively contributed to Deft JS, based on lessons learned on the front lines of large-scale application development.
Ext JS 5 demonstrates that this feedback loop is working. With this release, Sencha has introduced foundational improvements that address many of the needs that originally inspired third party libraries like Deft JS and GluJS.
The Deft JS team is excited about the new possibilities offered by Ext JS 5. So, let’s start with some of the features offered by Deft JS. From there, we’ll discuss our experience migrating our library to Ext JS 5, and what to expect from the next version of Deft JS — called Deft JS 5.
Core Deft JS Features
The key features currently provided by Deft JS for Ext JS 4.x and Sencha Touch 2.x are:
Inversion of Control (IoC) Container
IoC and IoC containers are widely used in the Java, .NET and ActionScript communities, mainly via frameworks like Spring. The power of IoC is that it “inverts” the flow of control. When an object needs to use another object, instead of creating it or reaching out to grab it from somewhere else, the necessary object is automatically provided by the IoC container. This provides a huge amount of flexibility and improved testability, because determining which object to provide is done externally.
Deft JS coordinates dynamic assembly of your application from loosely coupled reusable components, fulfilling object interdependencies via its configurable IoC container.
The Deft JS IoC container:
- Provides class annotation-driven dependency injection
- Maps dependencies by user-defined identifiers
- Resolves dependencies by class instance, factory function or value
- Supports singleton and prototype resolution of class instance and factory function dependencies
- Offers eager and lazy instantiation of dependencies
- Injects dependencies into Ext JS class configs and properties before the class constructor is executed
MVC with View Controllers
View controllers are a widely used component common to many implementations of the Model View Controller (MVC) architectural pattern.
These lightweight controllers are responsible for managing the state of a specific view instance and its child components. They listen for events dispatched by the view and its child components in response to user gestures, and delegate work to injected business objects and services.
Deft JS introduced view controllers for use in Ext JS 4 and Sencha Touch 2 applications.
Deft JS view controllers:
- Provide class annotation-driven association between a given view and its view controller
- Clarify the role of the controller – i.e. controlling a view and delegating work to injected business services (service classes, Stores, etc.)
- Support multiple independent instances of a given view, each with their own view controller instance
- Reduce memory usage by automatically creating and destroying view controllers in tandem with their associated views
- Support concise configuration for referencing view components and registering event listeners with view controller methods
- Integrate with the view destruction lifecycle to allow the view controller to potentially cancel removal and destruction
- Simplify clean up by automatically removing view and view component references and event listeners
Promises and Deferreds
Deft JS Promises:
- Provide an elegant way to represent a “future value” resulting from an asynchronous operation
- Offer a consistent, readable API for registering success, failure, cancellation or progress callbacks
- Allow chaining of transformation and processing of future values.
- Simplify processing of a set of future values via utility functions including all(), any(), map() and reduce().
- Are fully compliant with the CommonJS Promises/A and Promises/A+ specifications.
The Road to Deft JS 5
With the release of Ext JS 5, our team sat down to think about what this new version means for Deft JS. It has never been our goal to “lock people in” to using Deft JS. If features we’ve previously provided become unnecessary because they become part of the Sencha framework, everyone wins. Sencha will always have the ability to solve problems at a deeper level than we can reasonably supplement them from the outside.
For example, Sencha has added its own implementation of view controllers to Ext JS 5, partly due to the usefulness of the Deft JS feature that complemented previous versions of the framework. Their implementation includes deep changes to the standard Ext JS components to add support for two-way data binding with View Models.
As the Sencha frameworks evolve, Deft JS will as well, and it will shed old features as new releases of the Sencha framework make them unnecessary. That just leaves more time for new features to address new opportunities that emerge as we all reach higher.
“Ext JS 5 demonstrates that this feedback loop is working. With this release, Sencha has introduced foundational improvements that address many of the needs that originally inspired third party libraries like Deft JS and GluJS”
Upgrading Deft JS to work with Ext JS 5 was fairly straightforward. We obviously had to upgrade our Sencha Cmd version to the 5.0 beta. However, since Deft JS is really an MVC extension, and we don’t extend many Sencha classes, most of the changes in Ext JS 5 don’t directly affect Deft JS. The IoC container and Promise API carried over with minimal changes.
Ext JS 5 introduces a common core package of classes that is shared between Ext JS and future releases of Sencha Touch. The core package covers the class system, DOM, event handling and data among other things. In previous releases, the class system was similar between the two frameworks but with enough differences to necessitate an abstraction layer in Deft JS. The common core has made code reuse between the Sencha frameworks far easier and has enabled us to remove our abstraction layer in Deft JS 5.
Deft JS 5 makes use of the new Ext.Mixin base class for hooking into the class lifecycle to implement features such as the IoC container. Previously, class pre-processor hooks were used, but these have been deprecated because they are incompatible with the recently added Sencha Cmd full class system optimizer (configured via the build.optimize property and enabled by default for production builds). Ext.Mixin provides a powerful and well supported way of hooking into the class lifecycle from mixed-in classes.
The one area that did take a bit of thought was our view controller implementation. Because Sencha adopted view controllers in Ext JS 5, we had to consider what to do with the existing Deft JS implementation.
We ended up choosing to keep Deft.mvc.ViewController, but it now extends the Sencha Ext.app.ViewController. This allows us to leverage what Sencha has added, while still leaving room for us to include a bit of additional functionality:
- The Observe and Injectable mixins are automatically applied to your view controllers.
- A view controller can cancel view destruction by overriding the destroy() method. This can be useful in some situations, such as displaying a message such as “You have pending changes, are you sure you want to close this tab?”
- We may also add some extra features such as enhanced routing support, “companion” view controllers (to attach cross-cutting behavior), or utility methods for working with service methods which return a Promise. Obviously, we’re still brainstorming ideas in these areas.
Upgrading Apps to Deft JS 5
When upgrading an existing application to the new versions of Ext JS and Deft JS, many things will carry over with minimal changes:
- You will still use Deft.Injector.configure() to configure the IoC container, using the same syntax to define dependency providers, value mappings and factory functions.
- The inject and control annotations are still used.
- Observing events fired from injected objects is still possible using the observe annotation.
- The Promise API is still present.
The main changes will occur in view controllers. Sencha has implemented their own view controllers, and these work somewhat differently than the current Deft JS view controllers.
The most significant change relates to how view controllers interact with views. The Sencha control configuration is more limited than what Deft provided in the past:
- Selectors are not automatically set up using the id or itemId of the target view component.
- Getters and setters for view component references are not created from the control config. A separate refs config is used for this.
- Sencha is advocating that developers forego the use of control, and instead define event handler names on the view components themselves. The handler functions are located using the new referenceHolder features. These will typically be functions defined on a view controller. On the plus side, it means we’ll have to deal with component query selectors much less frequently.
- Sencha also is advocating that developers forego the use of refs, and instead use getReference() in a view controller to obtain references to view components.
As you can see, it doesn’t really make sense for us to push forward with our control implementation. We recommend that existing Deft JS developers go ahead and adopt the new approach, using references and view-defined listener names.
The other major change is mainly an internal one: mixins are now used instead of class preprocessors. For developers, this means that classes will need to apply the Deft.Injectable mixin when using the inject annotation. This is being done to better support projects built with Sencha Cmd, because as of now Cmd doesn’t recognize custom preprocessors in its define-rewrite optimizer.
The Deft JS team is excited about the new possibilities offered by Ext JS 5. With the introduction of MVVM, ViewControllers and Bindings in this release, Sencha has responded to much of the feedback and architectural concerns raised by its developer community. We’re also impressed with the open and collaborative stance Sencha has adopted when interacting with open source community projects like Deft JS and GluJS.
The Deft JS IoC and Promise upgrades were completed thanks to sponsorship by Joukou Ltd and Superstruct Ltd, while Brian Kotek took on the challenges associated with porting the ViewControllers. John Yanarella also supported the work across the board, as always. Thanks to all the companies, people and Sencha for being involved in getting a Deft JS 5 release ready!
The Deft JS library is evolving along with the Sencha platform, as we always knew it would. Old challenges shift or fade, and new challenges arise. We’ll keep pressing on, looking for new ways to make application development with the Sencha platform even faster, simpler, more testable and reusable. We hope you’ll consider joining us for the ride.