Kooboodle Online UI Architecture
Today we are going to look at the problems we are experiencing with our current Kooboodle website (UI part) and how they can be addressed. Also we are going to make an overview of a new conceptual architecture we are proposing for the website and see whether we should rebuild the UI as a SPA (Single Page Application). This article covers only web client-side UI and related hosting server-side and does not target server api components or desktop/mobile apps.
Why do we need a new UI architecture?
First of all, current website was built based on OpenPhoto open-source framework and was customized for our needs. This served as a good starting point for creating a photo sharing platform. But when project was branched off and we started to implement new features with time we lost the capability of updating the system’s framework with the original source being actively developed.
Problems we are facing right now which imply high cost
Here is a list of problems that makes both maintenance cost high and user experience poor.
- Performance issues
- Server performance issues – this is not directly related to client-side UI, but well-organized client side can help decrease server-side load (mostly by decreasing the number of requests and optimizing resource loading).
- UI performance problems are mostly related to pages where a big amount of photos is shown or involved into a single operation. E.g. sharing photos. It takes a lot of resources to execute performance tests. Also UI components are not scalable to handle required amount of data (pictures).
- Buggy functionality due to the lack of UI unit tests. This is because of immaturity of the original framework and inconsistency in UI modules.
- Slow development due to non-modularity of the UI components. This makes implementation of new features very slow.
- Poor UX due to impossibility to upgrade framework and UI dependency libraries. Consuming the old version of the original framework which is tightly coupled with outdated versions of some libraries (e.g. jQuery!!!) makes it difficult to develop according to modern development standards.
- Fragility of integration test automation. QA often faces broken tests when new features are introduced or bugs are fixed. I believe this is happening because current web site organization is not good enough for automation (e.g. no css class naming convention, html structure of components is not generic enough for reliable referencing UI elements from automation scripts). This brings us away from continuous integration pipeline, and makes a release process painful and time consuming.
What’s not possible with current architecture
- Responsive design
- User-specific customizations
- Widget based experience
- Real-time update experience
To solve all the listed problems and to get prepared to possible feature its essential to reevaluate the existing architecture and use appropriate tools and libraries to rebuild the application.
Goals to be achieved by the new architecture
Lets look now at the aspects that we should consider when proposing an architecture. I would like to refer to these design considerations as a goals the new architecture should be targeting. Achieving these goals is supposed to make maintenance and development cost low.
- Modularity. As a rich web application the UI should be built as a set of reusable, self-contained modules. This will give us important benefits such as:
- Reusability. Why build reusable modules? Because we are already looking towards different platforms like Facebook or Kik (smartphone messenger with a built-in browser) that we could develop UI apps for (Facebook canvas app, Kik card). And once we create a good module like gallery, or lightbox, or comments we could reuse it for any of our web apps.
- Scalability. By scalability in general we mean “quality of a software system to satisfy goals when characteristics of the execution environment and the system design vary over expected ranges” . At the simplest level, scalability is about doing more of something. This could be responding to more user requests, executing more work or handling more data . The last point is the most relevant to UI. The main goal of our software is to serve images the amount of which could be huge.
- Capability to handle potentially infinite stream of images.
- Robustness / Reliability. This includes:
- Fault tolerance
- Non-blocking UI experience
- Customizability. System should be able to serve a customized pages based on some criteria (like user’s location, previous experience, user’s preferences, etc) which will allow us to provide:
- User specific experience
- A/B testing
Now lets look at the concepts that could allow as to achieve the listed goals.
- Loose coupling of the modules. Modules should not have many dependencies and should be self-contained to be testable and reusable. Also modules should expose only certain functionality its build for via “public api”, this will allow to avoid problems when internal module functionality has to be updated.
- Functional reactive approach. See  for explanation of the paradigm by the example of flapjax language.
- to handle events as a stream (e.g. scrolling, mouse clicks, browser window resizing, etc). What is the main difference between Web app and “native” app? In case of a native its OS who handles events and resources for a developer. Browser does the job much worse so we have to help it via organizing events into streams that could be manageable in a much better way. This will allow as to build “non-blocking” UI experience.
- to handle data as a stream. If we could abstract data input into a stream that we know how to manage it will be very helpful for UI components that require fast a lot of rendering of an infinite type of data (like scrolling the gallery or comments).
- Use modern robust framework that is both actively supported and mature enough for a large scalable applications.
- Decouple from server-side. E.g. use REST api for communication. Some exceptions may apply, like: rendering some data on server side to avoid extra http requests, or separately served index page to not load the whole app before user gets authorized.
- Graceful degradation over progressive enhancement.
The goals we discussed and the concepts we would like to use can be applied to both multi-page and single-page applications. Lets take a look at these two approaches and see which one could fit better for our needs.
Single-Page Application vs Multi-Page Website
1. Resource loading
2. HTML caching
Also, multi-page website approach usually implies to render user specific data on server side which makes it impossible to cache by browser or CDN. Its opposite in SPA where application usually loads html templates which can be successfully cached regardless to user content, and then injects user specific information into the DOM. These templates can even be reused by multiple views.
3. Server load, non-blocking UX and offline experience
With regular website when user navigates from page to page every time browser submits a request to server. Then in order to serve the request server creates a process in memory and performs all necessary actions to finally render the output. The server-side actions can take long time in some cases and user would be completely blocked on browser’s side during this period.
With SPA all actions are executed asynchronously, which means user can continue to use the application in browser even when a heavy operations was initiated, e.g. uploading a big amount of photos, or sharing them to other users, or performing some non-trivial searching. While browser is waiting for the async operation to be resolved user is NOT BLOCKED from UI.
Also, for mobile users its often common to experience connectivity loss which is killing for multi-page websites. Whereas SPA can handle this problem with some trivial logic. Moreover modern browsers allow us to use Session and Local storage to store a lot of information including images that will allow user to enjoy the application constantly with an unreliable internet connection.
High level diagram of a proposed SPA architecture
The main idea is that every Page (or Page App) is a small (or big) SPA. We configure pages to use certain modules.
For example, a “semi-private” page could serve a case where Kooboodle user shares photos (or an album) to non-Kooboodle user (the link has to be unique and only known to this person thats why we call it “semi-private” – it does not require authorization for viewing). This page can include “gallery” module, “lightbox” module, “comments” module, “sign-in/sign-up” module.
Another examples of a Page could be a Facebook Canvas App or Kik card.
Regardless to the purpose of the Page, it is a SPA configured to include the core module and one or more other modules.
This way we can develop modules and reuse them for different applications.
- Dependency Injection
- AngularJS – as a main application framework
- RequireJS – as a package dependency manager
- RxJS – as a functional reactive library
- Bootstrap – as a responsive design framework
- SASS (LESS) tbd – as a object-oriented CSS framework
- Protractor – as a e2e development testing framework (not a QA)