Skip to content

Latest commit

 

History

History
71 lines (50 loc) · 4.2 KB

about.md

File metadata and controls

71 lines (50 loc) · 4.2 KB
layout title
default
About Bract - Multi-purpose, modular application initialization framework for Clojure

Rationale

Application configuration and initialization are tangential to delivering business value, yet we frequently get bogged down by their incidental complexity. Application development could be a better experience if we only have to focus on the application logic without worrying about configuration, initialization and the sundry development/maintenance tasks that applications frequently need. This should be a solved problem in a repeatable, predictable manner.

What is Bract?

Bract is a Clojure framework to bring power and flexibility to application configuration and initialization workflow. Whether you are developing your application, writing tests or preparing for deployment, Bract has you covered.

Bract aims to:

  • Bind the following pieces together
    • Application entry-point
    • Application configuration
    • Various steps to initialize, launch, stop and deinitialize application
  • Allow extensions to Bract, e.g. any library/framework integration

Bract does not aim to:

  • Prescribe which environments (Dev/QA/Prod etc.) you may have
  • Decide which libraries you should use (except Keypin for configuration)
  • Make you use Dependency Injection, let alone any particular DI library
  • Discourage you from using Dependency Injection

Bract is made of bract.core (with Keypin as the only dependency for config support) and a bunch of modules for various purposes. While bract.core is low level and prescribes no style, it is possible to author opinionated Bract modules on top of it. One may even extend Bract to build a custom application framework. Bract is suited for various types of applications, e.g. command-line tools, web services, batch jobs, web applications etc. and integrates well with tangential, yet relevant aspects such as configurable JVM logging.

How it works

The bract.core module is the minimum requirement for using Bract, and is used by all other modules. The essential idea behind Bract is the "inducer function" (fn [context & args]) -> context, also called inducer. One or more (often nested) inducers form the initialization workflow. The context is a map passed to one inducer after another.

Inducer

An inducer's role is to bring about a certain kind of change. An inducer receives the context map as argument, and must always return either updated or unchanged context. Say for example, a config-reader inducer may discover the config file name from the context and populate the context with loaded config before returning. An inducer usually does not know which other inducers are participating in the workflow. The inducers and their order of invocation are generally decided by either a Bract module (as entry point) or by the application developers. Various inducers are provided by the Bract modules and by the application developers.

Well known keys

An inducer generally needs information to do its job, which it can find in the context and in the optional arguments. The information an inducer finds in the context is usually put in by other inducers that executed earlier. However, inducers only have hard dependency on well-known context (or config) keys. This helps to keep inducers decoupled from each other while encouraging flexible workflows.

Entry point

The top level inducer workflow is usually executed from either a -main or an implicitly called function. An application may very well choose to do its own processing before invoking Bract initialization, but generally Bract modules make the job easier by providing such entry-point functions.

Fork me on GitHub