COBOL (ISO/IEC 1989:2023)

This assessment applies the coupling account — coupling as access to a shared resource, and the coupling floor [1], [2] — and the knowledge-embodiment theorem [3]; the language is assessed against its official reference [4].

1 Assessment

This page assesses COBOL in five parts: core coupling — what the language’s own constructs force; ecosystem coupling — what the surrounding platform, tooling, and community cost; engineering readiness — whether the artifact can be reproduced, verified, observed, worked in quickly, connected to other languages, and governed openly; the profile — the unscored facts a score cannot express; and the scoring detail — the mechanism marks and the arithmetic behind every score. A ✅ bullet marks a construct that helps. A ⚠️ or ❌ bullet marks a cost; the scoring model does not price every cost named here.

Core coupling 47/100 · Ecosystem coupling 54/100 · Engineering readiness 61/100

1.1 Core coupling

1.1.1 Type

  • ❌ Typing is weak and static: A PICTURE clause fixes an item’s shape, but a MOVE between items with different pictures converts the value silently, so the declared type does not protect it (T2)
  • ✅ The Data Division declares the shape once: Level numbers and PICTURE state each item’s size and category, and the Procedure Division uses that declaration without repeating it
  • ✅ Group items give a structured record: Level numbers nest elementary items inside groups, so a record layout is one declaration
  • ✅ Fixed decimal arithmetic is exact: COMP-3 packed-decimal operations do not accumulate binary floating-point error, so the numeric representation matches monetary values
  • ⚠️ USAGE decides the representation: COMP-3 (packed decimal), COMP (binary), and DISPLAY differ, and a move between them converts without a type error
  • ⚠️ An alphanumeric item accepts any character string: An X(n) item holds any text, so a category mistake is caught only by the program’s own checks

1.1.2 Construction

  • ❌ Every data item is visible to every paragraph: A WORKING-STORAGE item can be read and modified from any procedure, and before COBOL-85 the language offered no way to restrict access to it (C1)
  • ✅ The four divisions separate concerns: Identification, Environment, Data, and Procedure give each declaration a fixed place, so data definition does not share a space with program logic
  • ✅ CALL ... USING passes parameters to a subprogram: A called program receives its arguments explicitly, so a subprogram boundary is a declared interface
  • ✅ LOCAL-STORAGE gives per-call state: It is allocated for each invocation, so a re-entrant call does not share the state held in WORKING-STORAGE
  • ⚠️ PERFORM THRU names a range of paragraphs and passes nothing: The called region is a text span and the performed code communicates only through shared data items, with no parameter list and no call stack
  • ⚠️ GO TO and ALTER break structured flow: The language permits control transfers that obscure which paragraph runs next

1.1.3 Memory

  • ✅ Ordinary program data needs no allocator: WORKING-STORAGE and LOCAL-STORAGE come from a declared layout, so a program that uses only them calls no allocator and no free
  • ✅ No garbage collector: Storage is fixed at compile time, so reclamation is deterministic and unobserved
  • ✅ OCCURS declares fixed-size tables: The size of a table is known at compile time
  • ⚠️ OCCURS DEPENDING ON varies a table’s length at run time: The logic then couples to the actual occurrence count
  • ⚠️ ALLOCATE and FREE put deallocation back on the programmer: The 2002 standard added dynamic allocation for tables and objects, and release is an explicit statement

1.1.4 Error

  • ❌ Error handling has no structured path: USE AFTER STANDARD ERROR and other declaratives are declared globally in the DECLARATIVES section, and control may or may not return to the failing statement (Er1)
  • ✅ The declaratives section is separated from the main procedure: Recovery code is declared apart from the normal path
  • ✅ FILE STATUS reports I/O results as data: A file’s FILE STATUS item holds a two-character code that the program can test after each I/O statement
  • ✅ INVALID KEY and AT END put the failure case at the statement: READ ... INVALID KEY ... NOT INVALID KEY and AT END handle the result inside the operation itself
  • ❌ An error need not terminate the program: A declarative can return control after a failure, so a caller cannot rely on termination
  • ⚠️ No value carries the failure: There is no exception object and no result type, so detail travels only through shared items

1.1.5 Concurrency

  • ✅ Concurrency belongs to the transaction monitor: EXEC CICS and IMS link a program to a transaction environment instead of a language thread model
  • ✅ Batch steps are single-threaded by design: A batch program runs to completion without shared-memory concurrency
  • ✅ The 2023 standard defines asynchronous messaging: ISO/IEC 1989:2023 adds asynchronous message handling and transaction processing, so a program need not hand-roll that loop
  • ⚠️ The language has no threads or synchronisation primitives: Any parallel work couples the program to the monitor
  • ⚠️ Shared WORKING-STORAGE across transactions needs external discipline: A pseudo-conversational program must reset its state between transactions

