Dienstag, 12. April 2016

Avoiding Temporal Coupling - Part 2/2

In part one of this post I briefly introduced the problems which come with temporal coupling and "passing a block" as a technique to overcome those problems. In this last part of the post I want to demonstrate "passing a block" in pure C.

Lets start with a basic implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

typedef void (*FileCommandFunc)(FILE*);

int withFile(const char* fileName, const char* fileAccessMode,
             FileCommandFunc func) {
    FILE *myFile = fopen(fileName, fileAccessMode);
    if (NULL == myFile) {
        fprintf(stderr, "Error opening file '%s': %s\n",
                fileName, strerror(errno));
        return EXIT_FAILURE;
    }
 
    func(myFile);

    fclose(myFile);
    return EXIT_SUCCESS;
}

void printFirstLine(FILE* file) {
    char buffer[1000] = {0};
    if (fgets(buffer, sizeof(buffer), file)!=NULL) {
        printf("%s", buffer); 
    }
}

void printWholeFile(FILE* file) {
    char buffer[1000] = {0};
    while (fgets(buffer, sizeof(buffer), file)!=NULL) {
        printf("%s", buffer); 
    }
}

int main() {
    withFile("demo.txt", "r", printFirstLine);
    withFile("demo.txt", "r", printWholeFile);
}
Function withFile takes three arguments: the name of the file to be opened, the access mode (read, write, append...) and a file command. The latter is a pointer to a function which accepts a file object as only argument.

printFirstLine and printWholeFile are two example commands. Both employ fgets to traverse the file line by line.

In main we see "passing a block" in action. File "demo.txt" is opened in read mode and the actions implemented in the command functions are executed against the file. Error handling and closing of the file handle takes place inside withFile - the user of the function doesn't have to bother with that.

When coding this first draft I realized that my solution is quite limited. Inside the command you can only work with the file passed in and global variables. Other variables aren't simply accessible.

With the GNU Compiler Collection gcc there is the nested functions  feature which nicely works around this limitation:
int main() {
    const char* header = "Content of demo.txt";

    void printWholeFile(FILE* file) {
        puts(header);
        char buffer[1000] = {0};
        while (fgets(buffer, sizeof(buffer), file)!=NULL) {
            printf("%s", buffer); 
        }
    }

    withFile("demo.txt", "r", printWholeFile);
}
I admit the example is a little bit constructed since you could easily print the header before the call of withFile but there you go. The idea is simple: Since printWholeFile is now defined inside main, printWholeFile has access to all global variables and the local variables of main as well.

The downside of this is that it only works in gcc. Here is a more general implementation which uses a technique you find for example in the glibc comparision functions.
The command function accepts a second argument which is a void pointer. This allows us to pass anything into the command. We only have to cast it to the right type before using it. This is basically an accepted disabling of C's type checking.

Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

// withFile.h
typedef void (*FileCommandFunc)(FILE*, void*);

typedef struct {
    const char* name;
    const char* accessMode;
    FileCommandFunc func;
    void* commandArgs;
} withFileArgs;

// withFile.c
int withFile(withFileArgs args) {
    FILE *myFile = fopen(args.name, args.accessMode);
    if (NULL == myFile) {
        fprintf(stderr, "Error opening file '%s': %s\n",
                args.name, strerror(errno));
        return EXIT_FAILURE;
    }
 
    args.func(myFile, args.commandArgs);

    fclose(myFile);
    return EXIT_SUCCESS;
}

// production code

// the commands
void printFirstLine(FILE* file, void* commandArgs) {
    const char* header = commandArgs;

    puts(header);
    char buffer[1000] = {0};
    if (fgets(buffer, sizeof(buffer), file)!=NULL) {
        printf("%s", buffer); 
    }
}

void printWholeFile(FILE* file, void* notUsed) {
    char buffer[1000] = {0};
    while (fgets(buffer, sizeof(buffer), file)!=NULL) {
        printf("%s", buffer); 
    }
}

// using the commands
int main() {
    withFile((withFileArgs){.name="demo.txt", 
                            .accessMode="r", 
                            .func=printFirstLine, 
                            .commandArgs="Content of demo.txt"});

    withFile((withFileArgs){.name="demo.txt", 
                            .accessMode="r", 
                            .func=printWholeFile});
}
For convinces I've also replaced the growing number of arguments of withFile with something you call configuration object in Javascript, in C it is the beautiful marriage of designated initializers and compound literals, both introduced in C99.

