Token导航 LogoToken导航TokenDH.com
研究检索external-serviceclawhub未标认证来源可访问clear审计通过

bookforge-big-refactoring-plannerBookforge 大型重构规划器

Agent Skill

bookforge-big-refactoring-planner 用于查找、检索和筛选相关信息,适合在 OpenClaw 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

4,153

周安装

168

GitHub Stars

公开资料未说明

下载量

1,304
OpenClaw

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

MIT-0

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:bookforge-big-refactoring-planner(Bookforge 大型重构规划器)
来源仓库:https://github.com/quochungto/bookforge-big-refactoring-planner
安装命令:
openclaw skills install bookforge-big-refactoring-planner
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 OpenClaw 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

ClawHubOpenClaw
openclaw skills install bookforge-big-refactoring-planner

简介

用于规划和执行数周到数月的架构级重构。

  • 提供四种命名模式和阶段性重组策略。
  • 支持遗留系统改造和结构优化。bookforge-big-refactoring-planner 属于研究检索类 Skill,可作为该场景下的辅助能力补充。
  • 使用时需明确当前架构痛点和目标。
  • 建议分阶段实施并配合测试保障。

SKILL.md

name
big-refactoring-planner
description
|
version
1.0.0
homepage
https://github.com/bookforge-ai/bookforge-skills/tree/main/books/refactoring/skills/big-refactoring-planner
metadata
{"openclaw":{"emoji":"📚","homepage":"https://github.com/bookforge-ai/bookforge-skills"}}
status
draft
depends-on
source-books
title
Refactoring: Improving the Design of Existing Code
authors
["Martin Fowler", "Kent Beck"]
chapters
[12]
tags
[refactoring, code-quality, legacy-code, architecture]
execution
tier
2
mode
hybrid
inputs
description
The target codebase or subsystem with the architectural-scale structural problem
description
Code-smell-diagnosis report identifying which big refactoring pattern applies, if already run
tools-required
[Read, Grep, Write]
tools-optional
[Bash]
mcps-required
[]
environment
Run inside a project directory. Read source files to identify the structural pattern; write the campaign plan as output.
discovery
goal
Identify which of the four big refactoring patterns applies; select the correct execution variant; produce a campaign plan with milestones, decision points, and interleaving strategy for working alongside ongoing feature development
tasks
audience
roles
["software-developer", "senior-developer", "tech-lead", "architect"]
experience
senior — assumes comfort with object-oriented design and familiarity with individual refactoring moves
triggers
not_for

Big Refactoring Planner

When to Use

You have a structural design problem that cannot be fixed in a single refactoring session. The individual moves — Extract Method, Move Method, Extract Class — are not in question. The challenge is that the problem is architectural: dozens of classes are tangled, or a hierarchy is doing multiple jobs, or procedural logic is spread across a codebase that nominally uses objects. The fix takes weeks to months, not minutes.

This skill is for those campaigns.

Fowler and Beck's core principle: "You refactor not because it is fun but because there are things you expect to be able to do with your programs if you refactor that you just can't do if you don't."

Big refactorings are done for a purpose — specifically because a particular kind of change that the team needs to make is blocked or costly without the restructuring. You are not refactoring for cleanliness. You are refactoring because the architecture is standing in the way of features you need to build.

This skill applies to four named patterns:

PatternCore problemTime scale
Tease Apart InheritanceOne hierarchy doing two independent jobsWeeks
Convert Procedural Design to ObjectsOO language used in procedural styleWeeks to months
Separate Domain from PresentationBusiness logic embedded in GUI classesWeeks
Extract HierarchyGod class with accumulated conditionalsWeeks to months

Prerequisites: Run build-refactoring-test-suite before starting. Big refactorings require a test suite that can catch regressions — the campaign moves incrementally and tests must confirm each step is safe.


Context and Input Gathering