1.1.6 Platform

  • ❌ A large share of production runs on IBM mainframes: Much COBOL executes on z/OS with IBM compilers, so practice is largely one vendor’s (P2)
  • ✅ The language is an ISO standard: ISO/IEC 1989:2023 is the current edition, so the language is not owned by a single vendor
  • ✅ GnuCOBOL is an independent compiler: It is an open-source project separate from GCC and translates COBOL to C
  • ⚠️ Vendor extensions bind a program to a compiler: EXEC CICS, EXEC SQL, and vendor libraries do not compile unchanged elsewhere
  • ⚠️ Newer standard features are unevenly implemented: The 2002 object-oriented features and the 2023 additions are not uniformly available across compilers

1.1.7 Trade-offs (not coupling)

  • The small standard library is a scope decision: The standard specifies 43 statements, 87 functions, and one class, and adds no general-purpose library beyond them
  • The fixed reference format comes from the punched card: Columns 1–6 hold a sequence number and column 7 an indicator, and free format is now permitted, so the old constraint is optional
  • Mainframe batch orientation is a scope decision: COBOL assumes file and transaction processing in a monitor, which suits high-volume work and excludes systems programming
  • The PICTURE-driven fixed record suits flat files: The declared layout matches a fixed-length record, which is a modelling choice for the domain
  • The installed base is a business constraint: Retaining legacy programs is an organisational decision, not a property of the language

1.2 Ecosystem coupling

1.2.1 Performance

  • ✅ Compiled ahead of time to native code: IBM Enterprise COBOL and GnuCOBOL (through generated C) produce machine code, so no interpreter and no JIT warm-up sits on the path
  • ✅ USAGE selects the representation per item: COMP-3 packs two digits per byte where compact storage matters
  • ✅ A batch step amortises start-up over millions of records: One run processes the whole job
  • ⚠️ Tuning is platform-specific: IBM’s optimiser and GnuCOBOL produce different code, so a tuned program does not transfer unchanged
  • ⚠️ Exact decimal arithmetic is slower than binary: COMP-3 operations cost more than native binary arithmetic

1.2.2 Ecosystem

  • ❌ The ecosystem is legacy and vendor-fragmented: IBM, Micro Focus, and GnuCOBOL each supply their own compiler, runtime, and tooling (Ec3)
  • ❌ The mainframe tooling is proprietary: The compilers, monitors, and debuggers are commercial products (Ec4)
  • ✅ GnuCOBOL is open source and maintained: It gives the language a free compiler
  • ✅ A long-lived body of documentation exists: The ISO standard and the vendor manuals are complete and stable over decades
  • ✅ The deployed base is enormous: Gartner reported over 200 billion lines of COBOL in 1997, and the language remains among the most widely deployed
  • ⚠️ The skills base is shrinking: Retirements reduce the pool of maintainers, a risk exposed by the COVID-era unemployment-systems crisis

1.2.3 Evolution

  • ✅ The standard is backward compatible across decades: COBOL-74, -85, 2002, 2014, and 2023 code coexist, and programs written decades ago still compile
  • ✅ ISO/IEC 1989:2023 added modern features: Asynchronous messaging, transaction processing, and dynamic-capacity tables join the language
  • ⚠️ Revisions are infrequent: A new standard edition arrives at intervals of a decade or more, so a needed feature waits a long time
  • ⚠️ Adoption of a new feature is uneven: A compiler may not implement a standard feature for years after publication

1.2.4 Domain

  • ❌ Strong lock-in to mainframe transaction and batch processing: The language assumes fixed records, files, and a monitor runtime, so code carries that shape outside its home domain (D1)
  • ✅ Superb for high-volume batch and transaction processing: The fit to financial and administrative workloads is close
  • ✅ Still runs the bulk of card-payment background processing: The source reports COBOL behind most credit and debit-card swipe processing
  • ✅ Fixed-point decimal arithmetic fits money: The data model matches monetary computation without floating-point error
  • ⚠️ Poor for nearly everything else: Interactive, systems, and scientific work have little COBOL tooling

1.2.5 Learning

  • ❌ The learning curve is steep in practice: Verbosity and over 300 reserved words must be learned (L1)
  • ✅ The syntax is English-like: MOVE A TO B, ADD ... GIVING, IF ... END-IF, and DISPLAY read close to prose
  • ✅ The division structure is a fixed learning path: Four divisions in a defined order give a predictable place for each declaration
  • ⚠️ The vocabulary is large: More than 300 reserved words, and each verb carries many optional clauses
  • ⚠️ The tooling is not beginner-friendly: Mainframe editors, JCL, and compile procedures are learned separately from the language

