BRACT: A Minimal DRY Application Framework

BRACT: A Minimal DRY Application Framework

IN/Clojure 2019 presentation on Bract:


Shantanu Kumar

January 12, 2019


  1. BRACT: A Minimal DRY Application Framework Shantanu Kumar

  2. Who Am I? - Principal Engineer, SAP Concur - Author,

    “Clojure High Performance Programming” - Bio - Tends - @kumarshantanu on Twitter, Github
  3. Project setup these days • Commonly repeated concerns • Config,

    Logging, Graceful shutdown, Exceptions • Ad hoc, often copied from old project (error prone) • Init steps are implicit, snowflakes, pets (vs cattle) • Have several projects? Beware of Drift over time
  4. App initialisation deficiencies • Initialisation model (as data, can we

    query it?) • Initialisation steps (as data, can we specify it?) • Sequence of steps (as data, can we declare it?) • Orthogonality (can we refactor the init sequence independent of the involved steps?) • Reloaded workflow (start, stop, reload, restart)
  5. App initialisation challenges • Skill gradient (How many people can

    do this?) • Repeating yourself (Even though they know) • Magical number 7 ± 2 (for business-code focus) • Libraries lack glue, not enough • Templates don’t offer any abstraction
  6. Plausible solution • Divide app into initialisation and runtime phases

    • Initialisation phase prepares app for runtime • First class initialisation artifacts (model, steps) • Different entry-points for deployment/develop envs • Different init sequence for deploy/dev envs
  7. BRACT Multi-purpose, modular app initialisation

  8. Bract—Concepts • Context (map) as “rolling” initialisation state • Well

    known keys (shared among inducers) • Inducers `(fn [context]) -> context` as init steps • Potentially update context, have side effects • Specified declaratively, or programmatically • Context flows through inducers serially
  9. BRACT Some common context keys :bract.core/verbose? :bract.core/context-file :bract.core/config-files :bract.core/exit? :bract.core/cli-args

    :bract.core/config :bract.core/inducers :bract.core/deinit :bract.core/launch? :bract.core/launchers :bract.core/app-exit-code :bract.core/stopper
  10. BRACT: Inducer example (defn invoke-launchers ([context] (if (kdef/ctx-launch? context) (invoke-launchers

    context (kdef/ctx-launchers context)) (do (echo/echo "Launch not enabled, skipping launch.") context))) ([context launchers] (if (kdef/ctx-launch? context) (do (echo/echo "Launcher name:" launchers) (induce context launchers)) (do (echo/echo "Launch not enabled, skipping launch.") context))))
  11. Bract—Philosophy • NOT Convention over Configuration • Configuration defaults, overridable,

    powerful • Easy to reason about, not magical • Modular, each module offers capabilities • App runtime oblivious of Bract
  12. Context & Inducers (-> {,,,,} bract.core.inducer/run-context-inducers (my.webapp.init/app-init :debug) bract.ring.inducer/apply-wrappers bract.core.inducer/invoke-launchers)

  13. Inducers specified (EDN) [bract.core.inducer/run-context-inducers (my.webapp.init/app-init :debug) bract.ring.inducer/apply-wrappers bract.core.inducer/invoke-launchers]

  14. Bract—Modules • bract.core • bract.cli • • bract.ring •

    gossamer.core • Inducers • Context resources • Config resources • Necessary dependencies Available modules Modules may offer
  15. Demo Apps Image source:

  16. Entry points • Regular CLI (project.clj —> {:main b.core.main}) •

    Tests (require []) • REPL (require []) • Lein plugins (e.g. lein-ring) • {:handler :init!}
  17. Modules must integrate • Modules must integrate with app via

    framework • Module without Integration = Library • Hooks (plugins) vs configuration • Bract: Init steps ARE the glue! • Caveat: Writing excessive init steps is regressive!
  18. Gossamer Web framework based on Bract Try using: lein new

    gossamer <app> Image source:
  19. Gossamer • Opinionated (most Bract modules are not) • Batteries

    included (web, logging, middleware) • Initialisation steps are prescribed/inherited • Overridable • Init steps evolve across versions in Gossamer • App benefits from Gossamer version bump
  20. Gossamer • Consumer-facing framework • May be customised for special

    needs • Web framework • Can do custom (batch, maint) jobs • May have own modules (in future)
  21. Gossamer Demo App Image source:

  22. Thanks! @kumarshantanu