Seam Type Selector
by @quochungto
Select the right seam type (Preprocessor / Link / Object) for breaking a dependency in legacy code. Use whenever a developer needs to substitute behavior for...
Example A: Java class with a hard-coded dependency (Object Seam)
Situation: A UserService class has a constructor that directly instantiates UserRepository, which opens a database connection. No DI framework. Need to test UserService.findActiveUsers() without a real database.
Classification: Localized (one constructor site). Language: Java (OO).
Recommendation: Object Seam.
Enabling point: The UserService constructor. Introduce a second constructor that accepts a UserRepository parameter (Parameterize Constructor technique). Tests pass in a fake implementation; production code calls the original constructor.
Compatible techniques: Parameterize Constructor, Extract Interface (extract IUserRepository), Subclass and Override Method.
Example B: C++ with pervasive global calls (Link Seam)
Situation: A legacy C++ codebase has 60+ calls to log_event() (a global that writes to a syslog daemon) scattered across 15 files. Running tests triggers syslog writes and slows everything down.
Classification: Pervasive. Language: C++ (compiled, OO).
Recommendation: Link Seam.
Enabling point: The Makefile's link step. Create a test_log_event.o object file with a stub log_event() that records calls in memory. Swap it in via the Makefile for test builds. Source files are untouched.
Compatible techniques: Link-level substitution (Ch 19 procedural pattern), Encapsulate Global References (if later migration to OO is planned).
Example C: Legacy C with pervasive global calls (Preprocessor Seam)
Situation: A C codebase calls db_update(account_no, record) in 40 places across 8 files. There is no OO structure and no link-time substitution capability in the build environment.
Classification: Pervasive. Language: C (procedural β no object seam available).
Recommendation: Preprocessor Seam.
Enabling point: A #define TESTING flag passed to the C compiler (e.g., gcc -DTESTING). A localdefs.h header, included in each source file, defines a macro replacement for db_update under #ifdef TESTING that captures arguments without hitting the database.
Compatible techniques: Text Redefinition (C/C++ specific), C macro preprocessor pattern (Ch 19).
clawhub install bookforge-seam-type-selector