1.2.6 Syntax

  • ❌ Verbose: Every statement names its verb and its operands, and paragraphs need explicit names (S1)
  • ✅ English-like and self-describing: The verb names the operation, so a statement is readable without symbol decoding
  • ✅ END-IF, END-PERFORM, and END-READ bound a scope: Explicit terminators remove the ambiguity of implicit scope
  • ⚠️ Fixed-format column rules still shape style: Column 7 is an indicator and the code sits in columns 8–72 in the classic reference format, and free format is an option
  • ⚠️ The four-division prologue is long: Even a minimal program declares Identification, Environment, Data, and Procedure

1.2.7 Testing

  • ✅ FILE STATUS and INVALID KEY give checkable I/O outcomes: A test can assert on the status item after a file operation
  • ✅ Compilers supply tracing and dump facilities: IBM Debug Tool and GnuCOBOL’s runtime tracing report execution, and COB_SET_TRACE enables a trace at run time
  • ✅ GnuCOBOL runs on ordinary workstations: The open-source compiler executes test jobs locally
  • ⚠️ No test framework is in the language or the standard: A harness is external, so a suite couples to the tooling
  • ⚠️ A batch test needs representative data: The job needs real files and JCL, not just a unit of code

1.2.8 Security

  • ✅ Fixed PICTURE sizes bound every item: An oversized source value is truncated or padded on assignment rather than overrunning a buffer
  • ✅ No pointers in the classic language: A COBOL program cannot forge an address
  • ✅ The transaction monitor authorises access: CICS and RACF check a transaction’s resource use
  • ⚠️ Truncation is silent: A value that does not fit an item is truncated without an error, so data can be lost quietly
  • ⚠️ Dynamic SQL is injectable unless host variables are used: EXEC SQL with host variables is parameterised, but a statement built from a string re-opens SQL injection

1.3 Engineering readiness

1.3.1 Reproducibility

  • ❌ Builds are not byte-reproducible by default.
  • ❌ Dependencies resolve without a lock by default.

1.3.2 Supply chain

  • ⚠️ Published packages carry no signed provenance by default.

1.3.3 Observability

  • ⚠️ No stable tracing and metrics standard.
  • ⚠️ The standard library has no structured logging.

1.3.4 Feedback

  • ✅ No charged mechanism in this dimension.

1.3.5 Interop

  • ⚠️ No maintained portable target.

1.3.6 Governance

  • ✅ No charged mechanism in this dimension.

1.4 Profile

Unscored, and kept separate from every score on purpose. The profile records what a mechanism price cannot express: what a running program costs, how well a coding model and an agent work in the language, and whether a safety-critical path exists.

1.4.1 Energy and cost

What this axis asks: what does a running program cost in energy and time?

  • ✅ Compiles to native code: the fastest class in the language energy and time benchmarks [5], [6]. A causal re-analysis attributes the difference to execution time [7].

1.4.2 AI and agent readiness

What this axis asks: how well does a coding model and an agent work in this language?

  • ❌ Sparse training data: models write it unreliably [8].

1.4.3 Safety certification

What this axis asks: is there a certified or standards-qualified path to a safety-critical system?

  • ⚠️ No certified or standards-qualified path for safety-critical systems.

1.5 Scoring detail

1.5.1 Core coupling Dimensions

Dimension Mechanism Description Present Cost
Type T1 dynamic no static check — 0
T2 weak static ✅ −8
T3 dynamic/duck dispatch — 0
T4 no sum types — 0
T5 no generics — 0
T6 no namespaces — 0
T7 type erasure/reflection — 0
T8 operator overloading — 0
T9 inheritance required for polymorphism — 0
T10 no null-safety — 0
T11 no module boundary — 0
T12 no effect tracking ✅ −8
T13 async/sync colouring — 0
T14 unchecked foreign boundary ✅ −4
Type subtotal −15 (−20)
Construction C1 global mutable state by default ✅ −15
C2 no immutability by default — 0
C3 constructors coupled to allocation — 0
C4 no constructor/validation — 0
Construction subtotal −15
Memory M1 manual deallocation — 0
M2 GC non-deterministic pauses — 0
M3 no RAII — 0
M4 no ownership model — 0
Memory subtotal 0
Error Er1 no structured path ✅ −15
Er2 unchecked exceptions only — 0
Er3 errors ignored/non-exhaustive — 0
Er4 no composable result type — 0
Error subtotal −15
Concurrency K1 GIL/no parallel — 0
K2 shared mutable state default — 0
K3 manual sync no race detection — 0
K4 no structured concurrency — 0
K5 no primitives — 0
Concurrency subtotal 0
Platform P1 cannot function outside one vendor/domain — 0
P2 single-vendor but other uses ✅ −8
P3 legacy/discontinued platform — 0
Platform subtotal −8

Core Dimensions score: 47/100 — total cost = −53 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

1.5.2 Ecosystem coupling Dimensions

