Here are some design ideas & principles that guided the development or emerged while coding mbt. They are informed by the observations made in the rationale.
Mbt's apis try to be as uniform as possible by providing functions of one argument. This argument is a context / config map making every effective argument a named one.
This model allows for the following properties:
The process of building artefacts involves versioning. There is support for a pluggable versioning schemes using git tags in the default api. Maven and Semver are there...
There is also very basic support designed with the spec-ulation talk and the Meander project in mind. The idea is to have named Major versions which are reflected in namespaces and in artefact names. Also we must never introduce breaking changes inside a major version, Only provide more or require less. (See the spec-ulation talk).
For instance this project is named "mbt" and has a major version name alpha
. The git tags
and maven artefacts generated will be mbt-alpha(something)?
. In the alpha version
the code lives in ...mbt.alpha.xxx
namespaces. Configuration keywords and specs are also using a full
:...mbt.alpha.XXX/YYY
style.
This way when we want to provide a new major version i.e., a new thing i.e, breakage, we provide a new Major version
named for instance beta
. We would then have mbt-beta
artefacts with code living under ...mbt.beta.xxx
namespaces and :...mbt.beta.XXX/YYY
keywords.
It allows to have an arbitrary number of major versions living peacefully in the same classpath
and so reduce dependency hell. At least that's the idea.
To impose that the keywords used in the program all be namespace qualified can be a bit unwieldy at first. Especially considering:
::name
expanding to
something like :com.domain.project.version.actual.ns/name
com.domain.project.version
is there to avoid clashesactual.ns
should be a domain specific context for the keyword's nameactual.ns
part isn't necessarily what we want. It comes from the namespaces where ::name
is usedThe solution used in mbt is to provide macros simplifying this kind of stuff:
(create-ns 'com.domain.project.version.user)
(alias 'user 'com.domain.project.version.user)
::user/name
;=> :com.domain.project.version.user/name
(fr.jeremyschoffen.mbt.alpha.utils/pseudo-nss project)
::project/name
;=> fr.jeremyschoffen.mbt.alpha.project/name
There is a lot here that seems common wisdom. Still it might be good to state the obvious and see how mbt relates.
Mbt comes with a low level core api. The core utilities must be as un-opinionated and orthogonal as possible. This is the no assumptions part of the api.
For instance the core api provides:
deps.edn
format)None of these functions depend on one another. The one map argument principle allows a coding model where we can thread together several utilities on a config / context map. Several helper functions are provided to make this process easier.
Using just the core api can be tedious. The goal here is to provide a gluing of the core api in a sensible default fashion. For instance there is a function that encompasses all the steps cited in the previous example.
Still any build process that needs more complexity than what the default api provides can use the core api to define its own build tool and still use the default api where useful.
This project takes a lot from different projects whether in design ideas or directly in the way to code specific things:
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close