---
title: Frameworks
source: 'https://academia.sh/en/courses/enterprise-context/frameworks'
course: 'Enterprise Context and Integration'
language: en
updated: '2026-08-23T07:01:06+00:00'
license: 'CC BY-SA 4.0'
---

# Frameworks

The shared structure of enterprise architecture frameworks — layer separation, view set, governance cycle, and maturity level — and documenting the same enterprise model in a detailed-layered and a lightweight format: how many questions each format answers, how many items it carries, how many items are touched per change, and the questions no format answers at all.

The previous lesson built the enterprise model and tied alignment to three numbers. The model was
produced once, but where it should be written down was never discussed: which layers it splits
into, how many separate views it is kept in, who reviews it and how often are all unsettled.
Enterprise architecture frameworks claim to fill this gap, and the claim usually becomes a debate
— which framework to pick, whether the heavy one or the light one is right. This lesson turns the
debate into a measurement. No brand or framework name is written; frameworks are referred to by
their shared structure.

## The Shared Structure of Frameworks

Whatever their names and details, enterprise architecture frameworks are built from four parts.

**Layer separation** divides the enterprise into planes that are distinct from one another but
mapped onto each other: business capabilities and their owners, systems, data assets, and the
infrastructure that carries the systems. The **view set** is the same model's cross-sections, each
prepared for a different reader. The **governance cycle** ties down which record is reviewed by
whom and how often. The **maturity level** is a ladder ranking how much of these records the
enterprise keeps.

What these four parts share is this: none of them produces information, each tells you **where
information gets written**. A framework can therefore only be measured through the record types it
carries. Measurement needs three definitions. An **item** is a record row looked at independently;
fields that fall on the same row are not counted as separate items (**EA5**). The **question set**
is the twelve questions someone asks later; the measure is borrowed from the Architectural
Decisions and Documentation course — a document's value is the number of questions it answers
(**EA6**). A **maturity level** is not a title but a predicate tied to the presence of specific
record types (**EA7**).

The first file gives the previous lesson's enterprise model again; the block is repeated so it can
run on its own.

```js
// enterprise/model.mjs — MODEL regional library network: systems, owners, capabilities, data.
// Fictional; no real institution, vendor, product, or person is described.
export const SYSTEM = {
  catalog: { owner: "external-provider", budget: "service-fee" },
  loan: { owner: "it-department", budget: "internal-development" },
  billing: { owner: "it-department", budget: "internal-development" },
  membership: { owner: "member-services", budget: "member-services" },
  identity: { owner: "municipal-it", budget: "municipality" },
  "branch-local": { owner: "branch-management", budget: "branch" },
  kiosk: { owner: "branch-management", budget: "branch" },
  reporting: { owner: "management-unit", budget: "management" },
  archive: { owner: "none", budget: "none" },
};
// CAPABILITY — the business capabilities the enterprise must cover (a list independent of system)
export const CAPABILITY = ["material-search", "loan-issuance", "return-intake", "reservation",
  "membership-enrollment", "member-verification", "fee-calculation", "fee-collection",
  "inter-branch-transfer", "asset-count", "usage-reporting",
  "purchase-suggestion", "overdue-notification"];
// COVERS[s] = the capabilities system s claims to cover
export const COVERS = {
  catalog: ["material-search", "asset-count"],
  loan: ["loan-issuance", "return-intake", "reservation", "overdue-notification"],
  billing: ["fee-calculation", "overdue-notification"],
  membership: ["membership-enrollment", "member-verification"],
  identity: ["member-verification"],
  "branch-local": ["return-intake", "inter-branch-transfer", "asset-count"],
  kiosk: ["loan-issuance", "material-search"],
  reporting: ["usage-reporting"],
  archive: [],
};
// DATA[v] = data asset; which system writes it, which ones read it
export const DATA = {
  "member-record": { writes: ["membership"], reads: ["loan", "billing", "kiosk", "reporting"] },
  "identity-match": { writes: ["identity", "membership"], reads: ["loan", "kiosk"] },
  "material-record": { writes: ["catalog"], reads: ["loan", "kiosk", "branch-local", "reporting"] },
  "copy-status": { writes: ["catalog", "loan", "branch-local"], reads: ["kiosk", "reporting"] },
  "loan-transaction": { writes: ["loan", "kiosk"], reads: ["billing", "reporting"] },
  "fee-record": { writes: ["billing"], reads: ["membership", "reporting", "kiosk"] },
  "penalty-rule": { writes: ["billing"], reads: ["loan", "kiosk"] },
  "transfer-request": { writes: ["branch-local"], reads: ["loan", "catalog"] },
  "legacy-record": { writes: [], reads: ["archive", "reporting"] },
  "count-discrepancy": { writes: ["branch-local"], reads: [] },
};
export const SYSTEMS = Object.keys(SYSTEM);
export const owner = (s) => SYSTEM[s].owner;
// edge = the directed pair from the system that writes a data asset to the system that reads it
export function edges() {
  const e = new Map();
  for (const [v, d] of Object.entries(DATA))
    for (const w of d.writes) for (const r of d.reads)
      if (w !== r) e.set(`${w}->${r}`, [...(e.get(`${w}->${r}`) ?? []), v]);
  return e;
}
```