Required Input (ask if missing)

  • The structural problem. Either a code-smell-diagnosis report, a description of where the pain is ("every time we add a new deal type, we have to subclass in two hierarchies"), or a specific class or directory to examine. Why: the four patterns apply to distinct structural situations. Reading the code to confirm the signal is mandatory — big refactorings cannot be planned without inspecting the structure.
  • The purpose of the refactoring. What feature work is blocked? What change is currently too costly? Why: Fowler and Beck are explicit that big refactorings must be done toward a purpose. A campaign without a purpose will be abandoned when pressure mounts. The purpose also determines when to stop — when the blocked change becomes easy, the refactoring has succeeded.

Observable Context (read before asking)

Scan the codebase to identify which structural pattern is present:

Tease Apart Inheritance signals:
  - Subclasses with identical prefix adjectives at every level
    (TabularActiveDeal, TabularPassiveDeal — "Tabular" appears in both branches)
  - Adding a new variation in one dimension requires adding subclasses in every branch
  - Hierarchy depth exceeds 3 levels with cross-cutting concerns

Convert Procedural Design to Objects signals:
  - Classes with only static methods or methods that take data objects as parameters
  - Data classes (fields + accessors, no behavior) that are passed into procedure-style classes
  - Long methods (50+ lines) on classes with few or no instance variables
  - A single "calculator" or "processor" class that takes many different data objects

Separate Domain from Presentation signals:
  - SQL statements inside window, panel, dialog, or view classes
  - Window/form classes over 300 lines with business logic in event handlers
  - Pricing, discount, or calculation logic in GUI event handlers
  - java.sql imports in UI classes; database calls triggered directly by UI events

Extract Hierarchy signals:
  - One class with 10+ boolean flags or type code fields
  - Methods with large switch/case or if-elif chains that check the same flag
  - Adding a new "type" or "mode" requires editing the same class in 5+ methods
  - The class's behavior changes entirely based on a flag set at construction time

Process

Step 1: Confirm the Pattern

ACTION: Read the target code, identify which structural pattern applies, and confirm the diagnosis.

WHY: The four patterns require different remedies. Applying Extract Hierarchy mechanics to a tangled inheritance hierarchy will make it worse. Applying Tease Apart Inheritance to a god class with conditionals will create a hierarchy where subclassing is not the right solution. Correct pattern identification determines whether the campaign succeeds.

Work through the pattern-confirmation checklist:

Tease Apart Inheritance — confirm by answering:

  • Do classes at the same level of the hierarchy share the same adjective prefix? (e.g., Tabular appearing in both ActiveDeal and PassiveDeal branches)
  • Is the hierarchy growing combinatorially? (adding 1 new deal type requires adding 2 new subclasses because presentation styles cross with deal types)
  • Can you draw a two-dimensional grid where one axis is one job and the other axis is the other job?

If yes to all three: this is Tease Apart Inheritance.

Convert Procedural Design to Objects — confirm by answering:

  • Are there classes whose methods all take data objects as their primary parameter (e.g., calculatePrice(Order order) on OrderCalculator)?
  • Are the data objects pure data holders with accessors but no behavior?
  • If you removed the "calculator" class, would its behavior need to live somewhere on the data objects?

If yes: this is Convert Procedural Design to Objects.

Separate Domain from Presentation — confirm by answering:

  • Do GUI or window classes contain SQL, database calls, or business computation?
  • Is business logic triggered directly by UI events?
  • If you wanted to change the pricing algorithm, would you have to open a window class?

If yes: this is Separate Domain from Presentation.

Extract Hierarchy — confirm by answering:

  • Does one class control its behavior almost entirely through flags or type codes checked in conditionals?
  • Are the conditionals static during the object's lifetime — does the type or mode get set at construction and not change?
  • Does adding a new type require editing conditional logic in five or more methods of the same class?

If yes: this is Extract Hierarchy. Then determine the variant:

  • Variant A (unclear variations): You are not sure what all the subclasses should be — discover them one at a time.
  • Variant B (clear variations): The full set of variations is already known upfront — create all subclasses at once.

Step 2: Select Execution Strategy

ACTION: Based on the confirmed pattern, select the execution strategy and identify the key decision points.

WHY: Each pattern has a fixed sequence of moves, but the sequence has decision points that cannot be fully specified in advance — the specific code you encounter will determine which moves apply. Knowing the decision points before starting prevents mid-campaign confusion and ensures the team pushes through when the refactoring gets messy.


