MobileFrontend/JS code organization

Current state
Currently, JavaScript code in MobileFrontend is divided into separate modules (files). Each of them is responsible for a distinct feature in the mobile frontend, e.g.  folds and unfolds sections in articles,   adds additional feature to the mobile watchlist (thumbnails). The concept is similar to plugins.

Those modules are usually subsequent improvements added to the mobile frontend, not necessarily logical blocks of the application. Each module is optional and provides a javascript enhancement on top of the normal view.

Modules are sandboxed and should not communicate with one another. Where common functionality is identified historically this has been moved to mf-application.js. A module may bind triggers to certain events to allow other modules to run on these.

Some modules use the  function which expects an object with an   function as its argument. After the main code is initialized the  function of each module is called. This is used by modules which may need to reinitialize given a change of context - for example every time a page is dynamically loaded.

Other modules simply do something without ever calling, which can be binding to an event of the   object or performing some actions after the DOM is ready. This method is only used by modules which do not need to run more than once.

There are no guidelines as to how modules should look like. They are usually a collection of functions that perform everything needed for the given module without following any programming paradigms. Object oriented patterns are not used, there are no separate objects which would take care of different parts of a particular feature, like interpreting data from APIs (model) and building user interface (controllers/views/templates).

Very often a single JavaScript function has multiple responsibilities, like fetching data from API, fetching data from DOM, manipulating this data and rendering the user interface.

Problems
There are two main problems with our current JavaScript code:


 * Lack of code modularity, lots of functions that "do everything" (this is not about splitting code among many files, it's about enforcing Separation of concerns).
 * I'm not sure I agree... Can you give an example? I think most modules are large as they introduce new functionality that other modules have no need for. Over time these have been split into common functions in javascripts/common/ directory (e.g. notifications for example) Jdlrobson (talk) 20:45, 10 January 2013 (UTC)
 * Lack of a standardized module system (just loose JS files).
 * Does desktop have one? As far as I know it to just makes use of loose JS files Jdlrobson (talk) 20:45, 10 January 2013 (UTC)

Code modularity
The lack of code modularity has three consequences:


 * It makes code reuse or even noticing that a part of the code could be reused harder.
 * Not sure I agree here. Common functionality can be found on mw.mobileFrontend or mw Jdlrobson (talk) 20:45, 10 January 2013 (UTC)
 * It makes reviewing the code more tedious. When even a small change is introduced in a large function that has many responsibilities, the reviewer often has to reread the whole function to understand that small change.
 * Example of a large function that is difficult to code review? Jdlrobson (talk) 20:45, 10 January 2013 (UTC)
 * It makes testing more difficult. A piece of code that has many responsibilities can not be unit-tested which often leads to not testing that code at all.

TODO: add example of tangled code and how it can be untangled (modularized)

Module system
The lack of a good module systems has the following consequences:


 * Modules do not inter-operate, i.e. one module can't use another module's functionality easily. Right now we put all the functions we need in several places in mf-application.js but this file keeps growing and the functions it contains are often not related (e.g.  and  ).
 * Agreed - mf-application.js could and should definitely be reorganised. Note I expect things like getToken can eventually be replaced by functions in the mw library. Modules should not be able to inter-operate and where they can should make use of events - we should work on the assumption that any module can be removed without breaking any other module. Jdlrobson (talk) 20:45, 10 January 2013 (UTC)
 * There is no dependency management (there is no way to indicate that a module requires any other module to be loaded before it can run, we have to manually figure out loading order of JS files in PHP files).
 * Modules shouldn't depend on other modules. Modules might made use of additional libraries - e.g. jQuery.msg for example but there IS dependence management in that these dependencies can be managed in ResourceLoader. Jdlrobson (talk) 20:45, 10 January 2013 (UTC)

Solutions
Developers struggled with JavaScript code organization in many other big projects before us, so the most obvious solution to make the code more modular would be to use one of the popular JavaScript frameworks to structure the code. Apart from that we need to standardize our modules somehow.

Frameworks
There are two important things to note where it comes to our mobile frontend though if we are to use a framework:


 * We use various data sources. Typically, web apps rely on a standardized AJAX API to get data. We have many APIs that sometimes don't follow guidelines and are not RESTful. We also often fetch required data from the DOM of the server-side generated web site (e.g. titles of articles in the watchlist to query the PageImages extension). This means we need really flexible models.
 * Our web app is not a typical one-page web app where everything is loaded dynamically. It's more of a hybrid between a web site and a web app. The main reason for this is compatibility with devices with no JavaScript support. In the future we might think about separating it into a legacy mode without JS and a one-page dynamic web app. This would make the development easier and the mobile fronted more responsive.

The framework we choose should satisfy the following:


 * Be popular, with active community and good docs.
 * Be small (mobile).
 * Be flexible, do not impose too much on how we communicate with the backed or how we modify DOM.
 * Do not assume a fully dynamic one-page app.
 * Should provide only the barebones functionality we need. TODO:What is this? Jdlrobson (talk) 20:47, 10 January 2013 (UTC)

Modules
Right now modules are just scripts that do something by themselves and optionally have an  function. It would be useful to have something similar to AMD modules. We should investigate if Resource Loader can help us with that.