Token导航 LogoToken导航TokenDH.com
研究检索执行命令clawhub未标认证来源可访问clear审计通过

bookforge-library-seam-wrapperBookforge 图书馆缝包纸

Agent Skill

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

总安装

1,273

周安装

51

GitHub Stars

公开资料未说明

下载量

412
OpenClaw

安装说明

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

GitHub

来源数

2

许可证

MIT-0

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

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

请帮我安装这个 Agent Skill:bookforge-library-seam-wrapper(Bookforge 图书馆缝包纸)
来源仓库:https://github.com/quochungto/bookforge-library-seam-wrapper
安装命令:
openclaw skills install bookforge-library-seam-wrapper
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

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

ClawHubOpenClaw
openclaw skills install bookforge-library-seam-wrapper

简介

隔离第三方库依赖以解耦供应商锁定。bookforge-library-seam-wrapper 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

  • 适合希望提升代码可测性与复用性的开发。
  • 创建轻量包装接口屏蔽底层变化冲击。
  • 需同步维护包装层与原始库的版本兼容。
  • 测试时可轻松 mock 替代真实调用。

SKILL.md

name
library-seam-wrapper
description
Isolate third-party library dependencies behind thin wrapper interfaces to break vendor lock-in and enable testing. Use whenever a developer has direct calls to library classes scattered through production code and can't test or swap the library — 'library is killing me', 'vendor lock-in', 'can't mock this library', 'integration tests only for this SDK', 'AWS SDK everywhere', 'Stripe calls in 50 files', 'all API calls', 'wrapping a library', 'adapter for third-party'. Triggers for 'third party', 'SDK', 'library coupling', 'external service', 'API client'.
version
1.0.0
homepage
https://github.com/bookforge-ai/bookforge-skills/tree/main/books/working-effectively-with-legacy-code/skills/library-seam-wrapper
metadata
{"openclaw":{"emoji":"📚","homepage":"https://github.com/bookforge-ai/bookforge-skills"}}
status
draft
source-books
title
Working Effectively with Legacy Code
authors
["Michael C. Feathers"]
chapters
[14, 15]
domain
software-engineering
tags
[legacy-code, refactoring, testing, software-engineering, third-party-libraries, vendor-lock-in]
depends-on
execution
tier
1
mode
full
inputs
description
Codebase with direct library/SDK calls + identification of the library class(es) to wrap
tools-required
[Read, Grep, Edit, Bash]
tools-optional
[Glob]
mcps-required
[]
environment
Codebase (any OO language). Link Substitution fallback requires C/C++ build system.
discovery
goal
Replace direct third-party library calls with wrapped abstractions to enable testing and reduce lock-in.
tasks
audience
roles
[software-engineer, backend-developer, tech-lead]
experience
intermediate
when_to_use
triggers
prerequisites
why
Library wrapping is the object-seam approach; understand the seam model first
not_for
environment
codebase_required
true
codebase_helpful
true
works_offline
true
quality
scores
{with_skill: null, baseline: null, delta: null}
tested_at
null
eval_count
null
assertion_count
10
iterations_needed
null

Library Seam Wrapper

When to Use

Use this skill when production code calls third-party library or SDK classes directly — and those calls are making testing hard or locking the team into a vendor.

Concrete triggers:

  • Tests require the real library (slow, expensive, flaky) because there is no seam to inject a fake.
  • A vendor changed pricing, deprecated an API, or introduced licensing terms the team cannot meet, and switching would require touching dozens of files.
  • The codebase is "mostly API calls" — every class is a thin shell around external service SDKs with no testable seam.
  • A developer says "we'll never need to change this library" — Feathers' warning: that belief can become a self-fulfilling prophecy.

Do not use for in-house or fully-controlled libraries — those can be changed or extended directly without wrapping.


Context and Input Gathering

Before starting, establish:

  1. Library / SDK name and scope — Which library is being wrapped? One class, one module, or the entire SDK surface?
  2. Call-site inventory — Where does the library appear in the codebase? Use Grep to find import statements and class-name usages.
  3. Primary goal — Is the goal to enable test fakes, or to hedge against vendor swap, or both? The goal influences how domain-expressive the wrapper interface needs to be.
  4. Language and OO capability — OO languages use the object-seam approach (interface + adapter). C/C++ without viable interfaces fall back to Link Substitution.
  5. API complexity — A small, stable API is a good candidate for full Skin and Wrap. A large, complicated API is a better candidate for Responsibility-Based Extraction.

Process

Step 1: Inventory direct library calls

Grep the codebase for all import statements and direct usage of the library's class names. Build a call-site map:

