In my last post, I started setting out some of the work we did to create GapVis, an online interface for reading and visualizing GAP texts. In this post, I’ll go a bit more into the technical details of the application, which uses the Backbone.js framework.
A lot of the process of building a web application like GapVis (at least the way I do it) is about iteratively coming around to a solid architecture. For example, I started off without storing application state in any single place; but I discovered I was rapidly entering a tangled web of cross-referenced function calls in which too many parts of the application had to be aware of each other. Eventually, I arrived at the “global state” pattern, allowing different pieces to be nicely independent of each other by having everything listen to events on a single State model.
At the same time, I realized that in many cases coordinating the different components would be easier if “parent” components were responsible for their children, so I added some structure to make this simpler. As I went along, I noted the choices I was making, to help me follow a consistent pattern as I added new components:
Basic architecture: - Models are responsible for getting book data from API - Singleton state model is responsible for ui state data - Views are responsible for: initialize: - instantiating/fetching their models if necessary - instantiating sub-views - listening for state changes - listening for model changes render: - adjusting the layout of their container boxes - creating their content events: - listening for ui events, updating state ui methods: - updating ui on state change - updating ui on model change - Routers are responsible for: - setting state depending on route - setting route depending on state Process of opening a view: - URL router or UI event sets state.topview to the view class - State fires topview:change - AppView receives event, closes other views, calls view.open() - view clears previous content if necessary - view either renders immediately, or fetches data and renders
This is actually taken straight from the code comment I used to keep track of it. While this kind of documentation is usually used to enforce consistency across multiple programmers, I found it helpful for my own use as well, if only as a way of forcing me to solidify my architectural choices.
I hope that wasn’t too much technical detail (and if you want more, let me know – I’m happy to answer questions!). The last post will talk more about some of the interface and design choices we made, and how we think this kind of interface enhances and deepens the experience of reading GAP texts. And if you haven’t done so yet, please check out the GapVis application and let us know what you think!