Dimension Mechanism Description Present Cost
Performance R1 interpreted no AOT/JIT — 0
R2 GC pauses — 0
R3 JIT warmup — 0
Performance subtotal 0
Ecosystem Ec1 no package manager — 0
Ec2 fragmented tooling — 0
Ec3 small/niche/discontinued ✅ −8
Ec4 proprietary ✅ −8
Ec5 platform-locked tooling — 0
Ec6 monoculture — 0
Ec7 legacy burden — 0
Ecosystem subtotal −15 (−16)
Evolution V1 breaking changes — 0
V2 frozen — 0
V3 discontinued — 0
V4 glacial standards — 0
Evolution subtotal 0
Domain D1 domain/vendor lock-in ✅ −15
D2 poor domain fit — 0
D3 framework forces architecture — 0
Domain subtotal −15
Learning L1 steep ✅ −8
L2 large surface/multi-paradigm — 0
L3 sparse docs — 0
Learning subtotal −8
Syntax S1 verbose ✅ −8
S2 inconsistent — 0
S3 punctuation-heavy — 0
Syntax subtotal −8
Testing G1 weak tooling — 0
G2 poor debugging — 0
G3 runtime-only errors — 0
Testing subtotal 0
Security Q1 memory-unsafe — 0
Q2 dynamic/weak typing risk — 0
Q3 known vulnerability/injection — 0
Security subtotal 0

Meta Dimensions score: 54/100 — total cost = −46 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

1.5.3 Engineering readiness Dimensions

Dimension Mechanism Description Present Cost
Reproducibility Y1 build not reproducible ✅ −8
Y2 dependencies not pinned ✅ −8
Reproducibility subtotal −15 (−16)
Supply chain Y3 no signed provenance ✅ −8
Y4 registry without namespacing — 0
Supply chain subtotal −8
Observability Y5 no stable tracing standard ✅ −8
Y6 no structured logging ✅ −4
Observability subtotal −12
Feedback Y7 slow build — 0
Y8 no fast in-editor analysis — 0
Feedback subtotal 0
Interop Y9 no foreign-function interface — 0
Y10 no portable target ✅ −4
Interop subtotal −4
Governance Y11 single-vendor governance — 0
Y12 closed specification — 0
Governance subtotal 0

Readiness Dimensions score: 61/100 — total cost = −39 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

Verdict: COBOL’s two scores are deliberately even: its own constructs impose about as much coupling as its platform and ecosystem do. The four divisions and the PICTURE clause declare a record once, CALL ... USING gives a subprogram an explicit parameter interface, and LOCAL-STORAGE gives per-call state, but the default visibility of every data item to every paragraph, the paragraph-range semantics of PERFORM THRU, and error handling by declaratives that may not terminate the program make global coupling the norm. The platform side is legacy, vendor-fragmented, and locked to mainframe transaction processing, with a shrinking skills base. Inside high-volume batch and transaction processing COBOL is excellent; outside that niche the fit is poor.


The formal development. The definitions, theorems, and proofs behind this page are published in:

All published papers

References

[1]
Y. Loth, “On the nature of coupling: All coupling as shared resource access.” Zenodo, Aug. 2026. doi: 10.5281/zenodo.21925122.
[2]
Y. Loth, “Coupling as a consequence of cohesion: Decomposition, the coupling floor, and domain-imposed coupling.” Zenodo, Aug. 2026. doi: 10.5281/zenodo.21925201.
[3]
Y. Loth, “On the nature of cohesion: Cohesion as correctness relative to a partitioning rule.” Zenodo, Jul. 2026. doi: 10.5281/zenodo.21703193.
[4]
ISO/IEC JTC 1/SC 22, “Information technology — programming languages — COBOL.” International Organization for Standardization; International Standard ISO/IEC 1989:2023 (COBOL 1989:2023), Geneva, Switzerland, 2023.
[5]
R. Pereira et al., “Energy efficiency across programming languages: How do energy, time, and memory relate?” in Proceedings of the 10th ACM SIGPLAN international conference on software language engineering (SLE), 2017, pp. 256–267. doi: 10.1145/3136014.3136031.
[6]
R. Pereira et al., “Ranking programming languages by energy efficiency,” Science of Computer Programming, 2021, doi: 10.1016/j.scico.2021.102609.
[7]
N. van Kempen, H.-J. Kwon, D. T. Nguyen, and E. D. Berger, “It’s not easy being green: On the energy efficiency of programming languages,” in Proceedings of the 40th IEEE/ACM international conference on automated software engineering (ASE), 2025. doi: 10.1109/ASE63991.2025.00131.
[8]
S. Joel, J. J. Wu, and F. H. Fard, “A survey on LLM-based code generation for low-resource and domain-specific programming languages,” ACM Transactions on Software Engineering and Methodology, 2025, doi: 10.1145/3770084.