15

Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed
Page 2: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

QuantwmQuantum MVVM

Xavier LASNE

This book is for sale at http://leanpub.com/quantummvvm

This version was published on 2016-06-04

This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishingprocess. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools andmany iterations to get reader feedback, pivot until you have the right book and build traction onceyou do.

© 2016 Xavier LASNE

Page 3: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

Thanks to my wife Catherine, the sunshine of my life, and to my children.

Thanks to Cocoaheads Paris, which allowed me to share my work, discuss with my peers andencourage me to improve my framework.

Thanks to Apple for the Swift language, which advanced my programming capabilities to the nextlevel.

Page 4: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

Contents

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i

1. MVVM: The nice part and the missing part . . . . . . . . . . . . . . . . . . . . . . . . 1

2. Solution Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

Page 5: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

IntroductionSoftware Engineering is a mix of art of science. The purpose of this book is to push this border alittle more from art to science, by defining a clear architecture pattern for UI, and by extension, tothe management of the main thread of the application.

This book assumes that the reader has a good knowledge of programming, and has already madeone or two simple applications preferably in Swift, in order to grasp the basic concepts and be ableto follow the code samples. The goal is here to explain how to build your next complex applicationusing a strong, well-defined architecture: event-driven, data-centric, with layer isolation.

A simple application usually just works, whatever the chosen architecture, because the interactionbetween components is naturally low, the mapping between the data model and the user interfaceis trivial, and the number of user scenarios is low.

When dealing with complex applications, where a large number of components are interactingand sharing data, with background network or file system operations, simple architecture schemeswhich were satisfactory for basic applications are not valid, because they cannot cope with thisexponential complexity. And the mere theoretical knowledge of what should be done is notsufficient: programmer need a strong, well defined rules for each data, interaction and components.

Experienced programmers know how to cope with this complexity, by reducing to the extreme limitthe interactions between components, by assigning a specific role to each class, and by defining aunidirectional data flow.

My goal here is to present a set of software architecture rules and concepts based on the goodpractices and ideas which are emerging from many different places, and to combine them into acomprehensive architecture allowing to build solid applications from the beginning.

I have presented in April 2016 at Cocoaheads Paris the main lines of the architecture of my OSXin-progress application, which is a complex hybrid between a spreadsheet, a database and a browser.I received a great support from present people, which were very interested into this presentation,because it was an application level architecture trying to make things simpler, without requiring aframework. Nicolas Bouilleaud challenged me to make it more dynamic, and I started to develop theQuantwm framework, which I will present in this book.

I named the Quantum MVVM Framework “Quantwm” (pronounced Quantum) in order to avoidany trademark or copyright issues, and simplify future web searches on internet.

I decided to pause my application development and to write this book and to share this workwith the community in order to speed-up the adoption of these good practices, and accelerate thedevelopment of this framework.

The framework is at: Github:Quantwm¹

¹https://github.com/xlasne/Quantwm

i

Page 6: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

1. MVVM: The nice part and themissing part

The MVVM architecture pattern is a User Interface pattern. Its goal is to model how user interfaceviews are managed and connected to the Data Model.

In this chapter, we will present this pattern and details its strengths, and then list the issues usuallyfaced when applied to a complex application.

The MVVM (Model - View - View Model) architecture is an extension of the MVC (Model-View-Controller) architecture, which splits the software responsibility between 4 layers / components:

Views + View Controller - View Model - Model

The Views are graphical objects which are displayed on the User Interface, and allow interactionwith the User.

The View Controller owns the Views, owns the View Models, and connect them together. In theM-V-VM, the V stands for both the View Controller and its Views.

TheModel or Data Repository manages the persistent data of the application.

The role of each View Model is to convert a set of raw data from theModel into a processed, readyto be used by the Views content data.

The nice part

Let’s now details strengths of this architecture.

Layer Isolation

MVVM enforces isolation between 4 layers:

1

Page 7: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

MVVM: The nice part and the missing part 2

1. Views Layer2. View Controller Layer3. View Model Layer4. Data Repository Layer

This means for example that View Controller does not communicate directly with the DataRepository, but only through the ViewModel which in turn communicates with the Data Repository.We will see later exactly which communications are allowed, and in which direction.

This is a good constraint, because it really helps to enforce a Single Responsibility Principle andto reuse the code. At the end of this book, we will have added additional responsibilities to ViewModels which will make this constraint even more attractive.

Single Responsibility Principle

Each layer has a defined role:

• Views:– Display data content– Display presentation– Notify View Controller of a user input

• View Controller:– Manage its child view controller hierarchy– Create and Manage its View hierarchy– Create and owns the View Models needed to populate its views– Register to the Data Repository in order to be notified on data update.– Connects the Views with their associated View Models

* On View input action, call the associated View Model input action* When Data Repository is updated, update its own Views from the View Model readcontent action.

• View Model:– On input action, perform Data Repository updates.– On read content action, retrieve Data Repository raw values and process them into viewcontent value.

• Data Repository:– Store and Archive the persistent raw data.

In this pattern, the View Controller is the master of the User Interface. He is coordinating the inputand output actions, and has a central role. Views and View Models are slaves, created and dismissedby the View Controller, and serving under its orders.