Also note that in function printFirstLine the cast from the void pointer commandArgs to the const char pointer header is implicit - no extra cast operation needed on the right hand side of the equals operator.

Montag, 11. April 2016

We Love Code! - Eine popkulturelle Ode an das Programmieren

Ich wohne schon wirklich gern in dieser Stadt Leipzig. Alles da was man so von einer Großstadt erwartet und trotzdem übersichtlich wie früher auf dem Dorf. Und so kam es auch, dass mir "We Love Code! - Das kleine 101 des Programmierens" in die Hände fiel. "Da hat Natalie mit geschrieben - du weißt schon, meine ehemalige Mitbewohnerin" sagte unser Schlafgast.

Macht Spaß zu Lesen (Bildquelle)

Ja, ich konnte mich erinnern. Social Media, HTML, CSS, später Ruby und viel Neugier auf den Rest. Drei Jahre später legen die Code Girls Natalie Sontopski und Julia Hoffmann einen angenehm leichtgewichtigen Einstieg in die Welt der Programmierung vor.

Die beiden Autorinnen nehmen den Leser bei der Hand und erklären mit Verve dass man (wie auch ich) eine Mathe-Niete sein kann und trotzdem ein passabler Programmierer, dass Programmiersprachen ähnlich viele Geschmacksfacetten haben wie die irdischen Variationen von Spagetti mit Tomatensoße und dass C Programmierer harte Kerle sind. Da sich mindestens 50% dieses Blogs mit mehr oder weniger obskuren C Programmiertechniken beschäftigt, fühlte ich mich zugegebener  Maßen bei letztem Punkt gebauchpinselt.

Außerdem leistet das Buch einen wichtigen Beitrag zur Idolbildung in der Geschichte bedeutender Programmier-Veteranen. Ada Lovelace, Grace Hopper (It's easier to ask forgiveness than it is to get permission) und andere bekommen extra Seiten gewidmet. Bravo. Im Pop wird fleißig zitiert und referenziert. Die dritte Generation von Joy Division T-Shirt Trägern bevölkert nun die Indie-Clubs. Höchste Zeit dass auch wir Nerds unsere Helden auf der Brust tragen, Beispiel gefällig?

Bildquelle

Und zu guter Letzt: Es handelt sich um ein schönes, aufwendig gedrucktes Buch. Wer will seinen Liebsten auch schon einen USB-Stick mit einer epub-Datei schenken? Vielleicht noch mit einem animierten GIF als Glückwunschkarte.

Es gibt Dinge die kann man nicht digitalisieren. Ein schönes Buch gehört dazu. (Bildquelle)

Fazit: Falls ihr Partner, Freunde oder Verwandte habt die die Welt in der ihr lebt faszinierend finden aber eigentlich nix davon verstehen: We Love Code! ist ein empfehlenswerter Einstieg, am Besten direkt vom Verlag gekauft.

Montag, 4. April 2016

Avoiding Temporal Coupling - Part 1/2

Every now and then we try to watch Uncle Bobs cleancoders videos. In episode 4, "Function Structure" the issue of temporal coupling is discussed. Temporal coupling is something we encounter quite often: to work with a database you first need to connect to the database. Next you do your work with the database and as the last step you disconnect. The same applies to working with a file: first you open it, then you perform your actions on the file handle/ object and when your done you close it.

The order of this actions is important - you can't call the database disconnect method before you call the connect method. Also, those temporal couplings are often hidden in the background. Quite often some global init method created this database connection your are using for you, at least this is what you believe. When shutting down the application you are hoping that there is another magic method which closes the connection.

In order to deal better with temporal coupling Uncle Bob suggests a technique called "passing a block". The idea is to allocate and to release resources at the point where you need it. The following pseudo code illustrates this approach:
withRessource(ressource, command):
    allocate(ressource)
    command(ressource)
    release(ressource)
Python supports this pattern out of the box with its context manager . Also Java 7 and following has a similar construct.

When looking at the pattern I immediately thought that implementing "passing a block" in plain C isn't too hard.  Function pointers are your friend here. Wait for the second part of this post to see the implementation of withFile, a function which first opens a file, executes your desired actions and then closes this file.