Appaserver's Development Methodology

Functional declarative programming provides both air-tight execution and algorithm leverage. However, Appaserver is written in C -- an imperative programming language. To bridge the gap, you can approach functional programming in C by creating objects and operations, but omitting variables. The goal is to write C code that reads like a rosetta stone between the CPU and the human.

To develop this skill, follow Myer's * discipline which ranked the idea of module cohesion and module coupling. Module cohesion is the degree of interaction within a model. Module coupling is the degree of interaction between modules.

Cohesion

The quality of a module's function determines the level of cohesion. From worst to best, here are the levels of cohesion:

  1. Coincidental Cohesion is a module that performs two or more unrelated functions. Evidence of this occurs when a function name cannot be defined.
  2. Logical Cohesion is a module that has available a series of functions, but only one of the functions is executed. This is the result of the case statement. Myers contends that this degrades readability, resulting in having to inspect the function to determine what is going to happen.
  3. Temporal Cohesion is a module that performs a series of functions because it's time to. This usually occurs at the beginning of the algorithm, like calling the function perform_initialization().
  4. Procedural Cohesion is a module that performs multiple functions, but only loosely related. An example would be the function read_part_number_and_update_employee_record(), where the employee record has no need for the part number.
  5. Communicational Cohesion is a module that performs multiple functions, but closely related. An example would be the function read_part_number_and_update_sales_record(), where the sales record would need the part number.
  6. Informational Cohesion is a module that performs multiple functions, and each function has its own entry point. However, all of the functions work on shared variables. The C++ class structure works at this level.
  7. Functional Cohesion is a module that performs exactly one function. In the case of a module having multiple functions, then each function has its own entry point and works only on local variables. The goal is to be able to reuse the function in any context. As this ideal is achieved, imperative languages will execute as robustly as declarative languages.

Coupling

Modules interact with each other via function calls, passing information back and forth. The degree of information passing sets the level of coupling. From worst to best, here are the levels of coupling:

  1. Content Coupling is when a function modifies a variable local to another function.
  2. Common Coupling is when a function modifies a global variable.
  3. Control Coupling is when a function tells another function where to go. Difficulty occurs because the modules are no longer independent of each other.
  4. Stamp Coupling is when a function receives an entire structure as a parameter. This is how the FILE Abstract Data Type (ADT) behaves. Whereas stamp coupling saves typing, flexibility is lost.
  5. Data Coupling is when each data element is presented in the parameter listing individually. This allows for greatest flexibility and readability.

The ideal function should have only input parameters and return a single value. However, for CPU efficiency, sometimes it is necessary to return multiple values. If multiple return values are necessary, pass the addresses of the variables to the function starting at the first parameter position.

Developers of Appaserver attempt to achieve functional cohesion and data coupling by constructing ADTs. Each object is represented with a data structure, and all of the corresponding operations are contained in the same source file.

The syntax for each operation is either:

Datatype *ClassName_Verb( parameter list );

Or

Datatype *ClassName[_OptionalContext]_Datatype( parameter list );

For example:

/* firm.h */
/* ------ */
#ifndef FIRM_H
#define FIRM_H

typedef struct
{
	char *firm_name;
	/* Firm's other attributes */
	int firm_zip_code;
} FIRM;

/* Operations */
/* ---------- */
FIRM *firm_new(			char *firm_name,
				int firm_zip_code );
double firm_distance_miles_double(
				int firm_zip_code,
				int residential_zip_code );
#endif

/* firm.c */
/* ------ */
#include "stdio.h"
#include "firm.h"

FIRM *firm_new( char *firm_name, int firm_zip_code )
{
	FIRM *firm = (FIRM *)calloc( 1, sizeof( FIRM ) );

	if ( !firm )
	{	
		fprintf(stderr,
		"ERROR in %s/%(): cannot allocate %s bytes of memory.\n",
			__FILE__,
			__FUNCTION__,
			sizeof( FIRM ) );
		exit( 1 );
	}
	firm->firm_name = firm_name;
	firm->firm_zip_code = firm_zip_code;
	return firm;
}

double firm_distance_miles_double(	int firm_zip_code,
					int residential_zip_code )
{
	double miles_double;

	miles_double = /* code to compute distance between two zip codes */
	return miles_double;
}

/* main.c */
/* ------ */
#include "stdio.h"
#include "firm.h"

int main( int argc, char **argv )
{
	FIRM *firm = firm_new_firm( "Acme Retailer", 33014 );

	printf( "Got distance = %lf\n",
		firm_distance_miles_double(
			firm->firm_zip_code,
			95825 ) );
	return 0;
}

* Stephen R. Schach; "Software Engineering"; 1990; pp. 219-233.

* W. P. Stevens, G. J. Myers, and L. L. Constantine; "Structured Design, IBM Systems Journal, Vol. 13"; 1974; pp. 115-139.