Skip to content
Back to skills

Functional Splitting And Joining Code

ASecurity

Use when deciding whether to split a function or module, when a boolean parameter selects behaviour, or when two pieces always change together.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 21, 2026
ai-agents

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 21, 2026

npx -y skills add yutna/functional-design-skills --skill functional-splitting-and-joining-code --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Functional Splitting And Joining Code?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Functional Splitting And Joining Code
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yutna-functional-splitting-and-joining-code/badge)](https://www.skillsdirectory.com/skills/yutna-functional-splitting-and-joining-code)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: functional-splitting-and-joining-code
description: Use when deciding whether to split a function or module, when a boolean parameter selects behaviour, or when two pieces always change together.
license: MIT
metadata:
  pack: functional-design-skills
  version: 3.3.0
---

# Splitting and Joining Code

**In this pack:** [how much design a task warrants](../functional-design/references/calibration.md),
[the notation](../functional-design/references/notation.md), and
[syntax per language](../functional-design/SKILL.md#language-packs).

## Overview

Given two pieces of functionality, should they be in the same place or
separate places? The instinct to split is usually stronger than the
instinct to join, and it is usually wrong: subdividing creates
interfaces, and interfaces are where complexity lives. Subdivision also
scatters what belonged together, so a reader must find all the pieces
before understanding any of them.

Bring code together when the pieces share information, are always used
together, overlap conceptually, or cannot be understood apart. Split when
one piece is general and the other is special, or when the two have
genuinely separate reasons to change.

## When to use

- A function is "too long" and the urge is to extract parts of it
- Two modules are always changed in the same commit
- General logic and one caller's special case share a body
- A pipeline step is only ever called by one other step
- Deciding whether a helper belongs in the file that uses it

Not for: judging whether a module's interface is worth its cost, which is
[functional-designing-deep-modules](../functional-designing-deep-modules/SKILL.md).

## Bring together when

1. **They share information.** Both need the same non-obvious fact: a
   format, an invariant, a set of thresholds. Splitting them makes that
   fact travel.
2. **They are always used together.** Every caller of one calls the other,
   in the same order, with the same values.
3. **They overlap conceptually.** A single sentence covers both, without
   "and".
4. **One is hard to understand without the other.** If reading the second
   is required to understand the first, the split bought nothing.
5. **Joining eliminates duplication.** Two branches that repeat the same
   preparation collapse into one.

## Keep apart when

1. **One is general, the other special.** The general part serves many
   callers; the special part serves one. Mixing them means the general
   part carries a caller's assumptions forever.
2. **They have different reasons to change.** Different owners, different
   release cadence, different regulation, different domain.
3. **Only one needs to be understood by callers.** The other can be
   hidden behind it.
4. **They belong to different layers.** Different vocabulary means a real
   boundary, and a layer that is just a folder name is not one. Rule 1 of
   [functional-separating-layers](../functional-separating-layers/SKILL.md)
   lists what else earns a layer.

## Pattern

The special-general mixture, and its repair.

```text
-- general calendar primitive, contaminated by one caller's case
place : Interval -> AppointmentId -> Calendar -> Result<Calendar, Clash>
-- ...and, inside, a branch for "if this is a follow-up visit, let it
-- overlap the same clinician's existing appointment"
```

The follow-up rule now lives inside the general primitive. Every future
scheduling feature must read it, and any change to follow-ups risks
everything else.

```text
-- general stays general
place : Interval -> AppointmentId -> Calendar -> Result<Calendar, Clash>

-- special lives with the feature that needs it
placeFollowUp :
  Clinician -> Interval -> AppointmentId -> Calendar
            -> Result<Calendar, Clash>
placeFollowUp c i a cal =
  place i a (allowOverlapFor c cal) |> map (restoreRules cal)
```

The general primitive knows nothing about follow-ups. The special case is
one small function next to the feature that owns it.

## On splitting functions

Length alone is not a reason to split. Split a function when:

- The extracted part is a **separate, meaningful abstraction** that a
  reader could use without knowing the parent
- The parent becomes shorter **and** neither part now needs to explain
  the other
- The interface between the two parts is simple: few parameters, no
  shared mutable state, no required call order

Do not split when:

- The extracted part takes more than three parameters, half of them for
  context
- Its name has to be `doPart2` or `helperFor...`
- Reading it requires reading the parent anyway
- It exists only because a style rule sets a line limit

The failure mode is **conjoined functions**: two functions that can only
be understood together. That is worse than one longer function, because
the reader must now hold both, plus the mapping between them.

## Quick reference

| Signal                            | Verdict          |
| --------------------------------- | ---------------- |
| Both know the same format         | Together         |
| Always called as a pair           | Together         |
| One is general, one is special    | Apart            |
| Different reasons to change       | Apart            |
| Extracting needs 4+ parameters    | Leave together   |
| Only one is meant for callers     | Apart, and hide  |
| Reader must read both to get one  | Together         |
| Same nouns, different layer names | Together, remove |

## Red flags

- A function named after its position rather than its job
- Two files that never appear separately in a commit
- A general utility with a parameter named after one feature
- An extracted helper whose parameter list is longer than its body
- A module split that made both halves import each other

## Common mistakes

- **Splitting to satisfy a length limit.** Line limits measure nothing
  that matters; abstraction boundaries do.
- **Splitting by structure.** One file per type or per verb, or a folder
  per layer for every entity, distributes decisions rather than
  isolating them.
- **Joining things that merely resemble each other.** Two functions with
  similar shapes and different reasons to change should stay apart even
  if that means similar code.
- **Extracting the special case into the general module.** If it moves,
  it moves outward towards its caller, never inward.

## Related skills

- [functional-designing-deep-modules](../functional-designing-deep-modules/SKILL.md)
- [functional-separating-layers](../functional-separating-layers/SKILL.md)
- [functional-hiding-information](../functional-hiding-information/SKILL.md)
- [functional-composing-functions](../functional-composing-functions/SKILL.md)

## Further reading

- [decision-criteria.md](references/decision-criteria.md) turns the two
  lists above into a procedure, with worked cases including the
  duplication trap.

Files in this skill

  • SKILL.md6.7 KB
  • references/decision-criteria.md4.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.