This is a small todo app to demonstrate how to separate application logic and business rules from Ionic 2 as a framework. Almost all the logic is in a directory called
core with no outside dependencies.
Ionic 2 interacts with the
core app through a single point of entry, the
For a todo app, this example might be a bit over-engineered, but it serves as a starting point for a more complex app I’m developing.
Please read my other post Towards A Clean Architecture for Ionic 2 Apps to understand what I’m trying to achieve.
The app is extremely light on UI stuff. There’s basically a Timer that triggers a dummy interaction after 3 and 5 seconds. But that’s not the point of the project.
The idea: Code separation
Ionic 2 is optimized for iOS and Android, but not for web apps. I need all three: A web app, iOS and Android. The web app will be done with Angular 2 and thus, I need to separate as much logic from the framework as possible.
I treat Ionic 2 merely as a client for the core app. There could be other clients, such as a Unit Testing Framework, a command-line client, an Angular 2 web app or even something entirely different.
Most Ionic 2 example apps are written like jQuery apps in 2012. They’re too small to have proper separation of concerns. Everything is dumped all over the place. In the long run, this isn’t a very robust approach.
I was looking for a clean approach to an Ionic 2 architecture and came up with what you see now.
Dependency Inversion through a Data Repository
The database I’ll be using in a later project will be PouchDB/CouchDB. However, it’s a good idea to hide the actual implementation behind an interface. The Todo app uses a
DataRepository interface and an actual
MockRepository implementation that mimics the doc-like approach of PouchDB.
Docs have additional attributes like
_rev that aren’t needed within the core app or Ionic 2’s view layer. This is mostly to demonstrate how entities differ from DTOs and both differ from the database representation of business objects.
Mapping Data to DTOs to Entities
Instead of having a hard dependency within Ionic 2 to work with docs from CouchDB, everything goes through 1-2 steps of data mapping. Docs from the database are mapped to DTOs. DTOs are then turned into actual entities that maintain business logic.
Or the other way around: When taking a new object as input, the input is given as a DTO and the core app decides how to turn that DTO into business objects that maintain all business rules. It also deals with persistence. Ionic 2 as a client doesn’t care about persistence at all.
So for example, if you want to add a todo item, you need to call the according method
addItemToList on the
ItemController (the controller is part of the backend/core app!). The controller takes care of turning the DTO into a business objects, tries to validate business rules and deals with persistence as a side effect.
Ionic can then decide if it updates its view or not, depending on the result of
If you ever wondered what the relationship between docs, DTOs and entities is (like I did), this might give you an idea.
Enjoy, I hope it helps you to understand how to separate code in your own projects.