Design Principles
We're big fans of Ruby & Rails! The following links explain the principles and philosophy behind Arc:
Modularization
Monolithic applications and codebases require extra effort to ensure long term maintainability. Arc is built using the Modular Monolith approach (ADR) to stablish and enforce boundaries between them.
Modules
A module is a functional cohesive unit and it can be either business-oriented, encapsulating a specific domain of the business logic, or technical, providing a set of related functionalities such as logging or authentication.
Module API
- Public API: set of functionalities exposed to the rest of the application. This public API is the contract that the module provides, and it should be stable and well-documented.
- Private API: used internally by the module and should not be accessed by other parts of the application. This allows the module to change its internal implementation without affecting other parts of the application, as long as the public API remains the same.
Implementation
Modules are implemented using packs-rails, a tool built on top of Shopify's packwerk to enforce boundaries and modularize Rails applications. Each pack resembles a full Rails application and it will follow Rails conventions.
- Grouping: modules can be grouped in directories to organize them.
- Dependencies: modules can depend on other modules, accessing their public APIs.
- Namespaces: modules can be namespaced using Ruby Modules to avoid name collisions. Ideally the namespace should match the module name but additional namespaces can be used.
Pack structure example
package.yml # root level pack
modules/
module_name/
package.yml # Packwerk descriptor
app/
public/ # Recommended location for public API
services/ # Private services
models/ # Private models
controllers/
views/
config/
initializers/
jobs/
lib/
tasks/
spec/
public/
services/
models/
factories/
modules_group/ # Modules can be grouped in directories
module_name/
package.yml
...