Slide 1

Slide 1 text

BRACT: A Minimal DRY Application Framework Shantanu Kumar

Slide 2

Slide 2 text

Who Am I? - Principal Engineer, SAP Concur - Author, “Clojure High Performance Programming” - Bio https://kumarshantanu.github.io/ - Tends https://bangalore-clj.github.io/ - @kumarshantanu on Twitter, Github

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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)

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

BRACT Multi-purpose, modular app initialisation https://bract.github.io/

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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))))

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Context & Inducers (-> {,,,,} bract.core.inducer/run-context-inducers (my.webapp.init/app-init :debug) bract.ring.inducer/apply-wrappers bract.core.inducer/invoke-launchers)

Slide 13

Slide 13 text

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]

Slide 14

Slide 14 text

Bract—Modules • bract.core • bract.cli • bract.dev • bract.ring • gossamer.core • Inducers • Context resources • Config resources • Necessary dependencies Available modules Modules may offer

Slide 15

Slide 15 text

Demo Apps https://github.com/bract/demo.wordcount https://github.com/bract/demo.diceroll Image source: https://davesgarden.com/guides/articles/view/3156

Slide 16

Slide 16 text

Entry points • Regular CLI (project.clj —> {:main b.core.main}) • Tests (require [bract.core.dev]) • REPL (require [bract.core.dev]) • Lein plugins (e.g. lein-ring) • {:handler b.ring.dev/handler :init b.ring.dev/init!}

Slide 17

Slide 17 text

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!

Slide 18

Slide 18 text

Gossamer Web framework based on Bract Try using: lein new gossamer Image source: http://membean.com/exemplars/gossamer https://github.com/bract/gossamer.core

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Gossamer • Consumer-facing framework • May be customised for special needs • Web framework • Can do custom (batch, maint) jobs • May have own modules (in future)

Slide 21

Slide 21 text

Gossamer Demo App https://github.com/bract/demo.todomvc Image source: https://www.canadaflowers.ca/christmas-plants-poinsettias/perfect-poinsettia-plant.htm

Slide 22

Slide 22 text

Thanks! @kumarshantanu