Grep pattern: import.*<LibraryPackage> OR new <LibraryClass>( OR <LibraryClass>.

Record:

  • Which files import the library
  • Which class or method names from the library appear in production code
  • Whether usages cluster in a few classes or are scattered across the codebase

A scattered inventory confirms the anti-pattern Feathers names: the library has become structurally embedded, and every call site is a seam that does not exist.

Step 2: Classify wrapping scope

Choose between two strategies based on API complexity and migration risk:

Skin and Wrap (preferred when feasible):

  • Create an interface that mirrors the library's surface you actually use — not its entire API, only the methods your code calls.
  • Implement a production adapter that delegates to the real library.
  • Production code depends only on the interface; zero library imports outside the adapter.
  • Result: complete isolation. The adapter is the only file that touches the library; swapping vendors means writing one new adapter.
  • Good when: the API is relatively small, the team wants total isolation, or there are no tests and the only safe path is wrapping first.

Responsibility-Based Extraction (when the API is large or tangled):

  • Identify the domain responsibility behind each cluster of API calls (e.g., "send a message", "check for mail").
  • Extract those responsibilities into methods on a new class, giving them domain-expressive names.
  • The new class still calls the library, but the consuming code depends on higher-level behavior, not raw API calls.
  • Result: partial isolation. The extracted class is still testable through its interface; some API coupling may remain inside it.
  • Good when: the API is complicated, refactoring tools are available, or an all-at-once rewrite is not safe.

Many teams use both: a thin wrapper for test isolation, and a higher-level responsibility wrapper to give the application a domain language. Feathers: "Skin and wrap is more work, but it can be very useful when we want to isolate ourselves from third-party libraries."

Step 3: Design the wrapper interface

The interface must reflect your use case, not the library's API:

  • Name methods by what they do for your domain: sendTransactionalEmail(recipient, subject, body) not postWithSmtpTransport(SmtpSession, InternetAddress[], MimeMessage).
  • Include only the methods your production code actually calls — do not mirror the whole library.
  • Keep the interface stable against library changes; it should be driven by your domain needs.
  • One interface per logical service (payment, messaging, storage) keeps fakes small and readable.

If the existing code directly instantiates library objects (e.g., new Transport()) that cannot be subclassed — because the library class is final, sealed, or has non-virtual methods — wrapping is the only viable option. Feathers notes: "Sometimes wrapping the singleton is the only choice available to you."

Step 4: Implement the production adapter

Create a class that:

  • Implements the wrapper interface.
  • Holds a reference to the real library object (injected or created internally).
  • Delegates each interface method to the library — no business logic inside the adapter.
  • Is the only file in the codebase that imports the library package.

The adapter is thin by design. If business logic creeps in, extract it to the calling class instead.

Step 5: Migrate call sites incrementally

Replace direct library calls with wrapper calls one file at a time, not all at once:

  1. Start with the class that has the highest call density or the most urgent test need.
  2. Inject the wrapper interface via constructor parameter (preferred) or a setter.
  3. Verify tests pass after each migrated file before moving to the next.
  4. Leave the remaining call sites temporarily; the build stays green throughout.

Incremental migration avoids the "big bang" refactor that breaks the entire build simultaneously.

Step 6: Create a fake implementation for tests

With the interface in place, write a Fake<ServiceName> class that:

  • Implements the wrapper interface.
  • Records calls (captures arguments) or returns scripted responses.
  • Contains no real I/O or network calls.
  • Lives in the test source tree only.

Tests inject the fake; production code uses the real adapter. The interface is the only contract both must satisfy.


Inputs

InputRequiredDescription
Library / SDK nameRequiredThe third-party library to wrap
Codebase accessRequiredSource files containing direct library calls
Call-site inventoryRequiredGrep-generated list of files and usage patterns
Primary goalRequiredTest isolation, vendor swap, or both
LanguageRequiredDetermines whether object seam or Link Substitution applies

Outputs

wrapper-design.md

Documents the wrapping decision for the team:

## Wrapper Design: [Library Name]

**Strategy:** [Skin and Wrap | Responsibility-Based Extraction | Both]
**Rationale:** [1–2 sentences on why this strategy for this API]

**Interface:** [InterfaceName]
**Methods:**
- `methodName(params): ReturnType` — [what it does for the domain]

**Production Adapter:** [AdapterClassName]
**Fake Implementation:** [FakeClassName] (test source only)

**Enabling Point:** [Where the adapter is injected — constructor param, factory, etc.]

**Migration plan:** [List of files to migrate, in order of priority]

Production adapter source file

The implementing class, reviewed for zero business logic and single responsibility.

migration-plan.md

Ordered list of call sites to migrate, one per file, with estimated test coverage gain per step.


Key Principles

  1. "We'll never change this library" is a self-fulfilling prophecy. Every hard-coded library call is a seam that does not exist. The team cannot fake it, cannot swap the vendor, and eventually cannot change it at all. Wrap before the cost becomes prohibitive.
  1. The wrapper interface names the use case, not the library API. PaymentGateway.charge(amount, currency, token) is a domain concept. StripeClient.createPaymentIntent(PaymentIntentCreateParams) is a library detail. The interface protects consuming code from library churn.
  1. Full wrap is better than skin-and-wrap, but skin-and-wrap beats no wrap. Even a thin pass-through interface that mirrors the library API provides the test-injection seam. Improve the domain naming later.
  1. A library-using class can wrap itself. If a class uses a library for a single responsibility, extract that responsibility into an interface on the class itself. The class becomes its own adapter; no new file required.
  1. The adapter is the only file that imports the library. Enforcing this as a convention (via linting or package visibility) prevents the anti-pattern from re-emerging after migration.

Examples

Example A: Stripe SDK scattered across 40 Java files

Situation: A payment service has StripeClient, Charge, and PaymentIntent imports in 40 files. Unit tests hit the real Stripe API with test keys — they are slow and occasionally fail due to network timeouts.

Strategy: Skin and Wrap. The Stripe API surface actually used is small: create a charge, retrieve a charge, refund.

Interface:

interface PaymentGateway {
    ChargeResult charge(Money amount, String token);
    ChargeResult retrieve(String chargeId);
    RefundResult refund(String chargeId, Money amount);
}

Production adapter: StripePaymentGateway implements PaymentGateway — delegates to StripeClient, zero business logic.

Fake: FakePaymentGateway implements PaymentGateway — stores charges in a List, returns scripted responses.

Migration: Inject PaymentGateway via constructor into each service class, replacing direct StripeClient usages one class at a time.

Outcome: 40 files see the interface only. Switching to Braintree means writing one new adapter.


Example C: C codebase with curl calls (Link Substitution fallback)

Situation: A C codebase makes HTTP calls via curl_easy_perform() in 30 files. No OO structure exists; an interface cannot be defined. The team needs to test HTTP-dependent functions without real network calls.

Strategy: Link Substitution (Ch 25 fallback for procedural languages when interface wrapping is not feasible).

Steps:

  1. Identify all calls to curl_easy_perform, curl_easy_setopt, and curl_easy_init.
  2. Write a fake_curl.c that provides stub implementations recording calls in memory.
  3. Adjust the test build (Makefile) to link fake_curl.o instead of the real libcurl.

The production Makefile links the real libcurl. The test Makefile links the fake. Source files are untouched.

Limitation: Link Substitution provides fake isolation but not vendor-swap isolation. A full wrapper in OO code is preferable when feasible.


Example C: iOS app that is 90% CRM API calls

Situation: An iOS CRM client has view controllers calling the vendor SDK directly. 90% of the code is mapping API responses to UI. A product manager wants to evaluate switching vendors.

Strategy: Responsibility-Based Extraction with per-service wrappers.

Decomposition:

  1. Identify the domain responsibilities behind the API calls: contact lookup, activity logging, pipeline management.
  2. Create one protocol (Swift) per responsibility: ContactRepository, ActivityLogger, PipelineService.
  3. Implement production adapters that delegate to the CRM SDK.
  4. View controllers depend only on the protocols.

Outcome: Evaluating a new vendor requires writing three new adapters, not auditing 200 view controller methods. The app's logic is now testable without the CRM SDK.


References

See references/wrapper-design-template.md for a blank wrapper-design.md template and a decision checklist for choosing between Skin and Wrap and Responsibility-Based Extraction.


License

CC-BY-SA-4.0 — derived from *Working Effectively with Legacy Code* by Michael C. Feathers (2004).


Related BookForge Skills

  • seam-type-selector — Prerequisite. Library wrapping is the object-seam approach; this skill helps you confirm it before investing in wrapper design.
  • dependency-breaking-technique-executor — Extract Interface is the primary mechanic behind Step 3 and Step 4 of this skill. Use it when executing the interface extraction in a specific language.
  • legacy-code-symptom-router — Routes legacy code problems to the right skill. If the symptom is "can't test because of a library", it should direct here.

适合场景

01

OpenClaw 用户查找和安装 Skill 时

02

用户想查找某类 Agent Skill 时

03

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

04

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

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

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

能力 4

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

能力 5

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

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

平台分布

OpenClaw

78.6%
按下载量换算324

安全审计

VirusTotal

通过

ClawScan

通过

Static analysis

通过

权限和风险

执行命令

安装流程涉及命令执行,可能通过 openclaw skills install bookforge-library-seam-wrapper 联网下载 Skill 或依赖。用户安装前应确认命令来源、仓库内容和执行环境。

安装前确认

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

来源信息

继续浏览同类 Skills