Parameterize Method: One Juice Recipe with a Size Input
Learn the Parameterize Method refactoring with a juice stall story, TypeScript and C# examples, safe step-by-step mechanics, and the seesaw rule that pairs it with Replace Parameter with Explicit Methods.
🧃 The Story of the Three Recipe Cards
Meet Kavya, a class nine student from Mysuru. Her uncle, Ravi Anna, runs a small juice stall near the bus stand. Sweet lime, pineapple, watermelon — the stall is famous in the whole lane, and in May the queue stretches past the cobbler's shop.
One summer holiday, Kavya helps at the stall, and on her very first day she finds something funny. Ravi Anna has three recipe cards pinned to the wall, each in his careful round handwriting.
The first card says "How to make SMALL juice": take 200 ml of fruit pulp, add 50 ml of water, one spoon of sugar, four ice cubes, blend, pour, serve with a smile. The second card says "How to make MEDIUM juice": take 300 ml of pulp, add 75 ml of water, one and a half spoons of sugar, six ice cubes, blend, pour, serve with a smile. The third card says "How to make LARGE juice": 400 ml of pulp, 100 ml of water, two spoons of sugar, eight ice cubes, blend, pour, serve with a smile.
Kavya reads all three cards twice. Then she laughs out loud. "Anna, these are not three recipes. This is ONE recipe written three times! Every step is the same. Only the quantities change with the size."
Ravi Anna scratches his head. "But small, medium and large are different drinks, no?"
"No, Anna. The method is the same. Wash, blend, pour, serve — same, same, same. Only one thing changes: the size. Watch." Kavya takes a fresh card and writes: "How to make juice of size S ml: take S of pulp, add a quarter of S as water, sugar in proportion, ice in proportion, blend, pour, serve with a smile." One card. A blank for the size. Done.
Ravi Anna is not convinced yet. "Three cards have worked for ten years, Kavya."
"Have they, Anna? Last month, when the sugar supplier changed and you reduced the sweetness, how many cards did you correct?"
Silence. He had corrected the small and large cards — and forgotten the medium one. For three whole weeks, every medium juice was a little too sweet, and Ravi Anna could not understand why some customers were making faces. One recipe written three times means one mistake waiting to happen three times.
The best part of Kavya's single card comes a week later. A family from the marriage hall asks for a "family jumbo" — 600 ml. With the old cards, Ravi Anna would have stood there composing a fourth card from scratch. With Kavya's card, he just fills 600 into the blank. No new card. No new mistakes. No fourth thing on the wall to forget during the next sugar change.
This is exactly what happens in code. We write makeSmallJuice(), then copy it to make makeMediumJuice(), then copy again for makeLargeJuice(). Three methods, one idea, and every bug must be fixed three times. The refactoring that fixes this is called Parameterize Method: merge the copies into one method, and let the differing value walk in as a parameter.
Here is how an order flows at the stall once the single card is up. Notice that the customer simply states the size — the size is data travelling with the request, not a separate recipe.
🤔 What is Parameterize Method?
Parameterize Method is the refactoring where you replace several methods that do the same job — differing only by a value baked into their bodies — with one method that accepts that value as a parameter.
The "value" can be anything literal: a number (200 ml, 10%), a string ("small"), a rate, a limit. The key test is this: if you put the method bodies side by side and they match line for line except for that one value, you are looking at one method wearing three name tags.
In Martin Fowler's Refactoring, second edition (2018), this technique appears as Parameterize Function — the book's examples use plain functions — and the catalog at refactoring.com notes that Parameterize Method is its first-edition name. Fowler's classic illustration is a pair of salary functions for a ten percent raise and a five percent raise that collapse into a single raise function taking the factor as input. Refactoring Guru files the same technique under Simplifying Method Calls.
How similar were Ravi Anna's three cards, really? Kavya actually counted the lines. Out of every twenty lines of instruction, seventeen were word-for-word identical. Only the quantity lines differed.
When 85 percent of three methods is the same text, you are not maintaining three methods. You are maintaining one method and two photocopies that can silently drift out of date.
Why is merging such a win?
- Duplication dies. One body means one place to fix a bug, one place to add a feature, one place to read.
- The class API shrinks. Three or five or nine methods become one. Less to learn, less to scroll.
- New cases become free. A 600 ml jumbo juice or a 15% raise needs no new code — just a new argument at the call site.
- Drift becomes impossible. The sugar-change bug — fixing two copies and forgetting the third — structurally cannot happen when there is only one copy.
One line to remember: if the bodies are twins and only a value differs, pull the value out and let one method do the work of many. The differing value was always an input in disguise — Parameterize Method simply gives it its rightful seat in the parameter list.
College corner: what Kavya applied is the DRY principle — Don't Repeat Yourself, from Hunt and Thomas's The Pragmatic Programmer. The precise wording matters: every piece of knowledge should have a single authoritative representation in the system. The knowledge here is "how juice is made"; the three cards were three competing representations of it, and the sugar-change bug is the textbook failure mode of violated DRY — representations drifting apart. But note the equally important fine print: DRY is about knowledge, not about lines of text. Two methods that happen to look alike today but encode different business rules (say, a tax formula and a discount formula that are coincidentally both x * 0.1) should NOT be merged, because they will change for different reasons. Merging them couples two unrelated decisions. The test is never "do the lines match?" — it is "is this the same idea written twice?"
There is one warning to keep beside the tip. This refactoring has an exact opposite, Replace Parameter with Explicit Methods, and choosing between the two is a real skill. We will build a full decision table and a quadrant chart for that later in this post. The short version: parameterize when variants differ only by a value; split into explicit methods when variants differ in behaviour.
🚦 When do we need it?
Reach for Parameterize Method when you notice these signs:
- Copy-paste siblings. You see
chargeForHalfKg(),chargeForOneKg(),chargeForTwoKg()and the diff between any two is a single number. That is the textbook trigger. It is really a special case of the Duplicate Code smell — duplication where the copies vary only by a constant. - A new case means a new method. The product team asks for one more size, one more discount band, one more speed level — and your plan is "copy the nearest method and change the number". Stop. Parameterize first; then the new case is just a new argument.
- A fix had to be applied in several places. Last week's bug in the medium-juice method also existed in small and large, and somebody forgot one of them. Triplicated bodies guarantee this will happen again — ask Ravi Anna.
- The class is bloating with near-twins. Ten lookalike methods make a class feel huge even when the real logic is tiny. Merging them shrinks the surface dramatically.
This refactoring also connects to two smells you should know:
- Long Parameter List — be careful here. Parameterize Method adds a parameter. Adding one honest parameter to kill three duplicate methods is a great trade. But if a method keeps gaining flag after flag, you are walking toward this smell, and it may be time for the inverse refactoring instead.
- Data Clumps — sometimes the "one value" you extract turns out to be two or three values that always travel together (pulp ml, water ml, sugar spoons). If so, do not add three loose parameters; bundle them into a small object like
JuiceSize, so the clump travels as one neat parcel.
And know when the answer is no:
- The variants do different things — extra validation in one, a different calculation branch in another, a side effect in a third. Merging them gives you one method full of
if (size === ...)checks. That is worse, not better. - The fixed set of named methods is a feature.
raiseTenPercent()at a call site documents company policy;raiseBy(0.10)invites someone to pass0.45by mistake. If the menu is small, fixed, and policy-like, named methods may be the kinder API.
Here is the whole decision in one picture — keep it pinned next to Kavya's card:
👀 Before and after at a glance
Here is Ravi Anna's stall in TypeScript, exactly as Kavya found it:
// BEFORE: three methods, one idea
class JuiceStall {
makeSmallJuice(fruit: string): Juice {
const pulp = this.blend(fruit, 200);
const water = 200 / 4;
const sugar = 200 / 200; // spoons
const ice = 200 / 50; // cubes
return this.pour(pulp, water, sugar, ice);
}
makeMediumJuice(fruit: string): Juice {
const pulp = this.blend(fruit, 300);
const water = 300 / 4;
const sugar = 300 / 200;
const ice = 300 / 50;
return this.pour(pulp, water, sugar, ice);
}
makeLargeJuice(fruit: string): Juice {
const pulp = this.blend(fruit, 400);
const water = 400 / 4;
const sugar = 400 / 200;
const ice = 400 / 50;
return this.pour(pulp, water, sugar, ice);
}
}Look closely. Every line is identical except the number 200, 300, 400. That number is the size. It is an input pretending to be three method names. Here is the card Kavya wrote:
// AFTER: one method; the size walks in as a parameter
class JuiceStall {
makeJuice(fruit: string, sizeMl: number): Juice {
if (sizeMl <= 0 || sizeMl > 1000) {
throw new Error(`Juice size must be 1-1000 ml, got ${sizeMl}`);
}
const pulp = this.blend(fruit, sizeMl);
const water = sizeMl / 4;
const sugar = sizeMl / 200;
const ice = sizeMl / 50;
return this.pour(pulp, water, sugar, ice);
}
}
// callers: makeJuice("pineapple", 200); makeJuice("watermelon", 600); — jumbo is free!Notice two small kindnesses in the new version. First, a validation guard at the top — the old named methods could never receive a wrong size, so the merged method must defend itself. Second, the parameter is named sizeMl, not s, so call sites still read clearly.
The class structure tells the same story from above. Before, the stall carried three doors; after, one door with a size knob, and the size flows into the Juice it produces:
And here is the same collapse as a flow of bodies merging:
🪜 Step-by-step, the safe way
Never merge by deleting all three methods in one stroke. Refactoring means tiny steps with green tests between each. Picture the codebase moving through clean, named states — never jumping from the first to the last:
Here is the same ladder in words:
- Line up the twins and find the differing value. Put the bodies side by side. Confirm — honestly — that the only difference is the literal. If you find a sneaky extra
ifin one variant, stop and decide whether it belongs in all variants or whether these methods are not twins at all. - Create the new parameterized method, leaving the old ones untouched. Copy one body, replace the literal with the parameter everywhere it appears, and add validation for the new open range.
// Intermediate state: new method exists, old ones still standing
class JuiceStall {
makeJuice(fruit: string, sizeMl: number): Juice { /* shared body using sizeMl */ }
makeSmallJuice(fruit: string): Juice { /* old body, untouched for now */ }
makeMediumJuice(fruit: string): Juice { /* old body, untouched for now */ }
makeLargeJuice(fruit: string): Juice { /* old body, untouched for now */ }
}- Test the new method with each original value.
makeJuice("mango", 200)must produce exactly whatmakeSmallJuice("mango")produced. Do the same for 300 and 400. If you have a test suite, add these as explicit cases. - Turn each old method into a one-line forwarder. This is the magic intermediate step — the old names still work, but the duplication is already gone:
// Intermediate state 2: old methods become thin forwarders
makeSmallJuice(fruit: string): Juice { return this.makeJuice(fruit, 200); }
makeMediumJuice(fruit: string): Juice { return this.makeJuice(fruit, 300); }
makeLargeJuice(fruit: string): Juice { return this.makeJuice(fruit, 400); }- Compile and run all tests. Behaviour must be byte-for-byte unchanged. If a test fails here, the bodies were not true twins — go back to step 1 and look again.
- Migrate callers one by one. Replace
stall.makeSmallJuice("mango")withstall.makeJuice("mango", 200). Run tests after each batch of call sites. - Delete the forwarders once no caller uses them. The class is now one method lighter times three.
The most common slip: the bodies look like twins but one variant has a tiny behavioural difference — a rounding rule, an extra log line, a different error message. If you merge over that difference, you silently change behaviour for some callers. Always diff the bodies mechanically (your editor's compare tool, not your eyes) before step 2, and keep the forwarder stage so tests can catch any drift while both paths still exist.
📦 A bigger real-life example
Kavya's cousin Arjun works at a courier company in Pune. Their billing class grew the same disease, but with five twins instead of three:
// BEFORE: five charge methods that differ only by a weight baked into each
class CourierBilling {
chargeForHalfKg(distanceKm: number): number {
const base = 40;
const perKm = 0.8;
return Math.round(base + distanceKm * perKm * 0.5);
}
chargeForOneKg(distanceKm: number): number {
const base = 40;
const perKm = 0.8;
return Math.round(base + distanceKm * perKm * 1.0);
}
chargeForTwoKg(distanceKm: number): number {
const base = 40;
const perKm = 0.8;
return Math.round(base + distanceKm * perKm * 2.0);
}
chargeForFiveKg(distanceKm: number): number {
const base = 40;
const perKm = 0.8;
return Math.round(base + distanceKm * perKm * 5.0);
}
chargeForTenKg(distanceKm: number): number {
const base = 40;
const perKm = 0.8;
return Math.round(base + distanceKm * perKm * 10.0);
}
}Every body is the same formula. The only difference is the weight: 0.5, 1, 2, 5, 10. And the pain is real: when the base charge moved from 40 to 45 rupees last Diwali season, a developer updated four methods and missed chargeForFiveKg. Customers shipping five kilograms paid the old rate for two weeks before anyone noticed. Ravi Anna's sugar bug, wearing a courier uniform.
After Parameterize Method:
// AFTER: one method; weight is an honest input
class CourierBilling {
private static readonly BASE_CHARGE = 45;
private static readonly RATE_PER_KM = 0.8;
private static readonly MAX_WEIGHT_KG = 25;
chargeFor(weightKg: number, distanceKm: number): number {
if (weightKg <= 0 || weightKg > CourierBilling.MAX_WEIGHT_KG) {
throw new Error(`Weight must be 0-${CourierBilling.MAX_WEIGHT_KG} kg`);
}
return Math.round(
CourierBilling.BASE_CHARGE +
distanceKm * CourierBilling.RATE_PER_KM * weightKg
);
}
}
// chargeFor(0.5, 12); chargeFor(7.3, 12); — any weight in range, no new methodThree things improved at once. The base charge lives in exactly one place, so the Diwali bug can never repeat. The company can now bill a 7.3 kg parcel — the old design simply could not express weights between its five fixed methods. And the class API went from five entries to one.
The maintenance arithmetic is brutal and worth seeing as a chart. Every rate change used to mean five edits, five chances to forget one:
Notice also what we did not do. We did not add a string parameter like chargeFor("half-kg") that the method would switch on. The weight is a genuine number on a continuum, so it travels as a number. If instead the company had three plans — "express", "standard", "economy" — each with different promise dates, different insurance, different routing, those would be different behaviours, and the seesaw would tip toward explicit methods.
College corner: there is a useful theoretical lens here — binding time. In the before code, the weight was bound at compile time, frozen into method names; in the after code, it is bound at call time, supplied as data. Moving a decision to a later binding time always buys flexibility (any weight!) and always costs some static safety (the compiler no longer guarantees the weight is one of five blessed values). That is why the guard clause is not decoration — it is the runtime replacement for the compile-time guarantee you gave up. Mature APIs often split the difference: an open chargeFor(weight) for flexibility, plus a typed enum or named constants for the common sanctioned values. Knowing which guarantees you are trading at which binding time is the difference between refactoring and rearranging.
💻 The same refactoring in C#
The disease and the cure look the same in C#. Here is a salary module before:
// BEFORE
public class Salary
{
private readonly decimal _base;
public Salary(decimal baseAmount) => _base = baseAmount;
public decimal RaiseFivePercent() => _base * 1.05m;
public decimal RaiseTenPercent() => _base * 1.10m;
public decimal RaiseTwentyPercent() => _base * 1.20m;
}And after the merge:
// AFTER
public class Salary
{
private readonly decimal _base;
public Salary(decimal baseAmount) => _base = baseAmount;
public decimal RaiseBy(decimal fraction)
{
if (fraction <= 0m || fraction > 0.5m)
throw new ArgumentOutOfRangeException(nameof(fraction),
"Raise must be between 0 and 50 percent.");
return _base * (1m + fraction);
}
}
// salary.RaiseBy(0.05m); salary.RaiseBy(0.15m); // 15% needed no new methodOne C#-specific kindness: if the company truly allows only a few sanctioned raise levels, you can keep the open method and offer named conveniences as expression-bodied forwarders — public decimal RaiseTenPercent() => RaiseBy(0.10m);. The logic still lives in one place; the names merely document policy. That hybrid is often the most readable endpoint of this refactoring.
🛠️ IDE support
No IDE has a single button labelled "Parameterize Method", but the building blocks are first-class refactorings in every major tool:
- IntelliJ IDEA / Rider / WebStorm — the Extract Parameter refactoring (Ctrl+Alt+P on Windows/Linux, ⌥⌘P on macOS) does the core move: select the literal inside the method body, extract it as a parameter, and the IDE updates the declaration and every call to pass the old value. JetBrains documents this for Java, Kotlin, C#, and JavaScript/TypeScript. Combine it with Change Signature (Ctrl+F6) when you need to reorder or rename parameters afterwards.
- ReSharper (Visual Studio) — offers Introduce Parameter, which moves an expression from a method implementation to its callers by adding a new parameter and updating all calls in the solution with the matching argument.
- Visual Studio (built-in C# refactorings) and VS Code with the C# extension — provide Change method signature and Introduce parameter quick actions; you can extract the literal into a parameter and then merge the twin methods by hand using the forwarder ladder from this post.
- Safe deletion of the old twins — IntelliJ's Safe Delete and ReSharper's usage search confirm no caller still uses
makeSmallJuicebefore you remove it.
The merging of the bodies is yours to do — the IDE cannot know that three methods are spiritually one. The reliable recipe: run Extract Parameter on one twin, then convert the remaining twins into forwarders, then inline or delete them with the IDE's safe tools.
⚖️ Benefits and risks
| Aspect | Benefit | Risk / Cost |
|---|---|---|
| Duplication | One body to read, fix, and improve | If bodies were not true twins, merging changes behaviour silently |
| Flexibility | Any value in range works with zero new code | Open range admits invalid values the named methods made impossible — add validation |
| API size | Class surface shrinks; less to learn | Named methods like raiseTenPercent() documented intent; raiseBy(0.10) exposes a magic number at call sites |
| Maintenance | A rate change touches one method, not five | The single method now serves all callers; a bug in it breaks everyone at once |
| Evolution | New sizes, weights, rates arrive for free | If future "cases" start needing different logic, the method grows internal conditionals — time for the inverse refactoring |
🎢 The seesaw: Parameterize Method ↔ Replace Parameter with Explicit Methods
These two refactorings are exact inverses, like the two ends of a seesaw. Neither is "the good one". The shape of the variation decides which way to tip:
| Question to ask | Tips toward Parameterize Method | Tips toward Replace Parameter with Explicit Methods |
|---|---|---|
| Do the variants differ only by a value? | Yes — 200 ml vs 300 ml vs 400 ml | No — deposit vs withdraw are different actions |
| Is the value on a smooth continuum? | Yes — any weight, any percent could appear | No — a small fixed menu of discrete cases |
| Does the method body branch on the parameter? | No — the value flows straight into a formula | Yes — a switch picks completely different code paths |
| Do callers pass the value as runtime data? | Yes — the size comes from user input | No — every caller writes a literal like "height" |
| Is the parameter a cryptic flag or code? | No — sizeMl: 300 reads naturally | Yes — doBanking(2) means nothing without a legend |
You can place any group of suspicious methods on a two-axis map. The horizontal axis asks how different the insides are; the vertical axis asks how cryptic the would-be parameter is. Ravi Anna's juice methods sit deep in the parameterize corner:
A practical sign you tipped the wrong way: if your freshly parameterized method immediately needs if (size === "small") { ... } else { ... } inside it, the variants were behaviours, not values — undo and split into explicit methods. And in the other direction: if you find yourself adding a fourth, fifth, sixth explicit method that differ only by a constant, merge them back.
College corner: the seesaw is really the classic tension between DRY and explicitness, and it never fully resolves. Merging maximizes reuse but makes every call site carry a value whose meaning lives elsewhere (raiseBy(0.10) — is 0.10 policy or accident?). Splitting maximizes readability at call sites but multiplies the API and forbids new cases without new code. The professional habit is to treat the current position as provisional: codebases legitimately ride this seesaw multiple times as requirements clarify. A 2010-era payroll system might merge raises into raiseBy(f), then split out applyAnnualIncrement() years later when law gives that one case special audit rules. Refactoring is reversible by design — that is precisely why Fowler catalogs both directions as first-class moves rather than declaring a winner.
🩺 Which smells does it cure?
| Smell | How Parameterize Method helps |
|---|---|
| Duplicate Code | The primary target — near-identical bodies collapse into one |
| Large Class | Five lookalike methods become one; the class surface shrinks |
| Long Parameter List | Watch direction: this refactoring adds a parameter, so apply with care; if extracted values clump together, bundle them into one object |
| Data Clumps | When the differing "value" is really 2–3 values travelling together, introduce a small parameter object instead of loose parameters |
| Shotgun Surgery | A rate change no longer needs edits in five places |
🧠 The whole idea in one mindmap
📝 Quick revision box
+================ PARAMETERIZE METHOD ================+
| |
| SMELL : makeSmallJuice / makeMediumJuice / |
| makeLargeJuice - twin bodies, one value |
| differs (200 / 300 / 400) |
| |
| MOVE : one method, value becomes a parameter |
| makeJuice(fruit, sizeMl) |
| |
| LADDER: 1 diff the twins 2 write merged method |
| 3 test each old literal 4 old methods -> |
| forwarders 5 migrate callers 6 delete |
| |
| GUARD : open range needs validation at the top |
| |
| SEESAW: value continuum -> parameterize |
| behaviour switch -> explicit methods |
| (exact inverse refactoring!) |
+======================================================+🏋️ Practice exercise
A school canteen system has these methods — try the refactoring yourself:
class CanteenBilling {
priceForSamosaPlate(qty: number): number {
return qty * 15 + (qty >= 4 ? -5 : 0); // bulk discount
}
priceForIdliPlate(qty: number): number {
return qty * 30 + (qty >= 4 ? -5 : 0);
}
priceForDosaPlate(qty: number): number {
return qty * 45 + (qty >= 4 ? -5 : 0);
}
}Your tasks:
- Diff the three bodies. Confirm the only difference is the unit price (15, 30, 45).
- Write
priceFor(unitPrice: number, qty: number)with the shared body, plus validation thatunitPriceis positive. - Turn the three old methods into one-line forwarders and check (by hand or with tests) that every old call gives the same total.
- Migrate the callers, delete the forwarders.
- Stretch question: the canteen adds a rule — dosa plates get NO bulk discount on Saturdays. Does that rule change your answer? (Hint: now one variant behaves differently. Think about which way the seesaw tips, and whether
priceForshould grow anif, or whether dosa deserves its own method again.) - Bonus: the unit prices 15/30/45 still live at the call sites as magic numbers. Where would you keep a menu of item prices so that callers pass an item name and the price is looked up in one place? (That idea — letting the method fetch a value itself — is the next-door refactoring Replace Parameter with Method Call.)
- Chart it: draw your own version of Figure 10 and place the canteen methods on it. Before the Saturday rule, where do they sit? After the Saturday rule, which direction do they drift, and at what point would they cross into the "split" half?
Frequently asked questions
- What exactly does Parameterize Method do?
- It merges several near-identical methods into one. The methods must differ only by a fixed value hiding inside their bodies — a number, a string, a rate. You pull that value out, make it a parameter, and keep a single shared body. Three recipe cards become one recipe card with a blank to fill in.
- How do I know the methods are similar enough to merge?
- Place the bodies side by side. If they match line for line except for one or two literal values, merge them. If they also differ in steps — extra checks, different branches, different side effects — they are not the same recipe, and forcing them into one method creates a conditional mess instead of removing duplication.
- Is Parameterize Method the opposite of another refactoring?
- Yes. Replace Parameter with Explicit Methods is its exact inverse. Parameterize when variants sit on a smooth value scale, like 5%, 10%, 20%. Go the other way when a parameter is a cryptic switch that picks between genuinely different behaviours. Good code moves back and forth on this seesaw as designs evolve.
- Does this refactoring have a different name in Fowler's second edition?
- The second edition of Refactoring calls it Parameterize Function, because the book's examples use JavaScript functions rather than class methods. The idea is identical, and the catalog at refactoring.com lists Parameterize Method as the alias from the first edition.
- Won't a parameter let callers pass nonsense values?
- It can, and that is the honest cost. makeLargeJuice() could never receive a wrong size; makeJuice(-500) can. So when you parameterize, add validation at the top of the merged method, or use a narrow type like a union of allowed values, so bad inputs fail loudly instead of silently.
Further reading
Related Lessons
Replace Parameter with Explicit Methods: Name Boards Instead of Secret Codes
Learn the Replace Parameter with Explicit Methods refactoring with a bank counter story, TypeScript and Python examples, safe mechanics, and the seesaw rule that pairs it with Parameterize Method.
Replace Parameter with Method Call: Don't Tell the Shopkeeper His Own Prices
Learn the Replace Parameter with Method Call refactoring (Replace Parameter with Query in Fowler's 2nd edition) with a kirana shop story, TypeScript and C# examples, safe mechanics, and the testability fine print.
Preserve Whole Object: Show the Whole ID Card
Learn the Preserve Whole Object refactoring with a school ID card story, TypeScript and C# examples, safe step-by-step mechanics, and an honest look at the coupling cost of passing whole objects.
Long Parameter List: The Chai Order That Took Ten Instructions
Long Parameter List code smell made simple — why methods with too many arguments cause bugs, and how parameter objects make calls short, clear, and safe.