lotus/lotus — pull request #106 by jodosha (2014-12-16 17:56:35+00:00)
Title: Code generators

## Container architecture

Previously known as the _microservices architecture_.
I'm proposing to rename it because it's misleading.

[Microservices definition](http://martinfowler.com/articles/microservices.html) by Martin's Fowler:

> In short, the microservice architectural style is an approach to developing a single application as a suite of small services, **each running in its own process** and **communicating with lightweight mechanisms, often an HTTP resource API**.

Lotus _container architecture_ has multiple applications running **in the same process** and **communicating with Ruby's message passing**.

I want to promote it as a **default for new Lotus applications**.

When a project is new, to move fast, a team wants to ship a single deliverable in production.
Once the code grows, they may want to decide to extract microservices. However, this isn't always possible or easy, because of the high coupling between components.

Lotus comes to the rescue, by helping teams to build products with _slices_.
A _slice_ is a web application that serves for a single purpose: user facing application, administration backend, JSON API, dashboard for profiling etc. To make a Rails analogy, it's kinda equivalent to an _engine_. The only difference is that a _slice_ is a self contained Rack application that can be easily extracted.

Here's the name _**container**_: a Lotus _"shell"_ that can run multiple micro applications in the same process.

The core of this architecture lives in `lib/`, where developers should build features **independently from the delivery mechanism**.

Imagine you are building a personal finance application, and you have a feature called _"register expense"_. This functionality involves `Money` and `Expense` Ruby objects and the need of persisting data into a database. You can have those classes living in `lib/pocket/money.rb` and `lib/pocket/expense.rb` and use [Lotus::Model](https://github.com/lotus/model) to persist them.

It has few but important advantages:

* Code reusability. You can register an expense from the Web UI or from a JSON API, which can be different Lotus _slices_ or simple Rack based apps.
* Decoupled components. The core of your application depends only on a few gems and it doesn't need to worry about the Web/HTTP/Console/Background jobs.
* Applications are built like a gem, this ease the process of package them and share between projects, without the need of carry on a lot of dependencies.

### CLI

In order to test it, please checkout this branch and run:

```shell
% bundle exec lotus new pocket --lotus-head=true
```

This will generate a new application called `pocket`, which uses the `HEAD` of each Lotus repository.

It has some default options:

* Minitest + Capybara. Already planning to support RSpec + Capybara.
* Unit tests for: actions, views, entities, repositories etc. should be run by Minitest/RSpec.
* Feature tests: for testing functionalities at the high level should be run with Minitest/RSpec + Capybara.
* The adapter for Lotus::Model is `:file_system`. It allows rapid prototyping without the need of migrations (not yet implemented by Lotus).

### Layout

```shell
% cd pocket
% tree -a rb:ruby-2.1.5
.
├── Gemfile
├── Rakefile
├── apps
│ └── web
│ ├── application.rb
│ ├── config
│ │ ├── mapping.rb
│ │ └── routes.rb
│ ├── controllers
│ │ └── .gitkeep
│ ├── templates
│ │ └── application.html.erb
│ └── views
│ └── application_layout.rb
├── config
│ ├── .env
│ ├── .env.development
│ ├── .env.test
│ └── environment.rb
├── config.ru
├── db
│ └── .gitkeep
├── lib
│ ├── pocket
│ │ ├── entities
│ │ │ └── .gitkeep
│ │ └── repositories
│ │ └── .gitkeep
│ └── pocket.rb
└── test
├── features_helper.rb
├── pocket
│ ├── entities
│ │ └── .gitkeep
│ └── repositories
│ └── .gitkeep
├── test_helper.rb
└── web
├── controllers
│ └── .gitkeep
├── features
│ └── .gitkeep
└── views
└── .gitkeep

20 directories, 24 files
```

Let's inspect component by component:

* `Gemfile` it just includes a few gems (`lotusrb`, `lotus-model`, `minitest` and `capybara` in the `:test` group)
* `Rakefile` a single, default task to run the test suite
* `lib/pocket.rb` This is the entry point for the application. It contains setup code for `Lotus::Model`.
* `lib/pocket` This is where all the entities and repositories lives, alongside with the _interactors_ (aka _service objects_, not yet implemented by Lotus). All the Ruby files are recursively required when the app starts.
* `config/environment.rb` This is the entry point for the whole process. All the boot mechanisms in development/test/production depend on it.
* `config/.env{.development,.test}` Those are configuration files compatible with [Dotenv](https://github.com/bkeepers/dotenv). Here there are autogenerated settings like database uri connection string or session secrets.
* `config.ru` Rackup configuration file.
* `apps` This is where all the _slices_ live.
* `apps/web` The generated default slice
* `db` The directory where the file system database adapter persist data.
* `test` Test directory
* `test/test_helper.rb` Contains boilerplate code to setup the test environment. This should be required by **unit tests** in order to speed up the CI build
* `test/features_helper.rb` Contains setup code for feature tests. This should be required by **features tests**.
* `test/pocket` This should be used to test main application components: entities, repositories and _interactors_.
* `test/web` Contains both **unit tests** (under `test/web/{controllers,views}`) and **features tests** (under `test/web/features`).

Here's a closer look to `lib/pocket.rb`:

```ruby
require 'lotus/model'
Dir["#{ __dir__ }/**/*.rb"].each {|file| require_relative file }

Lotus::Model.configure do
# Database adapter
#
# Available options:
#
# * Memory adapter
# adapter type: :memory, uri: 'memory://localhost/pocket_development'
#
# * SQL adapter
# adapter type: :sql, uri: 'sqlite://db/pocket_development.db'
# adapter type: :sql, uri: 'postgres://localhost/pocket_development'
# adapter type: :sql, uri: 'mysql://localhost/pocket_development'
#
adapter type: :file_system, uri: ENV['POCKET_DATABASE_URL']

##
# Database mapping
#
mapping do
# collection :users do
# entity User
# repository UserRepository
#
# attribute :id, Integer
# attribute :name, String
# end
end
end.load!
```

Here's what's inside `apps/web/application.rb`:

```ruby
module Web
class Application < Lotus::Application
configure do
root __dir__

# adapter type: :file_system, uri: ENV['WEB_DATABASE_URL']

routes 'config/routes'
# mapping 'config/mapping'

layout :application

# cookies true
# sessions :cookie, secret: ENV['WEB_SESSIONS_SECRET']

load_paths << [
'controllers',
'views'
]

controller.prepare do
# ...
end

view.prepare do
# ...
end
end
end
end
```

As you may have noticed, there is another extra and **optional** database to setup. This is there, in case you want to persist extra data that is only pertinent to the user facing application.

## Slice

It allows to create a new _slice_ from an already existing _container_ application.

_To be implemented_

## Micro architecture

_To Be Implemented_

Closes #29