ProgramiCo
JavaScript Web Application Development
  • Home
  • SmartJs
    • Setting up the Environment
    • Running SmartJs
  • SmartJs Blog
  • About

JavaScript MVVM DI with AMD and Pub/Sub

9/30/2012

0 Comments

 
This post continues to answer "what is SmartJs".  In this article we look at the M and the A.  How does SmartJs demonstrate the MVVM pattern?  And what does AMD have to do with it? Read on to find out...

M is for MVVM

My favorite part of MVVM is the data binding.  Update a data structure, and the UI automatically changes.  That is like magic.  The benefits are tremendous.  A necessary part of MVVM is an event driven system.  When you think about it, MVVM is well suited to the job of rapid application design in a connected world.  But how to pull it off correctly?  Fortunately we have some some great libraries like Knockout and RequireJs to provide the abstractions we need.

Organic Design

I tend to think of software design from the GUI inward.  The UI can be quickly designed with prototyping tools like Codiqa.  I like that the prototype is easy to change in the design phase, but it isn't wasted effort.  The prototype becomes the starting point for the UI markup that can be bound with Knockout.  With a little practice, it becomes easy to extrapolate UI concepts into ViewModel data structures.   The system begins to design itself.  When the ViewModel is designed, we will have a clear sense of the upstream persistence and connectivity needs that need to be built into the underlying model.  In turn, the Server side development is very focused, delivering only the functionality needed, without wasted effort.

MVVM and MVC; Different tools for different jobs

When we talk about MVVM there is always the question of MVVM versus MVC.  My work in MVVM has been in Windows Client software which is event driven and relies on XAML to ViewModel binding.  Working with Knockout was an intuitive transition.  In a Single Page Application we are again able to present a real-time event-driven desktop-like experience to the user.  So for me, MVVM was a natural choice.

My personal experience with MVC has been in the context of the request/response paradigm.  When we evolved from Asp.Net postbacks to MVC I rejoiced.  .Net Postbacks are an artificial construct, while MVC felt more free and more like Cold Fusion Fusebox fuses, that I already knew about.  MVVM doesn't make much sense in a request/response flow.  But so doesn't MVC make sense to me for an event driven SPA.

RequireJs-> AMD-> DI-> MVVM-> Knockout-> UI

How do we combine these ingredients to concoct the architecture we need?  SmartJs uses RequireJs to implement Asynchronous Module Definition.  We get modules that have RequireJs injecting the Dependencies for us.  Each module is isolated, it knows only of its own dependencies.  Indeed it has its own namespace, so artificial container constructs like "self" become unnecessary.  The need to be composed with specific other implementations disappears, which allows us to write stub dependencies to facilitate unit testing.  There is no overriding controlling global authority available to the app.  And why should there be?  The ViewModel exists to serve the event driven application.  With a proper system of Publication and Subscription, events will propagate throughout the system and cause the appropriate changes.

So our AMD modules have their Dependencies Injected with RequireJs's define.  The ViewModel modules will be injected with a Knockout reference so that they can invoke the observableArray, computed, and other Knockout goodies.  We take the output from Codiqa and add some straightforward Knockout binding tag attributes, add in a rich system of published and subscribed events, and the application comes to life with behavior of its own.  And here we have the MVVM pattern.

Events happen; Pub and Sub

Most SmartJs modules are injected with a Pubsub reference that they can use to Subscribe to events that interest them.  The Pubsub module also provides a simple publish() method that will send out events to the local client only.  The Server module provides a publishGroupEvent() method that publishes virtually to all clients connected to the same nowjs group.

In an interactive SPA, events will be initiated by the UI, and that is a perfect application of Knockout's computed.  In the setter (write) of the computed, we implement a wrapper pattern around an observeable backer property.  But additionally we can run any application logic we want which generally is going to lead to a Publish of some sort.  The perfect example is in the flow that takes place when a user starts typing in the chat room.

Where'd the model go?

It's all too easy in JavaScript to just return a data structure from a method.  In a properly designed and maintainable system we must organize the model declarations so that they can easily be found and referenced.  When I wrote SmartJs I found myself asking, now what is the exact name of this model's column again?  And I would have to look everywhere in the code to find where it had been instantiated, often as a difficult-to-find anonymous type in a ViewModel.

So to save the hassle and headache, the Schema module was born.  And a lot of familiar concepts like Validation seem to belong there.  Having a clear sense of the data model in a JavaScript application is the exception rather than the rule.  But SmartJs attempts to give derivative works a place to build and maintain a data model that is easy to reference and therefore, should be hard to mess up :)
0 Comments

S is for SOLID

9/26/2012

0 Comments

 
The year is 2012 and we have acronyms of acronyms of acronyms.  The word SmartJs is itself an acronym, the first letter of which is the first word of an acronym, which is itself composed of acronyms.  