## Measurement

The second file defines the two formats. The detailed-layered format keeps each record type as a
separate item in its own layer; the lightweight format consists of nothing more than a single
system table and a capability list, folding owner, budget, and coverage information into the
system row's columns.

```js
// enterprise/framework.mjs — same enterprise model in two framework formats: answer, item, maintenance
import { SYSTEM, CAPABILITY, COVERS, DATA, SYSTEMS, owner, edges } from "./model.mjs";

const col = (s, n) => String(s).padEnd(n);
const E = edges();
// ITEM[type] = number of rows of that record type in the model enterprise
const ITEM = {
  capability: CAPABILITY.length,
  owner: new Set(SYSTEMS.map(owner)).size - 1,
  budget: new Set(SYSTEMS.map((s) => SYSTEM[s].budget)).size - 1,
  system: SYSTEMS.length,
  "capability-mapping": Object.values(COVERS).flat().length,
  data: Object.keys(DATA).length, edge: E.size,
  carrier: 4, "system-carrier": SYSTEMS.length,
  view: 4, governance: 4, maturity: 1,
};
// FORMAT[f][type] = the independent item that carries that record type; null means the format does not hold it.
// Records that fall on the same item do not need separate maintenance (this describes shared structure, not a brand).
const own = (l) => Object.fromEntries(l.map((k) => [k, k]));
const FORMAT = {
  "detailed-layered": own(Object.keys(ITEM)),
  lightweight: { system: "system", owner: "system", budget: "system",
    "capability-mapping": "system", capability: "capability" },
};
const holds = (f, type) => Boolean(FORMAT[f][type]);
const itemCount = (f) => [...new Set(Object.values(FORMAT[f]))].reduce((t, k) => t + ITEM[k], 0);

// QUESTION[i] = a question someone asks later; needs = the record types required to answer it
const QUESTION = [
  ["which system covers which capability", ["capability-mapping"]],
  ["who owns a system", ["owner"]],
  ["which capability is covered by no system", ["capability", "capability-mapping"]],
  ["if a system is shut down, which capability is left uncovered", ["capability-mapping"]],
  ["which budget pays for a system's cost", ["budget"]],
  ["which system writes a given data asset", ["data"]],
  ["which data passes between two systems", ["edge"]],
  ["which carrier does a system run on", ["system-carrier"]],
  ["which section of the document was reviewed when", ["governance"]],
  ["which view documents a given topic", ["view"]],
  ["how often does a given data asset pass", ["edge-frequency"]],
  ["who is notified if an edge breaks", ["edge-owner"]],
];
const answers = (f, needs) => needs.every((n) => holds(f, n));

// CHANGE[i][1] = the records that must be updated when the change happens
const CHANGE = [
  ["a new system goes live", { system: 1, "capability-mapping": 1, edge: 2,
    carrier: 1, "system-carrier": 1, view: 2, governance: 1 }],
  ["a system is transferred to another unit", { system: 1, owner: 1, budget: 1, view: 1, governance: 1 }],
  ["a new reader is added to a data asset", { data: 1, edge: 1, view: 1, governance: 1 }],
];
function touched(f, d) {
  const group = new Map(); // records that fall on the same item count as one maintenance
  for (const [type, n] of Object.entries(d)) {
    const k = FORMAT[f][type];
    if (k) group.set(k, Math.max(group.get(k) ?? 0, n));
  }
  return [...group.values()].reduce((t, n) => t + n, 0);
}

// MATURITY — rungs; each rung requires certain record types
const MATURITY = [
  ["a system inventory exists", ["system"]],
  ["every system's owner is recorded", ["system", "owner"]],
  ["a capability mapping exists", ["capability", "capability-mapping"]],
  ["data ownership is recorded", ["data"]],
  ["the impact of a change can be computed", ["data", "edge"]],
];
const level = (f) => {
  let n = 0;
  for (const [, needs] of MATURITY) { if (!needs.every((g) => holds(f, g))) break; n++; }
  return n;
};

const formats = Object.keys(FORMAT);
console.log(`MODEL enterprise: ${SYSTEMS.length} systems, ${CAPABILITY.length} capabilities, ` +
  `${Object.keys(DATA).length} data, ${E.size} edges; question set ${QUESTION.length} questions\n`);
console.log(col("question", 64) + formats.map((f) => col(f, 20)).join(""));
console.log("-".repeat(104));
for (const [q, needs] of QUESTION)
  console.log(col(q, 64) + formats.map((f) => col(answers(f, needs) ? "answer" : "-", 20)).join(""));

console.log("");
console.log(col("format", 20) + col("answer", 8) + col("item", 8) + col("level", 9) +
  col("item/answer", 13) + "items touched per change");
console.log("-".repeat(100));
for (const f of formats) {
  const y = QUESTION.filter(([, g]) => answers(f, g)).length;
  const k = itemCount(f);
  const d = CHANGE.map(([, o]) => touched(f, o));
  console.log(col(f, 20) + col(`${y}/${QUESTION.length}`, 8) + col(k, 8) + col(`${level(f)}/5`, 9) +
    col((k / y).toFixed(1), 13) + d.join(" + ") + ` = ${d.reduce((t, n) => t + n, 0)}`);
}

const [d, l] = formats;
const ansD = QUESTION.filter(([, g]) => answers(d, g)).length;
const ansL = QUESTION.filter(([, g]) => answers(l, g)).length;
console.log(`\ndiff: ${itemCount(d) - itemCount(l)} more items -> ${ansD - ansL} more answers = ` +
  `${((itemCount(d) - itemCount(l)) / (ansD - ansL)).toFixed(1)} items/extra answer`);
const untouched = CHANGE.filter(([, o]) => touched(l, o) === 0);
console.log(`changes where the lightweight format touches no item: ${untouched.length} ` +
  `(${untouched.map(([name]) => name).join("; ")})`);
const unanswered = QUESTION.filter(([, g]) => formats.every((f) => !answers(f, g)));
console.log(`questions no format answers: ${unanswered.length} -> ` +
  unanswered.map(([q]) => q).join(" / "));
console.log("annual review rounds (capacity sensitivity):");
for (const cap of [20, 40, 60])
  console.log("  per round " + col(cap, 4) + "items -> " + formats.map((f) =>
    `${f}=${Math.ceil(itemCount(f) / cap)}`).join(", "));
```