Strategy: Tease Apart Inheritance

Problem: One hierarchy is doing two jobs. (Example: Deal hierarchy also captures presentation style, creating TabularActiveDeal, TabularPassiveDeal.)

Goal: Two clean, focused hierarchies connected by delegation.

Sequence:

  1. Draw the two-dimensional grid. Label the axes with the two jobs the hierarchy is doing. Every current subclass should map to a cell in the grid. Cells that are missing reveal gaps in the current implementation. Why: the grid makes the tangling visible and determines how many new classes will be needed in the extracted hierarchy.
  1. Decide which job stays in the original hierarchy. The rule of thumb: leave the job with more code in place — it has less to move. Extract the job with less code into the new hierarchy. Why: moving less code reduces the risk of bugs during extraction. The job that stays will be simplified once the other job is extracted.
  1. Apply Extract Class at the common superclass to create a new class representing the subsidiary job. Add an instance variable to the original superclass to hold a reference to the new object. Why: the new class becomes the root of the extracted hierarchy; the instance variable is the delegation link between the two hierarchies.
  1. Create subclasses of the extracted class — one for each variation of the subsidiary job (e.g., TabularPresentationStyle, SinglePresentationStyle). Initialize the instance variable in each original subclass to the appropriate subclass of the extracted class. Why: until the subclasses are created, the extracted class is just an empty shell with no behavior — this step populates the second hierarchy.
  1. Move behavior into the extracted hierarchy. Apply Move Method (and Move Field where needed) in each original subclass to transfer presentation-related behavior to the corresponding extracted subclass. Why: behavior must follow data — the extracted hierarchy is not useful until it carries the code that belongs to it.
  1. Eliminate empty original subclasses. When a subclass has no more code of its own, delete it. Continue until all subclasses are gone from the dimension being extracted. Why: the original hierarchy should now contain only the classes representing the primary job; the second hierarchy handles the subsidiary job entirely through delegation.
  1. Look for further simplification. After the hierarchies are separated, each can often be simplified further with Pull Up Method or Pull Up Field — logic that was previously tangled may now be clearly common to all subclasses. Why: separation frequently reveals that what appeared to be variation was actually duplication.

Key decision point: Which job stays? Lean toward leaving the job with more code in place. If the code is evenly split, choose the job that is semantically primary — the job that gives the class its name.


Strategy: Convert Procedural Design to Objects

Problem: An object-oriented language is being used in a procedural style. Behavior is concentrated in procedure classes; data is concentrated in data-holder classes with no behavior.

Goal: Behavior distributed into the data objects where it belongs.

Sequence:

  1. Turn each record type into a dumb data object with accessors. If you have a relational database, create a class for each table with accessor methods. Why: the data classes are the correct eventual home for the behavior that currently lives in procedure classes. They must exist before behavior can move into them.
  1. Concentrate all procedural code into a single class. If it is scattered across multiple procedure classes, consolidate. Make the class a singleton or make its methods static to allow easy invocation during the transition. Why: having all procedural code in one place makes it easier to track progress and apply Extract Method systematically. This is a temporary state — the goal is to empty this class.
  1. Apply Extract Method to each long procedure to break it into smaller named operations. Immediately follow with Move Method to move each extracted operation to the data class whose data it primarily uses. Why: Extract Method creates handles on behavior units; Move Method is the act of distributing those units to their natural home. The procedure class shrinks with each Move Method applied.
  1. Continue until the procedure class is empty. If the original class was a purely procedural class, delete it — this is a sign the refactoring is complete. Why: an empty procedure class is the evidence that behavior has been fully distributed. If the class cannot be deleted, some behavior genuinely has no home and a new class may need to be created.

Key decision point: What to do when a method uses data from multiple record types equally. Move Method to the record type it uses most; extract the portions that use other records into separate methods that can be moved to those records.


Strategy: Separate Domain from Presentation

Problem: GUI classes contain domain logic. Business rules, SQL queries, and calculations are embedded in window or event handler classes.

Goal: Clean separation where GUI classes handle only presentation and domain classes carry all business logic.

