Skip to content

Inverted Control & Structural Governance

Fix the steps, let subclasses fill them in

Builds on Abstract classes and inheritance

Stage 3core2 min read

Each channel here has its own class, and the classes are unrelated. The same steps are copied and pasted into every channel. This causes a lot of repeated code, and no single place controls the shared steps.


1. Understanding the Issue

To send any alert, the code must run the same steps in order: check rate limits, validate the recipient, format the text, write a log entry, and record analytics.

These steps are not defined in one place. Both EmailNotification and SMSNotification write out every step by hand. So the steps that never change are copied next to the steps that differ, which is how the message is composed and sent.


2. Issues In This Code

Code Duplication

  • The Issue: Both EmailNotification and SMSNotification contain nearly identical logic for rate limit checking, string formatting, pre-send logging, and post-dispatch analytics updates.
  • The Impact: This breaks the DRY (Don't Repeat Yourself) principle. Copied logic makes the project bigger and adds technical debt (shortcuts that make later work harder). A simple cleanup means editing several files and keeping them in sync.

Hardcoded Workflow Behavior

  • The Issue: The rules for when an audit log is written or how rate limiting blocks a send are written straight inside each send() method.
  • The Impact: The code is hard to change. To make a channel skip logging or use a different validation check, you must rewrite the whole method. Each rewrite risks a regression (breaking something that used to work).

Lack of Extensibility & Maintenance Overhead

  • The Issue: A new channel (such as a PushNotification or a SlackNotification) needs a new class that repeats all the shared checks.
  • The Impact: As the system grows, more files carry the same code. Say a company rule adds an encryption step before every send. Developers must then open, edit and check every channel class one by one.

3. Structural Vulnerabilities

Fragmented Enforcement

No superclass enforces the steps of the delivery. Nothing guarantees that a new notification class will remember the analytics update or the rate limit check. A step can be skipped or changed without anyone noticing, and the channels slowly drift apart.


4. Operational Breakdown of Vulnerabilities

MetricNaive Design StatusArchitectural Target
Workflow GovernanceFragmented: Each class involves its own copy of every step.Controlled: One base class owns the order of the steps.

In this topic

Before code1 file

Before/Main.java65 linesGitHub
package DesignPatterns.BehaviouralPatterns.TemplateMethodPattern.Before;/** * PROBLEM: Code Duplication & Lack of Structural Enforcements. * EmailNotification and SMSNotification handle identical systemic steps (Rate Limits, Logging, * Validation, Analytics) manually. If the corporate security policy changes to require * an encryption phase before logging, every single distinct notification class must be modified. */class EmailNotification {    public void send(String to, String message) {        // ISSUE 1: RIGID BOILERPLATE REPETITION        System.out.println("Checking rate limits for: " + to);        System.out.println("Validating email recipient: " + to);        String formatted = message.trim();        System.out.println("Logging before send: " + formatted + " to " + to);        // ISSUE 2: VARIANT STEPS BLENDED WITH INVARIANT FLOW        // The only part truly unique to Email is how it is composed and delivered.        String composedMessage =            "<html><body><p>" + formatted + "</p></body></html>";        System.out.println(            "Sending EMAIL to " + to + " with content:\n" + composedMessage        );        // ISSUE 3: ENFORCEMENT GAP        // There is no mechanism guaranteeing that every implementation remembers to track analytics.        System.out.println("Analytics updated for: " + to);    }}class SMSNotification {    public void send(String to, String message) {        // REPEATED LOGIC: Duplicate rate limits, trimming, and logging mechanics.        System.out.println("Checking rate limits for: " + to);        System.out.println("Validating phone number: " + to); // Slightly different verification        String formatted = message.trim();        System.out.println("Logging before send: " + formatted + " to " + to);        // SMS Variant mechanics        String composedMessage = "[SMS] " + formatted;        System.out.println(            "Sending SMS to " + to + " with message: " + composedMessage        );        // Subtly different analytics logic, risking fragmented tracking reporting across channels.        System.out.println("Custom SMS analytics for: " + to);    }}class Main {    public static void main(String[] args) {        EmailNotification emailNotification = new EmailNotification();        SMSNotification smsNotification = new SMSNotification();        emailNotification.send(            "example@example.com",            "Your order has been placed!"        );        System.out.println(" ");        smsNotification.send("1234567890", "Your OTP is 1234.");    }}

Done with this topic?

How well do you know it?

PreviousLifecycle Management & State Transitions