From grimoire
Provides a unified, simplified interface to a complex subsystem, reducing client coupling and hiding internal complexity. Useful for wrapping intricate APIs or libraries.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:apply-facade-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Provide a unified, simplified interface to a complex subsystem, hiding its internal complexity from clients.
Provide a unified, simplified interface to a complex subsystem, hiding its internal complexity from clients.
Adopted by: AWS SDK's high-level clients (S3 Transfer Manager wraps 15+ low-level
S3 API calls behind upload_file() — used by millions of applications), Spring Boot
auto-configuration (a facade over Spring's XML-heavy configuration subsystem), Django's
send_mail() (a facade over smtplib, MIMEText, SMTP, and EmailMessage),
and every OS API (POSIX open() is a facade over filesystem drivers, VFS, inode
resolution, and buffer caches).
Impact: GoF documents that facades reduce the number of objects clients interact with
and simplify the learning curve for subsystems. AWS Transfer Manager's single
upload_file() call replaced a 5-step multipart upload sequence — adoption of S3 for
large files increased dramatically after its introduction.
Why best: Direct use of a complex subsystem forces every client to understand all
subsystem interactions, dependencies, and initialization order. A facade centralizes
that knowledge, reducing client code to the essential operations and isolating subsystem
changes to the facade.
Sources: Gamma et al. (1994) pp. 185–193; AWS S3 Transfer Manager documentation;
Django django.core.mail source
Subsystem: video encoding pipeline
Classes: VideoDecoder, FrameExtractor, AudioExtractor, Encoder, Muxer, FileWriter
Client needs: transcode(input_path, output_path, format)
Clients rarely need all subsystem operations — only the orchestrated result.
class VideoTranscoder:
def __init__(self):
self._decoder = VideoDecoder()
self._audio = AudioExtractor()
self._encoder = Encoder()
self._muxer = Muxer()
self._writer = FileWriter()
def transcode(self, input_path: str, output_path: str, fmt: str) -> None:
video_frames = self._decoder.decode(input_path)
audio_track = self._audio.extract(input_path)
encoded_video = self._encoder.encode(video_frames, fmt)
muxed = self._muxer.mux(encoded_video, audio_track)
self._writer.write(muxed, output_path)
Facade hides complexity but does not seal the subsystem. Clients that need fine-grained
control can still use VideoDecoder, Encoder, etc. directly. The facade is a
convenience, not a lock.
# Wrong — business logic in the facade
def transcode(self, input_path, output_path, fmt):
if not self._billing.is_paid(user_id):
raise BillingError("subscription required")
...
# Right — facade only orchestrates subsystem calls
# Billing belongs in a service layer above the facade
# Good — one facade per subsystem
class VideoFacade: ...
class AudioFacade: ...
class StorageFacade: ...
# Wrong — one mega-facade for everything
class MediaSystemFacade: # does encoding, billing, storage, notifications
...
Facade that delegates to itself recursively. A facade whose methods call other facade methods creates a tangle. Each facade method should call subsystem classes, not other facade methods.
Hiding all subsystem access. If the facade is the only way in, advanced use cases are impossible. Keep subsystem classes public; the facade is a convenience layer, not an access control mechanism.
Treating the facade as a God Object. A facade with 40 methods is just a big class. If the facade grows to cover unrelated subsystems, split it.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireSimplifies complex subsystems using the Facade pattern. Provides a clean, unified interface over multiple subsystems to reduce client coupling.
Generates Facade pattern classes and unit tests for PHP 8.4 to simplify interfaces for complex subsystems like order processing, notifications, or legacy APIs.
Guides extracting interfaces behind abstractions to decouple callers from concrete implementations, improving testability and reducing change impact.