Sequence:

  1. Create a domain class for each window. If a window displays grid data, also create a class for the rows in the grid. Link the domain class to the window class via a reference field. Why: the domain class is the eventual home for all business logic currently in the window. It must exist before any logic can be moved.
  1. Examine each field and data element in the window. Classify each one into one of three categories:

- *Pure GUI only (not used in domain logic):* Leave it on the window. - *Domain data not displayed in the GUI:* Move Field directly to the domain class using Move Field. Why: non-displayed domain data has no presentation dependency and can be moved immediately with low risk. - *Domain data that is also displayed in the GUI:* Use Duplicate Observed Data — create a corresponding field on the domain class with synchronization logic. Why: these fields cannot be moved directly because the GUI needs them; duplication with sync is the safe intermediate step before the GUI can be updated to reference the domain object's field instead.

  1. Examine the logic in the window class. Classify each logical operation:

- *Pure presentation logic:* Leave it in the window. - *Domain logic:* Apply Extract Method to isolate it, then Move Method to transfer it to the domain class. - *Mixed presentation and domain logic:* Apply Extract Method to separate the domain portion, then Move Method for the domain portion; leave the presentation portion in the window.

  1. Target SQL statements specifically. Drive SQL statements and database logic toward the domain class. Moving SQL imports away from the window class is a useful completion signal — when the window class no longer imports java.sql (or equivalent), the separation is largely complete. Why: SQL in a window class is the clearest signal of domain logic in the wrong place; its removal confirms the domain class is carrying its responsibilities.
  1. Stop when risk is addressed. The resulting domain classes will not be perfectly factored — they will hold the right logic but may need further refactoring (Data Clumps, Feature Envy). Stop the Separate Domain from Presentation campaign once the primary risk is eliminated. If the risk was the mixing of presentation and domain logic, that risk is gone when the separation is clean. Further refactoring of the domain classes is a separate, smaller campaign. Why: trying to fully factor the domain classes simultaneously with the separation campaign overextends the scope and increases the risk of abandonment.

Key decision point: What to do with data that is both displayed and used in domain logic. Always use Duplicate Observed Data as the intermediate step. Direct Move Field will break the GUI. Accept the duplication temporarily — it is easier to eliminate once the logic is clearly in the domain class.


Strategy: Extract Hierarchy

Problem: A single class is doing too much, controlled by flags or type codes, with behavior that varies entirely based on those flags.

Prerequisite check: The conditional logic must be static during the object's lifetime. If the flags can change after construction, apply Extract Class first to create a separate object for the varying aspect before applying Extract Hierarchy. Why: Extract Hierarchy uses subclasses to represent variations. Subclass membership cannot change after instantiation — if a flag changes at runtime, the variation cannot be a subclass.

Variant A — Unclear variations (discover one at a time):

  1. Identify one recurring variation in the conditional logic. Look for a flag or condition that recurs across multiple methods of the class. Why: starting with one variation keeps the scope manageable and prevents the campaign from becoming paralyzing.
  1. Create a subclass for that variation. Apply Replace Constructor with Factory Method on the original class so that clients receive a subclass instance when the variation applies. Why: the factory method is necessary because constructors cannot return subclass instances; it also gives the campaign a controlled entry point for the new subclass.
  1. Copy conditional methods to the subclass. For each method in the original class that has conditional logic based on the variation, copy the method to the subclass and simplify it — remove the branches that cannot apply to this subclass. Use Extract Method in the superclass if needed to isolate the conditional from the unconditional parts. Why: copying rather than moving allows the original class to continue working for all other variations while the subclass is being built.
  1. Continue isolating variations. Pick the next variation, create the next subclass, repeat. Continue until the original class's conditional methods can be declared abstract — all variations are now handled by subclasses. Why: each new subclass removes one variation from the superclass; when the superclass has no remaining conditional logic for a method, that method becomes abstract.
  1. Delete superclass method bodies when all subclasses override them. Make the superclass declarations abstract. Why: an abstract superclass with no concrete implementations is the evidence that the hierarchy is complete.

