Search code examples
coding-style

What is a "declarative format"?


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?


Solution

  • 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.