```
MODEL enterprise: 9 systems, 13 capabilities, 10 data, 23 edges; question set 12 questions

question                                                        detailed-layered    lightweight         
--------------------------------------------------------------------------------------------------------
which system covers which capability                            answer              answer              
who owns a system                                               answer              answer              
which capability is covered by no system                        answer              answer              
if a system is shut down, which capability is left uncovered    answer              answer              
which budget pays for a system's cost                           answer              answer              
which system writes a given data asset                          answer              -                   
which data passes between two systems                           answer              -                   
which carrier does a system run on                              answer              -                   
which section of the document was reviewed when                 answer              -                   
which view documents a given topic                              answer              -                   
how often does a given data asset pass                          -                   -                   
who is notified if an edge breaks                               -                   -                   

format              answer  item    level    item/answer  items touched per change
----------------------------------------------------------------------------------------------------
detailed-layered    10/12   106     5/5      10.6         9 + 5 + 4 = 18
lightweight         5/12    22      3/5      4.4          1 + 1 + 0 = 2

diff: 84 more items -> 5 more answers = 16.8 items/extra answer
changes where the lightweight format touches no item: 1 (a new reader is added to a data asset)
questions no format answers: 2 -> how often does a given data asset pass / who is notified if an edge breaks
annual review rounds (capacity sensitivity):
  per round 20  items -> detailed-layered=6, lightweight=2
  per round 40  items -> detailed-layered=3, lightweight=1
  per round 60  items -> detailed-layered=2, lightweight=1
```