Variant B — Clear variations (create all subclasses at once):

  1. Create a subclass for each known variation. Apply Replace Constructor with Factory Method to return the appropriate subclass for each variation.
  1. For each method with conditional logic, apply Replace Conditional with Polymorphism. If the whole method varies, move it in full to each subclass. If only part of the method varies, apply Extract Method first to isolate the varying part, then move the extracted method. Why: Replace Conditional with Polymorphism is the terminal move — it eliminates the conditional by making each subclass responsible for its own case.

Key decision point: Which variant to use. Use Variant A when you are unsure how many variations exist or the existing conditional logic is inconsistent. Use Variant B when the full set of variations is well-understood and each variation is consistently represented in the conditional logic.


Step 3: Build the Campaign Plan

ACTION: Produce a phased campaign plan the team can execute over weeks or months.

WHY: Big refactorings that are not planned as campaigns get abandoned. The team hits a messy intermediate state, feature pressure mounts, and the refactoring is frozen half-done — a state that is worse than the starting point. A campaign plan with explicit milestones and interleaving rules allows the team to make progress every day without disrupting feature delivery.

Campaign plan structure:

# [Pattern Name] Campaign Plan — [Target Class/System]

## Purpose
[The specific feature or change that is currently blocked. Why this refactoring now.]

## Pattern
[Selected pattern and variant, with one-sentence rationale for the selection]

## Team Alignment Required
Big refactorings require shared awareness. Every developer working in the affected
area must know:
  1. This refactoring is "in play"
  2. Which classes are being restructured
  3. How to continue the refactoring when adding new code (new code goes into the
     new structure, not the old one)

[List the classes and files "in play" for this campaign]

## Milestones

### Milestone 1: [Name] — [Estimated: N days]
Goal: [What structural state the code is in at the end of this milestone]
Steps:
  1. [Specific move to apply]
  2. [Specific move to apply]
  ...
