Here we document the reasoning behind certain tools, technology and process choices for Mojaloop.
- Open source - the entire project may be made open source in accordance with the level one principles. All tools and processes must be open source friendly and support an Apache 2.0 license and no restrictive licenses.
- Agile development - The requirements need to be refined as the project is developed, therefore we picked agile development over waterfall or lean.
- Scaled Agile Framework - there are four initial development teams that are geographically separate. To keep the initial phase of the project on track, the scaled agile framework (SAFe) was picked. This means work is divided into program increments (PI) that are typically four 2 week sprints long. As with the sprints, the PI has demo-able objective goals defined in each PI meeting.
- Threat Modeling, Resilience Modeling, and Health Modeling - because this code needs to exchange money in an environment with very flaky infrastructure it must have good security, resilience, and easily report it's health state and automatically attempt to return to it. To achieve this we employ basic tried and true modeling practices.
- Automated Testing - for the most part, most testing will be automated to allow for easy regression. See the automated testing strategy.
- Microservices - Because the architecture needs to easily deploy, scale, and have components be easily replaced or upgraded it will be built as a set of microservices.
- APIs - In order to avoid confusion from too many changing microservices, we use strongly defined APIs. APIs will be defined using OpenAPI or RAML. Teams document their APIs with Swagger v2.0 or RAML v0.8 so they can automatically test, document, and share their work. Swagger is slightly preferred as there are free tools. Mule will make use of RAML 0.8. Swagger can be automatically converted to RAML v0.8, or manually to RAML v1.0 if additional readability is desired.
- Services - Microservices are grouped and deployed in a few services such as the DFSP, Central Directory, etc. Each of these will have simple defined interfaces, configuration scripts, tests, and documentation.
- Database Storage - although Microsoft SQL Server is widely used in Africa, we need a SQL backend that is open source friendly and can scale in a production environment. Thus, we chose PostgreSQL. The database is called through an adapter and the stored procedures are kept in simple ANSI SQL so that it can be replaced later with little trouble.
- USSD - Smart phones are only 25% of the target market and not currently supported by most money transfer service, so we need a protocol that will work on simple feature phones. Like M-Pesa, we are using USSD between the phone and the digital financial service provider (DFSP).
- Operating System - Again, Microsoft Windows is widely used in many target countries, but we need an operating system that is free of license fees and is open source compatible. We are using Linux. We don't have a dependency on the particular flavor, but are using the basic Amazon Linux. In the Docker containers, Alpine Linux is used.
- Interledger - The project needed a lightweight, open, and secure transport protocol for funds. Interledger.org provides all that. It also provides the ability to connect to other systems. We also considered block chain systems, but block chain systems send very large messages which will be harder to guarantee delivery of in third world infrastructure. Also, while blockchain systems provide good anonymity, that is not a project goal. To enable fraud detection, regulatory authorities need to be able to request records of transfers by account and person.
- MuleSoft - For the most part, the mule server is simple a host and pass through for Level One Client API calls. However, it will be necessary to deploy Mojaloop system into existing financial providers. MuleSoft provides an excellent adapter so that the APIs can be easily hooked up to existing systems while providing cross cutting concerns like logging, fault tolerance, and security. The core pieces used don't require license fees.
- NodeJS - NodeJS is designed to create simple microservices and it has a huge set of open source libraries available. Node performance is fine and while Node components don't scale vertically a great deal, we plan to scale horizontally, which it does fine. The original Interledger code was written in NodeJS as was the level one prototype this code is based on. Most teams used Node already, so this made sense as a language.
- NodeJS "Standard" - Within NodeJS code, we use Standard as a code style guide and to enforce code style.
- Java - Mule can't run NodeJS directly, so some adapters to mule and interop pieces are written in Java. This is a very small part of the overall code.
- Checkstyle - Within Java code, we use Checkstyle as a code style guide and style enforcement tool.
- GitHub - GitHub is the standard source control for open source projects so this decision was straightforward. We create a story every time for integration work. Create bugs for any issues. Ensure all stories are tracked throughout the pipeline to ensure reliable awx.
- Slack - Slack is used for internal team communication. This was largely picked because several team already used it and liked it as a lightweight approach compared to email.
- ZenHub - We needed a project management solution that was very light weight and cloud based to support distributed teams. It had to support epics, stories, and bugs and a basic project board. VS and Jira online offerings were both considered. For a small distributed development team an online service was better. For an open source project, we didn't want ongoing maintenance costs of a server. Direct and strong GitHub integration was important. It was very useful to track work for each microservice with that microservice. Jira and VS both have more overhead than necessary for a project this size and don't integrate as cleanly with GitHub as we'd want. ZenHub allowed us to start work immediately. A disadvantage is the lack of support for cumulative flow diagrams and support for tracking # of stories instead of points, so we do these manually with a spreadsheet updated daily and the results published to the "Project Management" Slack channel (Cumulutative flow is being added to Zenhub, but wasn't available for most of the project).
- AWS - We needed a simple hosting service for our Linux instances, and we aren't going to use many of the extra services like geo-redundancy, since we expect customers may wish to self-host. AWS is an industry standard and works well. We considered Azure, which also would have worked, but it's harder for the Gates Foundation to get an Azure subscription than AWS.
- Docker - the project needs to support both local and cloud execution. We have many small microservices that have very simple specific configurations and requirements. The easiest way to guarantee that the service works the same way in every environment from local development, to cloud, to hosted production is to put each microservice in a Docker container along with all the prerequisites it needs to run. The container becomes a secure, closed, pre-configured, runnable unit.
- CircleCI - to get started quickly we needed an online continuous build and testing system that can work with many small projects and a distributed team. Jenkins was considered, but it requires hosting a server and a lot of configuration. CircleCI allowed for a no host solution that could be started with no cost and very limited configuration. We thought we might start with CircleCI and move off later if we outgrew it, but that hasn't been needed.
- Artifactory - After the build we need private repository to put our NodeJS packages and Docker containers until they are formally published. Docker and AWS both do this, and any solution would work. We chose Artifactory from JFrog simply because one team already had an account with it and had it setup.
- SonarQube - We need an online dashboard of code quality (size, complexity, issues, and coverage) that can aggregate the code from all the repos. We looked at several online services (CodeCov, Coveralls, and Code Climate), but most couldn't do complexity or even number of lines of code. Code Climate has limited complexity (through ESLint), but costs 6.67/seat/month. SonarQube is free, though it required us to setup and maintain our own server. It gave the P1 features we wanted.
- DropBox - Intermediate and planning documents need a simple shared set of folders. They don't need versioning or tracking like GitHub offers. The share should have integration with Slack. We considered SharePoint, Syncplicity, Box, and others. DropBox was already used by most teams and the Gates Foundation already had an account for it, so it was simply the easiest to go with. It's also the most full-featured choice and integrates well with Slack.
- Markdown - Documentation is a deliverable for this project, just like the code, and so we want to treat it like the code in terms of versioning, review, check in, and tracking changes. We also want the documentation to be easily viewable online without constantly opening a viewer. GitHub has a built-in format called Markdown which solves this well. The same files work for the Wiki and the documents. They can be reviewed with the check in using the same tools and viewed directly in GitHub. We considered Google Docs, Word and PDF, but these binary formats aren't easily diff-able. A disadvantage is that markdown only allows simple formatting - no complex tables or font changes - but this should be fine when our main purpose is clarity.
- Draw.io - We need to create pictures for our documents and architecture diagrams using an (ideally free) open source friendly tool, that is platform agnostic, supports vector and raster formats, allows WYSIWYG drawing, works with markdown, and is easy to use. We looked at many tools including: Visio, Mermaid, PlantUML, Sketchboard.io, LucidChart, Cacoo, Archi, and Google Drawings. Draw.io scored at the top for our needs. It's free, maintained, easy to use, produces our formats, integrates with DropBox and GitHub, and platform agnostic. In order to save our diagrams, we have to save two copies - one in SVG (scalable vector) format and the other in PNG (raster). We use the PNG format within the docs since it can be viewed directly in GitHub. The SVG is used as the master copy as it is editable.
- Dactyl - We need to be able to print the online documentation. While it's possible to print markdown files directly one at a time, we'd like to put the files into set of final PDF documents, where one page might end up in more than one final manual. Dactyl is a maintained open source conversion tool that converts between markdown and PDF. We originally tried Pandoc, but it had bugs with converting tables. Dactyl fixes that and is much more flexible.
- Ansible - We need a way to set microservice configurations and monitor/verify that those configuration are correct. We need the tool to be very simple to setup and use. It must support many OS's and work for both the cloud and local environments as well as Docker and non-Docker setup. We looked at many tools including: Chef, Puppet, Cloud Formation, Docker Compose/Swarm, Kubernetes, Terraform, Salt, and Ansible. Chef and Puppet were eliminated because they have a very large learning curve and large setup requirements. AWS Cloud Formation and Docker were both limited to specific environments and we need broader support. Terraform was a good tool, but works differently with each environment, so a configuration for cloud can't be reused locally. Kubernetes is also good, but is designed to send commands across large scale environments, not configure a few specific microservices. Salt and Ansible can both do the job. Salt is more scalable and performant, as it puts an agent on each server to orchestrate config. Ansible is much simpler, having an agentless direct setup. We went with Ansible because of the simple setup and learning curve. We don't need the speed and scale Salt provides and accept a slightly lower performance. Ansible allows us to define the expected state of the microservice in a playbook. If the state is incorrect, Ansible can automatically alert and correct the state. In this way it is both a monitoring and configuration tool.