This post aims to discuss SOLID principles and, in particular, demonstrate their usage in the SmartJs framework.

Background of SOLID

Please take a look here for some background on SOLID principles.  It is rather heavy reading so Wikipedia's article may be easier to digest.  We have been studying SOLID at our work and it has had a profound influence on my ability to formalize how I think about software development.

S = SRP; Single Responsibility Principle

SmartJs contains many examples of The Single Responsibility Principle.  Most obviously, AMD provides a language construct that encourages modular software design.  Each module of SmartJs is designed to do one thing only.  Indeed, during the organic construction of SmartJs, several modules were born when the code in a parent module began to do more than one thing.

But more than the modules themselves, the SRP was built right into the functionality at a fundamental level.  The most clear example of this is the interface to the Server module.  Although the interface exposes public methods that provide data persistence services, the function calls to Server are designed to begin the process only, and report back success or failure.  They never return a model representing the result of persistence, that is consumed by the caller.  In cases where a model is the result of a persistence operation, that model data always follows as a separately published application event.

The design and enforcement of rules like this took awhile to evolve.  By adhering to SRP, this design pattern doesn't seem difficult to work with, but rather a joyful reminder that SRP can be very helpful when correctly applied.  The application components must always remember that, for example in a list operation, the command to list will not be immediately followed by a list of results.  It is only a command to start the process, and a separate e.g. topic.list event will be present in the system a short time later with the contents of the requested data.  This allows an opportunity for all the components of the  application to respond equally and independently to the presence of new data and events in the ecosystem.

O = OCP; Open Closed Principle 

The Open Closed Principle can be hard to pull off, especially in a project that is evolving quickly.  It can be hard to have the foresight to know where OCP will eventually be needed.  Sometimes a switch statement is a good place to look for a place to implement OCP.

I think JavaScript makes OCP a lot easier than C# because there is never a type conversion that needs to be done.  Any object and any number of parameters can be passed to a function in any order, so Extensibility is rather built in.  It can be a fine line to walk.

The best example of OCP I can think of in SmartJs is the conduit from the client to the server.  It is boiled down to one function to call from client to server, and one function to call from server to client.  Everything goes through this narrow pipe, and the pipe itself does not require any maintenance when new functionality is added to the application.

Two modules use the Server functionality, dataContext and groupContext.  These wrap the Server in convenient methods, extending the Server's usability without requiring modification.  These two demonstrate OCP and ISP well, since new functionality could be added to the system without ever needing to change server.js.  The data conduit is truly open for extension, and closed for modification, making it a breeze to add interesting new realtime functionality.

L = LSP; Liskov Substitution Principle 

SmartJs demonstrates LSP when it passes around a Knockout observeableArray as if it was an array, to the Validation module.   Validation pushes errorMessages onto it as if was an array, never knowing or caring that the array is bound to the UI.

I = ISP; Interface Segregation Principle

Similar to SRP, modules in SmartJs are designed to do one thing.  They return only the minimum necessary interface that other modules will need.

When a model in the system needs to be used for two different purposes, SmartJs will use two different ViewModels, each with their own UI binding and public interface.  This prevents having a catch all interface that is cluttered and violates SRP.

DataContext and groupContext modules also provide segregation of the Server interface.  Their interfaces are specific to data and group kinds of functionality respectively.  New group functionality could be added to the groupContext without needing to change the server's interface.  This results in a system that is less brittle overall.

D = DIP; Dependency Inversion Principle

The best for last.  I really think this is my favorite.  It is the reason that AMD is so wonderful.  It is what separates MVVM from MVC.

AMD allows modules to have dependencies fed to them at run time.  There is no composition root.  There is no Controller to call for help.  There is only the View and the ViewModel, their binding, and events in the system which encourage things to happen.  When model properties are changed, the user interface automatically udpates through binding.

Modules never have to know or care how their dependencies are fulfilled.  They call an interface and have an expected result.  Therefore, DI makes it easy to perform Unit Testing, by allowing the building of stub objects that fulfill the dependency interfaces without doing any real work.

I have a good deal of background working in MVVM in XAML/WPF for Windows app development.  One thing that makes this pattern possible in that world, is Unity Controller.  MVVM without a DI container is a lost cause.  MVVM with a DI container is a pure pleasure to develop.

Therefore, implementing MVVM in JavaScript is correctly done using AMD and RequireJs provides this ability flawlessly.

Next post...M is for MVVM 
0 Comments

    About the Author

    Picture
    Hugh Anderson is a web frontend developer in Tennessee who loves JavaScript and C#. 

    View my profile on LinkedIn

    Archives

    August 2015
    January 2013
    December 2012
    November 2012
    October 2012
    September 2012

    RSS Feed

Powered by Create your own unique website with customizable templates.