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.
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.
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.
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 :)
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 :)