Done when: [Specific, observable condition — e.g., "TabularPresentationStyle class exists
  and holds all tabular layout methods"]

### Milestone 2: [Name] — [Estimated: N days]
[...]

## Interleaving Rules
- Refactoring steps happen during feature work, not in a dedicated freeze.
- Each milestone step is small enough to complete between feature commits.
- New features that touch the affected area use the new structure, not the old.
- Do not skip milestones to reach the end state — intermediate states must compile
  and pass all tests.

## Decision Points
[List the key decisions that cannot be made until the code is read at that milestone:
  e.g., "At Milestone 2: decide which job stays in the original hierarchy based on
  line count of each dimension"]

## Stopping Condition
[The specific observable state that means the refactoring is done enough:
  e.g., "When OrderWindow no longer imports java.sql"]
[The specific feature or change that was blocked must now be easy to make]

Step 4: Identify Interleaving Strategy

ACTION: Establish the rules for how the campaign runs alongside feature development.

WHY: "Refactoring not because it is fun but because there are things you expect to do with your programs" — Fowler and Beck. Big refactorings must coexist with feature delivery. The alternative — a two-month code freeze to refactor — is not available in production systems. The nibble-at-the-edges approach is the only viable one.

Interleaving rules (apply to every big refactoring campaign):

  1. Refactor to a purpose, not for cleanliness. The campaign starts because a specific feature or change is blocked. Every step of the campaign should move toward making that feature easier. If a step does not contribute to that goal, question whether it is necessary.
  1. Nibble at the edges. Each time a developer touches an affected file for feature work, they apply the next step of the refactoring. The refactoring rides along with feature development — it does not block it. A little today, a little tomorrow.
  1. Do as much as needed to achieve the real task. You do not have to complete the entire campaign before shipping the feature. You have to complete enough of the campaign that the feature becomes easy to add. Stop when the purpose is achieved.
  1. Never leave tests failing overnight. Each step of the campaign must leave the codebase in a state where all tests pass. An intermediate state with failing tests is a blocker for the whole team. The campaign must be executed in safe steps, each verifiable by the test suite.
  1. New code follows the new structure. When adding new features in the affected area during the campaign, use the new structure (the extracted class, the new hierarchy, the domain class) — not the old one. This prevents the old structure from growing while the campaign is in progress.

Step 5: Define the Stopping Condition

ACTION: Establish when the campaign is done and communicate it to the team.

WHY: Big refactorings without a stopping condition run forever or collapse under pressure. The stopping condition is the purpose stated in terms of observable code state. It is the answer to "how will we know when we are done?"

Stopping condition by pattern:

  • Tease Apart Inheritance: Done when the two hierarchies are fully separated, each class in the original hierarchy has a single job, and adding a new variation in one dimension does not require adding subclasses in the other.
  • Convert Procedural Design to Objects: Done when the procedure class is empty or deleted, and all behavior lives in the data objects. (Optional secondary: when the data objects no longer need to be passed as parameters because they know how to perform their own operations.)
  • Separate Domain from Presentation: Done when the window class contains no SQL, no database calls, and no business computation — only display logic and event routing. The domain class handles all business logic. (Observable signal: the window class no longer imports database libraries.)
  • Extract Hierarchy: Done when the original god class is abstract, each variation is a subclass, and adding a new variation requires adding only one new subclass with its own implementations — not editing any existing class.

Key Principles

1. Big refactorings are purposeful, not cosmetic. The motivation for a big refactoring is always a specific blocked capability. "The code is messy" is not sufficient motivation — a campaign that long will be abandoned. "We cannot add a new billing scheme without editing conditional logic in twelve methods of BillingScheme" is a sufficient motivation. The purpose drives the campaign and defines when it is complete.

2. Steps cannot be fully specified in advance. Unlike the individual refactoring moves in Chapters 6-11, the steps of a big refactoring emerge as you do it. The pattern provides the strategy; the code provides the specifics. The plan must include decision points — places where you explicitly pause to assess the code and decide the next move based on what you find.

3. Team agreement is mandatory. A big refactoring affects every developer working in the area. If one developer is teasing apart a hierarchy while another is subclassing the old tangled one, the campaign moves backward. Every developer must know that the refactoring is "in play" and must use the new structure when writing new code.

4. Intermediate states are dangerous — tests must pass at every step. The period between starting and finishing a big refactoring is the most dangerous time. The code is in a partially restructured state. Without a test suite that passes after each step, the team cannot detect regressions. Run build-refactoring-test-suite before starting any campaign.

5. Accumulation is the enemy. Fowler and Beck: "Accumulation of half-understood design decisions eventually chokes a program as a water weed chokes a canal." Big refactorings address accumulated design debt. They are not optional maintenance — they are necessary for the system to remain changeable.


Examples

Example 1: Tease Apart Inheritance — Deal Hierarchy

Situation: A codebase has a Deal hierarchy with subclasses ActiveDeal, PassiveDeal, TabularActiveDeal, and TabularPassiveDeal. Every time a new deal type is added, tabular and non-tabular subclasses must both be added. Every time a new presentation style is added, active and passive subclasses must both be added. The team needs to add a chart-based presentation style.

Pattern confirmed: Tease Apart Inheritance — same adjective prefix ("Tabular") appears in both branches; the hierarchy is growing combinatorially.

Two-dimensional grid:

             | Active Deal | Passive Deal |
-------------|-------------|--------------|
(single)     |      X      |      X       |
Tabular      |      X      |      X       |

Decision — which job stays: Deal type (Active/Passive) has more code; presentation style (single/tabular) has less. Extract presentation style.

Campaign milestones:

Milestone 1 (Day 1-2): Apply Extract Class at Deal superclass — create PresentationStyle. Add presentation instance variable to Deal. Tests pass.

Milestone 2 (Day 3-5): Create TabularPresentationStyle and SinglePresentationStyle subclasses of PresentationStyle. Initialize presentation in TabularActiveDeal and TabularPassiveDeal constructors to TabularPresentationStyle. Tests pass.

Milestone 3 (Day 6-10): Apply Move Method in each tabular subclass — move presentation-related methods to TabularPresentationStyle. When a subclass is empty, delete it. Apply Move Method in single subclasses similarly. Tests pass after each deletion.

Milestone 4 (Day 11-12): Apply Pull Up Method/Field to simplify each hierarchy now that they are separated. Tests pass.

Stopping condition: TabularActiveDeal and TabularPassiveDeal are deleted. Adding ChartPresentationStyle requires only one new class.


Example 2: Separate Domain from Presentation — Order Window

Situation: An OrderWindow class (400 lines) handles all GUI rendering and also contains SQL queries for fetching product prices, customer discount calculations, and order total computation. The team cannot unit test pricing logic because it is embedded in GUI event handlers.

Pattern confirmed: Separate Domain from Presentation — SQL statements in a window class, business calculation in event handlers.

Purpose: Make pricing logic unit-testable without a running GUI.

Campaign milestones:

Milestone 1 (Day 1): Create Order domain class linked from OrderWindow. Create OrderLine for grid rows. Tests pass (no behavior moved yet).

Milestone 2 (Day 2-5): Examine each field. customerCodes field is not displayed — apply Move Field directly to Order. Display fields (customerName, amount) — apply Duplicate Observed Data: add mirrored fields to Order with sync. Tests pass.

Milestone 3 (Day 6-15): Apply Extract Method to isolate SQL calls and pricing calculations in OrderWindow. Apply Move Method to transfer each extracted operation to Order. Drive all SQL toward Order. Tests pass after each move.

Observable stopping signal: OrderWindow no longer imports java.sql. Pricing methods exist on Order and can be unit tested without instantiating the GUI.


Example 3: Extract Hierarchy — Billing Scheme (Variant A)

Situation: BillingScheme has flags for disability status, lifeline status, and business type. Every method contains conditional logic checking these flags. Adding a new billing category requires editing conditional logic in eight methods.

Pattern confirmed: Extract Hierarchy, Variant A — variations not fully clear upfront; flags static during object lifetime.

First variation picked: disability scheme.

Campaign milestones:

Milestone 1: Apply Replace Constructor with Factory Method on BillingScheme. Create DisabilityBillingScheme subclass. Factory method returns DisabilityBillingScheme when disability flag is set. Tests pass.

Milestone 2: Copy createBill to DisabilityBillingScheme. Simplify — remove branches that check disabilityScheme() since the subclass is always in disability context. Tests pass.

Milestone 3: Continue for other methods with disability conditionals. Pick next variation (lifeline). Create LifelineBillingScheme. Repeat. Tests pass after each subclass iteration.

Milestone 4: When all variations are subclassed, declare BillingScheme abstract. Delete conditional method bodies from the superclass. Tests pass.

Stopping condition: Adding a new billing category requires creating one new subclass of BillingScheme — no edits to existing classes.


References

FileContentsWhen to read
references/big-refactoring-patterns.mdFull mechanics for all four patterns with decision tables and edge casesStep 2 — selecting execution strategy

Related skills:

  • code-smell-diagnosis — run first to identify which pattern applies (Parallel Inheritance Hierarchies, Data Class, or Large Class god class)
  • build-refactoring-test-suite — run before starting any campaign to establish the safety net
  • method-decomposition-refactoring — for the Extract Method and Move Method steps within the campaign
  • conditional-simplification-strategy — for the Replace Conditional with Polymorphism steps in Extract Hierarchy

License

This skill is licensed under CC-BY-SA-4.0. Source: BookForge — Refactoring: Improving the Design of Existing Code by Martin Fowler and Kent Beck.

Related BookForge Skills

Install related skills from ClawhHub:

  • clawhub install bookforge-code-smell-diagnosis
  • clawhub install bookforge-build-refactoring-test-suite
  • clawhub install bookforge-method-decomposition-refactoring
  • clawhub install bookforge-conditional-simplification-strategy

Or install the full book set from GitHub: bookforge-skills

适合场景

01

OpenClaw 用户查找和安装 Skill 时

02

用户想查找某类 Agent Skill 时

03

需要根据任务场景推荐可安装能力包时

04

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

OpenClaw

94.99%
按下载量换算1,239

安全审计

VirusTotal

通过

ClawScan

通过

Static analysis

通过

权限和风险

external-service

该 Skill 可能调用第三方服务、云服务或外部模型 API,使用前需要确认账号、额度、数据发送范围和服务条款。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills