開発環境
- OS X Yosemite - Apple (OS)
- Emacs (CUI)、BBEdit - Bare Bones Software, Inc. (GUI) (Text Editor)
- C (プログラミング言語)
- LLVM/Clang (コンパイラ, Xcode - Apple)
Head First Object-Oriented Analysis and Design: A Brain Friendly Guide to OOA&D (Brett McLaughlin (著)、 Gary Pollice (著)、 David West (著) 、 O'Reilly Media)のChapter 5. Good Design = Flexible Software: Give Your Software a 30-minute Workout、THE GREAT EASE-OF-CHANGE CHALLENGE(No. 3385)をC言語で考えてみる。
THE GREAT EASE-OF-CHANGE CHALLENGE(No. 3385)
コード(BBEdit, Emacs)
find_instrument.c
#include "dict.h"
#include "instrument_spec.h"
#include "inventory.h"
static void initialize_inventory(inventory *in) {
dictionary *properties = dictionary_new();
dictionary_add(properties, "instrument_type", "guitar");
dictionary_add(properties, "builder", "colllings");
dictionary_add(properties, "model", "cj");
dictionary_add(properties, "type", "acoustic");
dictionary_add(properties, "top wood", "indian posewood");
dictionary_add(properties, "back_wood", "sitfas");
instrument_spec *spec = instrument_spec_new(properties);
inventory_add_instrument(in, "11277", 3999.95, spec);
instrument_spec_free(spec);
dictionary_free(properties);
properties = dictionary_new();
dictionary_add(properties, "instrument_type", "guitar");
dictionary_add(properties, "builder", "martin");
dictionary_add(properties, "model", "D");
dictionary_add(properties, "type", "acoustic");
dictionary_add(properties, "num_strings", "6");
dictionary_add(properties, "top_wood", "adirondack");
dictionary_add(properties, "back_wood", "mahogany");
spec = instrument_spec_new(properties);
dictionary_free(properties);
inventory_add_instrument(in, "122784", 5495.95, spec);
instrument_spec_free(spec);
properties = dictionary_new();
dictionary_add(properties, "instrument_type", "guitar");
dictionary_add(properties, "builder", "fender");
dictionary_add(properties, "model", "stratocastor");
dictionary_add(properties, "type", "electric");
dictionary_add(properties, "num_strings", "6");
dictionary_add(properties, "top_wood", "alder");
dictionary_add(properties, "back_wood", "alder");
spec = instrument_spec_new(properties);
dictionary_free(properties);
inventory_add_instrument(in, "V95693", 1499.95, spec);
instrument_spec_free(spec);
properties = dictionary_new();
dictionary_add(properties, "instrument_type", "guitar");
dictionary_add(properties, "builder", "fender");
dictionary_add(properties, "model", "stratocastor");
dictionary_add(properties, "type", "electric");
dictionary_add(properties, "num_strings", "6");
dictionary_add(properties, "top_wood", "alder");
dictionary_add(properties, "back_wood", "alder");
spec = instrument_spec_new(properties);
dictionary_free(properties);
inventory_add_instrument(in, "V9512", 1549.95, spec);
instrument_spec_free(spec);
properties = dictionary_new();
dictionary_add(properties, "instrument_type", "guitar");
dictionary_add(properties, "builder", "gibson");
dictionary_add(properties, "model", "5G");
dictionary_add(properties, "type", "electric");
dictionary_add(properties, "num_strings", "6");
dictionary_add(properties, "top_wood", "mahogany");
dictionary_add(properties, "back_wood", "mahogany");
spec = instrument_spec_new(properties);
dictionary_free(properties);
inventory_add_instrument(in, "82765501", 1890.95, spec);
instrument_spec_free(spec);
properties = dictionary_new();
dictionary_add(properties, "instrument_type", "guitar");
dictionary_add(properties, "builder", "gibson");
dictionary_add(properties, "model", "Les Paul");
dictionary_add(properties, "type", "electric");
dictionary_add(properties, "num_strings", "6");
dictionary_add(properties, "top_wood", "maple");
dictionary_add(properties, "back_wood", "maple");
spec = instrument_spec_new(properties);
inventory_add_instrument(in, "70108276", 52295.95, spec);
instrument_spec_free(spec);
dictionary_free(properties);
properties = dictionary_new();
dictionary_add(properties, "instrument_type", "mandolin");
dictionary_add(properties, "builder", "gibson");
dictionary_add(properties, "model", "F5-G");
dictionary_add(properties, "type", "acoustic");
dictionary_add(properties, "top_wood", "maple");
dictionary_add(properties, "back_wood", "maple");
spec = instrument_spec_new(properties);
dictionary_free(properties);
inventory_add_instrument(in, "9019920", 5495.99, spec);
instrument_spec_free(spec);
properties = dictionary_new();
dictionary_add(properties, "instrument_type", "banjo");
dictionary_add(properties, "builder", "gibson");
dictionary_add(properties, "model", "RB-3");
dictionary_add(properties, "type", "acoustic");
dictionary_add(properties, "num_strings", "5");
dictionary_add(properties, "back_wood", "maple");
spec = instrument_spec_new(properties);
dictionary_free(properties);
inventory_add_instrument(in, "8900231", 2945.95, spec);
instrument_spec_free(spec);
}
int main() {
inventory *inv = inventory_new();
initialize_inventory(inv);
dictionary *properties = dictionary_new();
dictionary_add(properties, "builder", "gibson");
dictionary_add(properties, "back_wood", "maple");
instrument_spec *client_spec = instrument_spec_new(properties);
instrument** instruments = inventory_search(inv, client_spec);
if (instruments[0] != NULL) {
printf("You might like these instruments:\n");
for (int i = 0; instruments[i] != NULL; i++) {
printf("%d\n", i + 1);
instrument_spec_print(instruments[i]->spec);
instrument_print(instruments[i]);
}
} else
printf("Sorry, we have nothing for you.\n");
}
instrument_spec.h.
#pragma once
#include "dict.h"
typedef struct instrument_spec {
dictionary* properties;
void* (*get_property)(struct instrument_spec*, char const *);
int (*matches)(struct instrument_spec*, struct instrument_spec*);
} instrument_spec;
instrument_spec *instrument_spec_new(dictionary *in);
instrument_spec* instrument_spec_copy(instrument_spec *in);
void instrument_spec_free(instrument_spec *in);
void* instrument_spec_get_property(instrument_spec *in, char const * name);
int instrument_spec_matches(instrument_spec *in, instrument_spec *other);
void instrument_spec_print(instrument_spec *in);
instrument_spec.c.
#include <stdlib.h>
#include "instrument_spec.h"
instrument_spec *instrument_spec_new(dictionary *in) {
instrument_spec *out = malloc(sizeof(instrument_spec));
*out = (instrument_spec){.properties=dictionary_copy(in)};
return out;
}
instrument_spec* instrument_spec_copy(instrument_spec *in) {
instrument_spec *out = instrument_spec_new(in->properties);
return out;
}
void instrument_spec_free(instrument_spec *in) {
dictionary_free(in->properties);
free(in);
}
void* instrument_spec_get_property(instrument_spec *in, char const * name) {
if (in->get_property) {
return in->get_property(in, name);
}
return dictionary_find((dictionary const *)&(in->properties), name);
}
int instrument_spec_matches(instrument_spec *in, instrument_spec *other) {
dictionary* kv = other->properties;
keyval** pairs = kv->pairs;
for (int i = 0; i < other->properties->length; i++) {
keyval* kv = pairs[i];
char *key = kv->key;
if (dictionary_find(in->properties, key) != dictionary_not_found &&
strcmp(dictionary_find(in->properties, key), kv->value)) {
return 0;
}
}
return 1;
}
void instrument_spec_print(instrument_spec *in) {
dictionary* kv = in->properties;
keyval** pairs = kv->pairs;
for (int i = 0; i < in->properties->length; i++) {
char *key = pairs[i]->key;
char *value = dictionary_find(in->properties, key);
printf("%s: %s\n", key, value);
}
}
inventory.h
#pragma once
#include "instrument.h"
typedef struct inventory {
instrument **instruments;
int length;
} inventory;
inventory* inventory_new();
void inventory_free(inventory *in);
void inventory_add_instrument(inventory *in, char *serial_number, double price,
instrument_spec* spec);
instrument** inventory_search(inventory *in, instrument_spec *spec);
inventory.c
#include "inventory.h"
#include "instrument.h"
inventory* inventory_new() {
inventory* out = malloc(sizeof(inventory));
*out = (inventory){.instruments=malloc(sizeof(instrument**)),.length=0};
return out;
}
void inventory_free(inventory *in) {
for (int i = 0; i < in->length; i++)
instrument_free(in->instruments[i]);
free(in);
}
void inventory_add_instrument(inventory *in, char *serial_number, double price,
instrument_spec* spec) {
instrument *inst = instrument_new(serial_number, price, spec);
in->length++;
in->instruments = realloc(in->instruments, sizeof(instrument*)*in->length);
in->instruments[in->length - 1] = inst;
}
instrument** inventory_search(inventory *in, instrument_spec *spec) {
instrument** out;
int j = 0;
for (int i = 0; i < in->length; i++) {
if (instrument_spec_matches(spec, in->instruments[i]->spec)) {
out = realloc(out, sizeof(instrument)*(j + 1));
out[j] = in->instruments[i];
j++;
}
}
out = realloc(out, sizeof(instrument)*(j + 1));
out[j] = NULL;
return out;
}
instrument.h
#pragma once
#include "instrument_spec.h"
typedef struct instrument {
char *serial_number;
double price;
instrument_spec *spec;
} instrument;
instrument* instrument_new(char *, double, instrument_spec*);
void instrument_free(instrument *in);
void instrument_print(instrument *in);
instrument.c
#include <stdlib.h>
#include "instrument.h"
instrument* instrument_new(char * serial_number, double price,
instrument_spec *spec) {
instrument *out = malloc(sizeof(instrument));
*out = (instrument){.serial_number=strdup(serial_number),.price=price,
.spec=instrument_spec_copy(spec)};
return out;
}
void instrument_free(instrument *in) {
free(in->serial_number);
free(in);
}
void instrument_print(instrument *in) {
printf("serial number:%s price:%g\n", in->serial_number, in->price);
}
入出力結果(Terminal)
$ make &&./find_instrument clang ... You might like these instruments: 1 instrument_type: guitar builder: gibson model: Les Paul type: electric num_strings: 6 top_wood: maple back_wood: maple serial number:70108276 price:52295.9 2 instrument_type: mandolin builder: gibson model: F5-G type: acoustic top_wood: maple back_wood: maple serial number:9019920 price:5495.99 3 instrument_type: banjo builder: gibson model: RB-3 type: acoustic num_strings: 5 back_wood: maple serial number:8900231 price:2945.95 $
0 コメント:
コメントを投稿