## The Difference Between the Two Formats

The detailed-layered format answers ten of the twelve questions and carries 106 items. The
lightweight format answers five and carries 22 items. The difference comes down to a single
number: **84 more items, 5 more answers** — 16.8 items per extra answer. The framework choice is
made against this ratio. If an enterprise finds the answer to "which system writes a given data
asset" worth the ongoing maintenance of 16.8 items, the detailed format wins; if it does not, the
lightweight format wins. This is a calculation, not a preference, and the numbers depend on the
size of the enterprise model: as the edge count grows, the detailed format's item count grows
fast, because 23 of its 106 items are edges.

The per-change cost difference is sharper: the same three changes update 18 items in the detailed
format and 2 in the lightweight one. There is a caveat inside this. The change "a system is
transferred to another unit" touches five items in the detailed format; the system itself does not
change, only its owner and budget do. At enterprise scale, most maintenance comes not from
technical change but from **ownership change**.

The third change makes the distinction visible: when a new reader is added to a data asset, the
lightweight format touches **no item at all**. This is the source of the lightweight format's
cheapness, and at the same time its limit. The document does not go stale, because it never made
any claim on the matter; it stays silent. A new edge forms in the enterprise, and no one
looking at the document can see it.

The maturity level is a shorthand for the same difference: the detailed format reaches five of the
five levels, the lightweight format three. A level is not a ranking of success; it is which
questions can be answered, reduced to a single number. The lightweight format stops at the fourth
level, because it does not keep data ownership at all — and the fifth level, whether the impact of
a change can be computed, depends exactly on this course's unit of measure.

## The Question a Framework Does Not Answer

Two questions stay unanswered in either format: how often a given data asset passes, and who is
notified when an edge breaks. The reason for this is not the framework choice. The model never
carries these fields; because it does not carry them, no layer separation and no view set can
produce them. A framework debate does not produce information, it organizes information that
already exists — and if there is no information to organize, a more detailed framework only
produces more empty items.

The governance cycle's cost is read from the same place. The number of items that can be worked
through per round is a threshold, and the source of that threshold should be written down: this
model chose forty items per round (**EA8**). At this threshold, the detailed format is reviewed in
three rounds, the lightweight format in one. When the threshold drops to twenty, the detailed
format rises to six rounds; when it rises to sixty, it falls to two. If the review capacity stays
below the item count, the document loses currency — that is, the framework itself becomes the
source of the drift it measures.

## Summary

- Enterprise architecture frameworks are built from four parts regardless of brand differences:
  layer separation, view set, governance cycle, and maturity level; none of them produces
  information, each determines where it belongs.
- The same enterprise model answers 10 of 12 questions and carries 106 items in the
  detailed-layered format; it answers 5 and carries 22 items in the lightweight format.
- The number that decides is items per extra answer: 84 more items buy 5 more answers, that is,
  16.8 items/extra answer; maintenance per change is 18 items against 2.
- One change touches no item at all in the lightweight format — a new reader being added. This is
  the source of the cheapness, and it is also where the document stays silent.
- Two questions go unanswered in either format (a data asset's frequency and an edge's owner),
  because the model never carries those fields; choosing a framework does not fill a missing
  field.

## Next Step

Both lessons treated the enterprise as a static structure: systems, owners, capabilities, records.
But a business capability is not a list row; it is a process that unfolds step by step. Between a
member walking through the door and taking a material in hand there is a sequence of operations,
and not all of these steps happen inside software. The next lesson models a business process step
by step and sorts every step into three classes — fully automatic, requiring human judgment,
outside the system. What gets measured is where the automation boundary runs, and how many
rollbacks come from forcing that boundary, that is, from automating a step that requires human
judgment.