The Model is a central resource which is storing the data, and notifying its changes to the registeredView Controller.

Page 8: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

MVVM: The nice part and the missing part 3

Modifiability

Change Happens.

By using MVVM, the View / View Model pairing allows to reuse your View Models in severalposition in your application.

MVVM: What is missing?

Building an application using the architecture pattern above is a good start, and for simpleapplications, will be enough. But for complex applications, this is an other story.

A complex application has the following additional constraints versus a simple application:

Complex View Hierarchy

A complex View hierarchy translates either into:

• a complex view controller hierarchy and the problem of sharing and synchronise contextualdata between them or

• a massive and complex view controller.

In both cases, complex communication issues occurs between these view controllers, withoutforgetting the additional need to archive/restore this hierarchy when needed to provide a nice userexperience.

UI Refresh depends of a set of data

If a displayed component is the result of the processing of a set of raw values, then it shall not beprocessed each time one of these element is changing, but only once all the values are changed.

The processing of the Model data, or the refreshing of it, can take a significant amount of processingpower, and shall be limited to the case where data has effectively changed.

In the worst case, recomputing the whole UI each time one on the original value has changed mayhave significant processing / UI impact.

Exponential increase of scenario and transitions

As the number of transitions and the complexity increase, the number of scenarios explodeexponentially. To manage this complexity, it is utterly vital to reduce this complexity by limitingthe communications between components, and to ultimately reduce it to the view hierarchyconfiguration and the update of views from the data model. This strategy has a good code coverageand tends to resolve into: if it can display correctly all the possible cases, then it works.

Page 9: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

MVVM: The nice part and the missing part 4

Practical issues

Let’s list the practical issues which are raised with MVVMwhen dealing with a complex application(or even with simple ones), and appreciate how asking the right question is more than half-way tosolve it:

Shared Context Data:

A context data is a variable which is not stored persistently in a file, but describe a display orcontextual state of the application, like which tab is selected or which view has the focus. A local(= non-shared) context variable shall be owned by its view controller, but which component shouldown a shared context data? Storing them in the common ancestor view controller creates stronginter-view controller dependencies which prevent easy refactoring and change of view controllerhierarchy, which is bad for modifiability, and is violating the simple responsibility principle becausethese variables are not related to the role of this ancestor.

Coordinated Data Update:

When the content of a view depends on the processing of a set of raw data, and if several of thesedata are modified during the same event loop, this view content is updated several times. The datamodel is unaware of the association and usage made of these data by the View Model, and alerts theView Controller at each update. If the updates are performed inside the same event loop, this is justwasted processing time, but the situation is even worse if the notifications are not performed duringthe event loop (case of Reactive) because its triggers successive refresh and a flickering of the UserInterface and the need of an additional coordination of these updates.

Registration on non-yet existing data:

If a View Controller depends on a data which may be present or not, KVO is not helping becauseyou cannot register on an object which does not yet exist.

Communication with View Controllers:

The problem when communicating with a view controller, it is that they are not permanent. Bydesign, View Controllers are created and dismissed according to the UI layout needs. This is not anissue is there is only one active View Controller, but this creates a communication failure possibilitywhen communicating between child of a same ancestor, and even a parent communicating withhis child on an update will have to wait for the dismissed Child View Controller to disappearand the created Child View Controller to reach the ViewDidLoad or ViewWillAppear state beforecommunication is possible. A clear set of rules on which communication is allowed between ViewController is thus needed.

Page 10: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

MVVM: The nice part and the missing part 5

Data Repository Abstraction:

View Controller shall register to the data update, but it is the View Models who knows which datathey are reading from the Model. The View Controller should not be aware of these data modeldetails, but only of the content data. A good registration interface should abstract the model.

Update Synchronisation:

When a data is updated, notification are fired to all the registered entities. But sometime, you needto perform update sequentially in a defined order. What is the component in charge of ordering theupdate?

Refresh Loop:

The more complex the data flow, the more likely the creation of a refresh loop where data areupdated circularly in an infinite loop. A well defined, uni-directional data flow is the best way toavoid them.

Conclusion

The main reason why the previously described MVVM pattern needs improvement is that severalView Controllers shall coordinates their Views and share contextual variable.

The contextual variable are usually stored in the common view controller ancestor, who willhave to manage and coordinate the changes between its child view controllers. This coordinatedmanagement is itself redundant with the view controller restoration management.

MVVM is a User Interface level architecture pattern, and as such, does not address the complexityan Application Level architecture. Quantum MVVM propose an architecture level pattern whichintegrates MVVM for its User Interface part.

Page 11: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

2. Solution OverviewLet’s introduce in this chapter a high level description of Quantum MVVM, and detail in thefollowing chapters each concept.

Overview

First, let’s define the Data Repository as an abstraction which unifies under a common datamonitoring API:

• theDataModel persistent storage, which owns, archives and restore the persistent applicationor document data

• the Context Manager storage, which owns, archive and restore the contextual data sharedbetween the View Controllers. Contextual data local to a View Controller should be archivedand restored by this View Controller.

