String Transformer

Level: Advanced 60–90 min

Concepts: AlgorithmsDesign PatternsEdge CasesRefactoring

Solutions: C# | TypeScript | Python


Build a string transformer that supports chainable operations. Each operation transforms the input string and passes the result to the next operation.

Requirements

  1. Create a StringTransformer that takes an initial string
  2. Support the following operations, all chainable:
    • capitalise() — capitalise the first letter of each word
    • reverse() — reverse the entire string
    • removeWhitespace() — remove all whitespace
    • snakeCase() — convert to snake_case
    • camelCase() — convert to camelCase
    • truncate(n) — truncate to n characters, adding ”…” if truncated
    • repeat(n) — repeat the string n times with a space separator
    • replace(target, replacement) — replace all occurrences
  3. result() returns the final transformed string
  4. Operations are applied in order

Test Cases

InputOperationsResult
”hello world”capitalise()“Hello World"
"hello world”reverse()“dlrow olleh"
"hello world”removeWhitespace()“helloworld"
"hello world”snakeCase()“hello_world"
"Hello World”camelCase()“helloWorld"
"hello world”truncate(5)“hello…"
"hello world”truncate(50)“hello world"
"ha”repeat(3)“ha ha ha"
"hello world”capitalise().reverse()“dlroW olleH"
"hello world”snakeCase().capitalise()“Hello_World"
""capitalise()""
"HELLO WORLD”camelCase()“helloWorld"
"hello-world test”snakeCase()“hello_world_test”

Bonus

  • Add cipher(n) — apply a Caesar cipher shifting each letter by n positions
  • Add slug() — convert to URL-friendly slug (lowercase, hyphens, no special characters)
  • Add mask(n) — mask all but the last n characters with asterisks (useful for credit cards, emails)
  • Make the transformer immutable — each operation returns a new transformer, allowing branching transformations

Reference Walkthrough

Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/string-transformer. This is an F2 (light builder) kata showcasing the Strategy pattern: every transformation (Capitalise, Reverse, SnakeCase, Truncate(n), Replace(target, replacement), …) is a self-contained class implementing a uniform apply(string) -> string; Pipeline runs them in order; a small test-folder PipelineBuilder makes each scenario a one-line fluent chain.

Scope note — eight required transformations only. The reference implements the eight chainable operations from the spec (capitalise, reverse, removeWhitespace, snakeCase, camelCase, truncate, repeat, replace). The four bonus ideas — cipher(n), slug(), mask(n), and immutable-branching pipelines — are out of scope and listed as stretch goals in the repo README.

This kata ships in Agent Full-Bake mode at middle gear, the F2 (light builder) tier. See the repo’s Gears section for why middle gear is the deliberate choice.


  • Katas Are Rehearsal, Not Performance
    You don't practice TDD on production code. You practice on katas and bring the muscle memory to production. The gap between knowing TDD and doing TDD is reps.
  • Property-Based Tests Are the Guardrail Agents Need
    Example-based tests encode cases an agent can enumerate and hardcode past. Property-based tests quantify over inputs the agent did not see at code-write time, which is the gap that makes the lookup-table attack more expensive than the honest fix. Properties are one layer in the enforcement stack, not the whole stack.
  • Agents Amplify Whatever Vocabulary They Find
    Agents do not bring vocabulary to your codebase. They mirror what's already there. Strong vocabulary gets agent contributions that read like the team. Weak vocabulary gets faster mediocrity. The work you did for craft reasons just became leverage.