The Twelve-Factor App says:
Use declarative formats for setup automation, to minimize time and cost for new developers joining the project
What does "declarative formats" mean?
Declarative Code. Declarative code is very common, and it is represented by domain-specific, logic, and functional programming languages. Examples of these are HTML, SQL, F#, Prolog, and Lisp.
Declarative programming focuses on the end result, while imperative programming focuses on how to get there. For example, when you jump in a taxi, you declare to the driver where you want to go. You don't tell him how to get there by providing turn-by-turn directions.
What. A technique for making it easier to design and redesign using descriptions of design at a much high level that make it easier for both a human or machine to manually or automatically explore potential implementation tradeoffs.
Declarative languages, also called nonprocedural or very high level, are programming languages in which (ideally) a program specifies what is to be done rather than how to do it.
A declarative format is one in which you declare the intention/end-result of the program, instead of how it should be arrived at. Declarative code is typically comprised of statements that invoke high-level functions or abstractions with clear human-readable intent. Conversely, imperative code is comprised of statements that clearly impart their effects on the program state without reference to any high-level goal.
More succinctly, declarative code conveys the why, and imperative conveys the how.
The following code is the Makefile
for a hypothetical program hellomake
. This program uses the abstractions provided by make
to define the build procedure without specifying the the implicit low-level details. The Makefile
only needs to specify the compiler, the source directory, and the file dependency structure, and then uses the make
abstractions to fill in all the boilerplate based on this program structure. This is considered a declarative
format because the statements convey high-level meaning without specifying low-level actions.
CC=gcc
CFLAGS=-I.
DEPS = hellomake.h
# Build an object file for each of the dependencies.
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
# Build the hellomake program using the hellomake and hellofunc object files.
hellomake: hellomake.o hellofunc.o
gcc -o hellomake hellomake.o hellofunc.o -I.
The following Python script performs the same task defined in the Makefile
, but because Python is far more general-purpose than make
, all of those build details need to be performed explicitly. These explicit program actions clearly describe how the program will alter the build environment, but cannot describe how they contribute to the overall goal of compiling the program without auxiliary explanation (e.g. comments). This is considered an imperative
format because the low-level actions are clearly defined and conveyed to the programmer.
CC = "gcc"
CFLAGS = "-I."
DEPS = ["hellomake.h"]
def make_o_file(o_file, deps):
#don't recompile if it exists & is current
c_file = "%s.c" % os.path.splitext(o_file)[0]
if (os.path.exists(o_file)
and is_newer(o_file, c_file)
and all(is_newer(o_file, dep) for dep in deps)):
return
#else actually compile it
compile_c_file(CC, code_file, o_file, CFLAGS)
if target == "hellomake":
make_o_file("hellomake.o", DEPS)
make_o_file("hellofunc.o", DEPS)
link_o_files("hellomake", ["hellomake.o", "hellofunc.o"])
Both imperative and declarative formats serve valuable purposes in programming. The Wikipedia on declarative programming might be useful for additional details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With