Each monitored data is identified by a Keypath composed of a root object and a chain of properties,similar to Key Value Coding. This keypath is defined statically, and does not requires the existenceof the root object.

In a simple application, a single View Controller is the central actor coordinating all the interactionsbetween User and Data Repository.

In a complex application, several View Controllers are interacting simultaneously, and create theneed of a central actor, the Repository Observer in charge of coordinating the interactions betweenthe different View Controllers and the Data Repository.

Quantum MVVM structures the interactions between the View Controllers (and their View Model)and the Data Repository in 2 categories:

• Update actions, which are updating the Data Repository and shall not refresh the UserInterface.

• Loading Actions, which are reading from the Data Repository and are refreshing the Views,but shall not update the triggering monitored data.

In order be notified, each View Controller shall register with the Repository Observer its RefreshAction based on a triggering set of keypath.

At the end of each event loop, after the last Update action, the Repository Observer will:

6

Page 12: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

Solution Overview 7

• Poll the Data Repository to detect updates performed• Depending on these updates, trigger the View Controllers Refresh Action which will refreshthe User Interface.

The old observing contract between the View Controller and the Model was “This data has changed.Me, Model, I do not care if you need other data to display your view. By the way, you may receiveor not other notifications soon about other data that your view also need before your view is evendisplayed. I let you decide how you manage this. You may decide to always reread and refresh eachtime a single data change. Or have a global notification to redisplay everything each time a singledata change. I wish you good luck.”

With QuantumMVVM, the new contract between the View Controller and the Repository Observerwill become: “Me, Repository Observer, I am informing you, View Controller, following the changesjust performed on the Data Repository in this event cycle, that all the data which are needed by yourviews have reached a coherent state. I request you to read all the data needed to refresh your viewsbefore this call returns. This will be your unique notification.”

The communication between View Controllers shall be limited to creation/dismiss and initializationof child view controllers. All data exchange between View Controllers shall be performed via theData and Context repository.

Let’s illustrate these different phases.

Registration Phase

Registration Phase

On View Controller creation, the View Controller shall register its Refresh Actions via its ViewModel, following target-action pattern.

Page 13: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

Solution Overview 8

On Root Object creation, the root object shall register itself.

Update Phase

Update Phase

On each input, the View Controller shall update the Data Repository via its View Model.

• U1: Input Action initiated by user interface• U2-U3: Update of Data Repository, repeated as many times as needed.• U4: After the last update of the event loop, call refreshUI().

Page 14: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

Solution Overview 9

Refresh Phase

Refresh Phase

On refreshUI() call, Data Repository Observer will perform, for each registered Refresh Action:

• R1: Polling of the Data Repository to check if one of the registered keypath has been updated.• R2: If yes, then call synchronously the Refresh Action of the View Controller, else perform R1on the next registered refresh action.

• R3-R4-R5: View Controller loads view content from the Data Repository via View Model andrefresh its Views.

• R6: The synchronous Refresh Action call returns.

An important additional concept is that in phase R3-R4, View Model may write data if and onlyif this data is not modifying the already evaluated keypath in the previous R1 steps of the currentevent loop, as detailed in “Concept: Dependency Management”

Comparison with Reactive

And for experienced programmers, a small advance reflexion if you are just thinking that thedescription above is very close of Reactive paradigm. And it’s true. Both Quantum and Reactiveare capturing values of a set of variables, defining a contract on the state of these variables, andperform an action on this set. The fundamental difference resides in both the way the values arecaptured and the time at which this closure is scheduled.

Reactive captures the values by performing a copy of the value into a signal, and schedules theexecution of a closure asynchronously on the requested thread.

Page 15: Quantwm - samples.leanpub.comsamples.leanpub.com/quantummvvm-sample.pdfThanks to my wife Catherine, the sunshine of my life, and to my children. Thanks to Cocoaheads Paris, which allowed

Solution Overview 10

Quantum captures the value by enforcing that the value will not change until the end of the eventloop, and call the registered target/action inside the event loop before the event call returns.

Both methods are very powerful, and complement themselves. Reactive is best suited for asyn-chronous processing: networking, user input until reaching a state which can be shared by the viewcontroller, interaction between threads. Quantum is best suited for synchronous management ofcomplex or massive interfaces. We could describe Quantum as an efficient, synchronous Reactivewhere you can see the full stack which is triggering your action and only be called at most onceinside your event loop.

And as personal preference, I findmore natural to pull data from repository when the view controllerhas a confirmed need of it, rather than systematically pushing it to the view controller.

Next steps

The first chapter presented MVVM, and its strengths and weakness. This chapter presented anoverview of Quantum MVVM.

The next chapters will details the concepts required to understand Quantum, and also try to justifythe enigmatic origin of the name “Quantum”:

• The Event Loop, Freezing Point and Cold Phase• Keypath and Observable• Transactions• Dependency Management• View Controller hierarchy configuration

The Part 2 will provide detailed Quantum user guide and API details for each component:

• Data Repository• View Controller• View Model

The Part 3 will consider more advanced topics:

• Quantum Migration Guide• Interaction with background threads• Evolution toward standard Quantum User Interface components• Unit Testing