I wanted to try experimenting with fluent interface design in the C programming language. That's why I wanted to ask you, Dear Code Review users, comments on the way I have implement this simple employee record interface.
Please note that for maximum simplicity I am resorting to as simple data structures as possible.
#include <stdio.h>
#include <assert.h>
/* if this weren't just an example I'd make a linked list */
#define MAX_EMPLOYEE_COUNT 10
/* global this pointer, there is no way around this */
void* this;
typedef struct Employee {
struct Employee* (*set_salary)(int);
struct Employee* (*set_employee_id)(int);
char* name;
int salary;
int employee_id;
} Employee;
Employee* do_set_salary(int s)
{
((Employee*)this)->salary = s;
return this;
}
Employee* do_set_employee_id(int id)
{
((Employee*)this)->employee_id = id;
return this;
}
typedef struct Record {
Employee* (*add_employee)(char*);
Employee employees[MAX_EMPLOYEE_COUNT];
int cnt;
} Record;
Employee* do_add_employee(char *n)
{
Record* this_record = (Record*)this;
assert(this_record->cnt < MAX_EMPLOYEE_COUNT);
this_record->employees[this_record->cnt].set_salary = do_set_salary;
this_record->employees[this_record->cnt].set_employee_id =
do_set_employee_id;
this_record->employees[this_record->cnt].name = n;
this = &this_record->employees[this_record->cnt];
this_record->cnt++;
return this;
}
void init_record(Record* r)
{
r->cnt = 0;
r->add_employee = do_add_employee;
}
Record* edit(Record* r)
{
this = r;
return r;
}
void print_record(Record* r)
{
int i;
for (i = 0; i < r->cnt; i++) {
printf("%s, salary %d, id %d\n",
r->employees[i].name,
r->employees[i].salary,
r->employees[i].employee_id);
}
}
int main(void)
{
Record record;
init_record(&record);
/* behold, fluent interface design! */
edit(&record)->
add_employee("Alice")->
set_salary(1500)->
set_employee_id(10201);
edit(&record)->
add_employee("Bob")->
set_salary(2000)->
set_employee_id(10202);
print_record(&record);
return 0;
}
add
,set
, etc.) , or turns it into something more "human" (with
,having
, etc.) One of the points is to make it sound "right". \$\endgroup\$