Introduction
- Overview
- Historical Intention
The Decomposition Problem
- Why EL_base is difficult to split into smaller libraries; initial hypotheses around reflection and string/container coupling
ChatGPT Analysis of
library/base/base.ecf
- Scope and intent of the base library; early evidence of tight internal coupling
Reflection as a Systemic Dependency
- Inheritance-based reflection, type utilities, and modules; why reflection resists isolation
ZSTRING and Container Bidirectional Coupling
- Container extensions, conversion semantics, and ZSTRING as a semantic substrate
Expanded AI Analysis with Tests, Benchmarks, Examples, and Tools
- What usage code reveals about architectural assumptions; ecosystem-wide coupling
From Tight Coupling to Architectural Intent
- Why EL_base resists modularization; refactoring versus redesign
What a Greenfield, Decomposable Successor Would Require
- Trade-offs involved in abandoning ambient reflection, universal string semantics, and inheritance-as-infrastructure
Architectural Audacity
- Coherence, expressiveness, and the deliberate acceptance of tight coupling
Gobo’s Philosophy
- Language fidelity, modular conservatism, and social scalability
Conclusion: A Deliberate Trade-off
- Coherence versus modularity as conscious architectural choices
The following ChatGPT source code analysis thread explores why the Eiffel-Loop base library EL_base resists decomposition into smaller, modular libraries, and whether that resistance is accidental or the result of deliberate architectural choices.
Starting from a concrete technical question about coupling, specifically reflection mechanisms and string/container design, the analysis broadens to include evidence from unit tests, benchmarks, examples, and tools. This broader view reveals that EL_base is not merely a utility library, but the architectural substrate of an entire ecosystem. The phrase architectural audacity, which appears later, is not one I would have chosen myself and initially came as a surprise. It emerged during an GPT-assisted analysis of the design and proves useful as a shorthand for characterizing this style.
From there, the conversation moves beyond mechanics into philosophy:
The result is not a verdict for or against any approach, but a clarification of worldviews: architectural audacity versus modular conservatism, expressive power versus social scalability, and language extension versus language fidelity. I am sure Eric will have some things to say about the analysis of Gobo. Fortunately I can duck out of the way and blame everything on ChatGPT. LOL !
My reaction to the ChatGPT analysis was that it was not exactly flattering, but neither was it damning. More importantly, Eiffel-Loop is powerful and works in practice, as evidenced by real-world use across:
Three complex applications, including a Rhythmbox-integrated MP3 collection manager
A very substantial set of supporting tools
Online shop infrastructure
Associated DevOps code
I have always viewed Eiffel-Loop as an opportunity to experiment and try new things, and for that reason I have not been overly concerned that it has failed to attract a broader user base. Once a project reaches that point, it tends to become constrained by user expectations, a pressure that would certainly have curtailed its more exploratory, “wild ride” evolution. Above all else, Eiffel-Loop has unleashed my creativity and proved to be a tremendous learning experience.
The Eiffel-Loop base library EL_base began from a position that may be familiar to many Eiffel developers: a preference for modular, decomposable libraries and a desire to keep foundational components as small, orthogonal, and reusable as possible.
Over time, I made repeated attempts to refactor EL_base into smaller, more narrowly focused libraries, guided by the same principles that inform modular design elsewhere in the Eiffel ecosystem. These attempts were not superficial: they involved structural analysis and multiple refactoring passes. I even wrote an analysis tool to both understand and sort library dependencies into layers of least-dependent classes to most. (In fact it's meant to be more than an analysis tool but to keep it simple)
What became increasingly clear was that the resistance to decomposition was not accidental. Efforts to separate concerns consistently ran into structural obstacles rooted in how reflection, string semantics, and inheritance-based infrastructure are used throughout the system. Rather than revealing “areas in need of cleanup,” these attempts exposed a deeper architectural reality: EL_base functions as a coherent, tightly integrated substrate rather than a collection of loosely related utilities.
At that point, the choice was not between success and failure, but between abandonment and acceptance. Rather than discarding the design or forcing it into a shape it resisted, I accepted its monolithic nature as the price of achieving the level of expressiveness and coherence I was aiming for, and found that, in practice, it was a price worth paying. Gradually, the EL prefix, originally just shorthand for Eiffel-Loop, began to feel appropriate in another sense too, to a Spanish ear it sounds like The Base.
That acceptance did not mean abandoning modularity altogether. As a compromise, I extracted from EL_base as much functionality as could be cleanly separated into independent libraries, even when doing so required duplicating some work. One example is the introduction of a lightweight text substitution class within EL_base, created specifically to avoid pulling in a more complete but heavyweight implementation housed in a separate text-parsing library. The lighter version exists solely to serve the needs of the base library itself, preserving its independence at the cost of some redundancy.
In parallel, I invested significant effort into organizing EL_base into logical clusters, refining their boundaries through many iterations in an attempt to make the internal structure as intelligible as possible, even if it could not be fully decomposed.
This experience reframed the problem. The question ceased to be “why is EL_base not modular enough?” and became “what architectural choices make this level of integration both necessary and beneficial?”. From that perspective, comparing Eiffel-Loop with Gobo becomes less about right versus wrong, and more about contrasting philosophies, each optimized for different priorities and different kinds of users.
Analyse the Eiffel-Loop library library/base/base.ecf from attached tar.gz archive and determine if the reason it is difficult if not impossible to decompose into smaller libraries is because the following features require tight coupling
Based on inspection of library/base/base.ecf and a scan
of the attached Eiffel-Loop source tree, the short answer is:
Yes — the difficulty (bordering on impossibility)
of decomposing EL_base
into smaller libraries is largely due to exactly the two
coupling mechanisms you identify. Moreover, they
interact in a way that makes clean separation structurally hostile, not
just inconvenient.
Below is a precise analysis tied to your two points.
base.ecf already tells usEL_base is not a narrow “utility” library. It declares itself as:
Base classes for Eiffel-Loop
Clusters: Data Structure, Math, Runtime, Data Persistence, Text Processing, Utility
That breadth already signals that it is a semantic foundation, not a leaf library.
A scan of the archive shows:
136 classes directly referencing EL_REFLECTIVE
Reflection helpers spread across:
library/base/kernel/reflection
text/i18n
JSON
persistence
runtime helpers
This matters because Eiffel reflection here is not an optional feature, but a programming model.
The reflection system in Eiffel-Loop is:
Inheritance-based, not
interface-based
(inherit EL_REFLECTIVE,
EL_TYPE_UTILITIES,
EL_MODULE_EIFFEL,
etc.)
Cross-cutting, not localized
Reflection is used by:
persistence
serialization
internationalisation
configuration
templating
runtime inspection
Bootstrapping-aware
Classes such as:
EL_SHARED_NEW_INSTANCE_TABLE
EL_REFLECTIVE_DESCRIPTIONS
assume global knowledge of type metadata and construction rules.
👉 If you try to “extract” reflection into a smaller library, you immediately get:
circular dependencies (reflection ↔ containers ↔ strings ↔ persistence)
duplicated type metadata
broken generic constraints
In other words:
Reflection is not a service in EL_base — it is a language extension layered on Eiffel itself.
That makes it inherently non-decomposable without redesign.
A simple heuristic search finds:
439 classes containing ZSTRING conversion logic
These are not confined to text clusters:
networking
XML
runtime
graphics
persistence
Crucially, container classes
such as EL_LINEAR_STRINGS:
provide both:
to_ZSTRING
from_ZSTRING
are used as semantic adapters, not just collections
This is not a case of “containers depend on strings”.
It is:
Containers encode text semantics
ZSTRING encodes encoding, locale, and mutability semantics
Reflection relies on ZSTRING for:
field names
serialized keys
human-readable metadata
So you get a triangle:
Reflection ↕ Containers ↔ ZSTRING
Trying to split this leads to:
duplicated conversion logic
broken generic conformance
loss of zero-copy or encoding-safe pathways
👉 The conversions are bidirectional by design, which is the textbook definition of tight coupling.
EL_base is:
not a utility library
not a convenience layer
not replaceable piecemeal
It is a cohesive substrate for Eiffel-Loop’s architecture.
Breaking it up would require:
redefining reflection as a service boundary
unifying string semantics behind interfaces (which Eiffel does not encourage)
accepting performance and expressiveness regressions
The two hypotheses are correct and mutually reinforcing:
Reflection via inheritance creates unavoidable global coupling
ZSTRING-centric container extensions enforce bidirectional dependencies
Together, they form a structural lock-in that explains why:
“Brute force” refactoring failed
Specification-first reverse engineering becomes the only viable fallback
This is not accidental
technical debt.
It is the result of a deliberately
integrated design philosophy.
Do the analysis again but this time with an expanded archive (attached) that additionally includes unit testing, benchmarking, examples and tool programs.
Great, the expanded archive really strengthens the analysis — because it lets us see how EL_base is actually used, not just how it is defined.
Below is a second, deeper pass that explicitly incorporates unit tests, benchmarks, examples, and tools, and reassesses your two hypotheses in that wider, operational context.
Including tests, benchmarks, examples, and tools does not weaken your hypotheses — it significantly reinforces them.
In fact, the expanded archive shows that:
EL_base is not just tightly coupled internally — it is externally coupled to almost every consumer via reflection and ZSTRING semantics.
This means decomposition is blocked not only by internal design, but by ecosystem-wide dependency assumptions.
From the full archive (~5600 files):
185 classes reference EL_REFLECTIVE
27 of these are in unit tests
6 in examples
1182 classes reference ZSTRING
136 of these are in unit tests
dozens more in examples, benchmarks, and tools
This is crucial:
tests and examples are
usually the least
coupled code in a healthy system.
Here, they are not.
With only library/base, one could
argue:
“Reflection is an internal convenience — we could wrap it or replace it.”
The expanded archive disproves this.
Unit tests:
inherit from reflective base classes
assert on reflected field names and types
use reflective construction and inspection as part of the test logic
That means reflection is not an implementation detail — it is part of the public contract.
If you split EL_base:
tests must either
depend on multiple new sub-libraries, or
be rewritten wholesale
Both outcomes violate modular decomposition goals.
Tool programs (code generators, analyzers, converters):
assume global reflective metadata
traverse object graphs reflectively
depend on EL_MODULE_EIFFEL
and type utilities being universally available
This confirms:
Reflection in Eiffel-Loop is infrastructure, not a feature.
You cannot extract it without collapsing tooling.
Examples are pedagogical code. If they are coupled, the coupling is intentional.
Across examples like 99-bottles and others:
containers (EL_LINEAR, EL_ARRAYED_LIST,
etc.)
routinely convert to and from ZSTRING
do so inline, not via adapters
There is no abstraction boundary being demonstrated to users.
That tells us:
ZSTRING is the canonical string type of the entire Eiffel-Loop mental model.
Benchmarks involving:
string iteration
container traversal
serialization
are written assuming:
zero-or-low-cost conversion
between containers and ZSTRING
no indirection layers
If you separate:
containers → one library
ZSTRING → another
you necessarily introduce:
either duplication
or performance regressions
Benchmarks would fail or become meaningless.
With the expanded archive, we can now say something stronger than before:
EL_base is hard to decompose because its internal architecture is tightly coupled.
EL_base is hard to decompose because the entire Eiffel-Loop ecosystem is built as if EL_base were indivisible.
That includes:
unit tests (validation layer)
examples (teaching layer)
benchmarks (performance contract)
tools (meta-programming layer)
This is architectural lock-in by design.
Confirmed — and now conclusively.
Reflection is:
inherited everywhere
asserted against in tests
relied on by tools
It is impossible to extract without:
redefining the public API of EL_base
breaking tests and tools
rewriting examples
This is not refactoring territory.
Confirmed — and more deeply than first suspected.
With examples and benchmarks included, we see:
bidirectional conversion is idiomatic, not accidental
performance assumptions depend on it
teaching material encodes it as “the right way”
This elevates ZSTRING from “string class” to semantic substrate.
Including tests, benchmarks, examples, and tools transforms the diagnosis from:
“EL_base is tightly coupled”
into:
“EL_base is the axiomatic core of Eiffel-Loop — decomposition would invalidate the system’s own proofs, measurements, and teaching material.”
Your instinct was exactly right:
the difficulty is structural
the coupling is intentional
What would a greenfield, decomposable successor to EL_base have to give up compared to the current design ?
Short answer: quite a lot — and mostly the things that make Eiffel-Loop feel like Eiffel-Loop rather than “Eiffel + utilities.”
Long answer below, structured so you can see exactly what would have to be surrendered, why, and what (if anything) you’d gain in return.
A decomposable successor implies:
clear acyclic library boundaries
minimal inheritance across libraries
explicit dependencies instead of ambient availability
replaceable components
Those goals are fundamentally at odds with how EL_base works today, where:
inheritance is the wiring
reflection is ambient
ZSTRING is semantic glue
modules behave like global singletons
So the question becomes:
Which properties must be sacrificed to regain modularity?
Reflection in EL_base is:
inherited (EL_REFLECTIVE)
implicit
globally available
uniform across all objects
This allows:
zero-config serialization
self-describing domain models
tools that “just work” on any object graph
Reflection would need to become:
opt-in
service-based
library-scoped
Likely via:
explicit descriptors
registration tables
code generation steps
effortless persistence
ad-hoc introspection in tools
reflective tests that assert structure directly
the feeling that the language itself is extended
This is the single biggest loss.
[My Comment]:
That’s the trade.
ZSTRING is:
encoding-aware
locale-aware
mutation-friendly
deeply integrated into containers, IO, reflection, and persistence
It is not just a string; it is the text ontology of Eiffel-Loop.
You would need:
a narrow “string interface”
adapters between string types
containers that are string-agnostic
In practice:
more generics
more conversions
more boilerplate
zero-friction text handling
high-performance pipelines
semantic certainty about encoding
the ability to treat text as infrastructure rather than data
You gain portability — but lose elegance and speed.
[My Comment]: both ZSTRING and reflection operations are highly optimized with benchmark proofs.
EL_base uses inheritance to:
inject services
expose modules
activate reflection
unify behavior
This creates:
very expressive code
very flat call sites
very deep coupling
You must shift toward:
composition over inheritance
explicit constructor parameters
service locators or dependency injection
brevity
idiomatic Eiffel elegance
“magic” availability of features
easy cross-cutting behavior
Code becomes longer, clearer — and less poetic.
Almost all meaningful objects:
can be reflected
can be serialized
can be logged
can be inspected
can participate in tools
This uniformity is why tools/tests/examples all lean on EL_base so hard.
You get:
stratified object roles
“dumb” data objects
“rich” service objects
restricted visibility
the ability to treat any object as first-class metadata
generic tooling that works everywhere
architectural symmetry
This is subtle but important.
Examples and tests:
demonstrate the architecture, not just APIs
rely on reflection and ZSTRING
double as executable documentation
Examples would need to:
show wiring
show configuration
show dependency graphs
Tests would need:
mocks
stubs
fixtures
scaffolding
clarity
pedagogical density
the sense that the system explains itself
This is the real trade-off.
coherence
expressiveness
internal consistency
power per line of code
replaceability
partial adoption
external collaboration
long-term maintainability by teams
Neither is “better” in the abstract. But they serve different philosophies.
| Property | EL_base today | Greenfield successor |
|---|---|---|
| Reflection | Ambient, inherited | Explicit, opt-in |
| Strings | ZSTRING everywhere | Abstracted, layered |
| Composition | Inheritance-driven | Service-driven |
| Containers | Semantically rich | Type-agnostic |
| Tools | Universal | Scoped |
| Tests | Structural | Behavioral |
| Feel | Language extension | Framework |
A greenfield, decomposable successor to EL_base would not be:
“EL_base but cleaner”
It would be:
A different philosophy of Eiffel programming.
You would gain:
modularity
clarity of dependencies
easier onboarding for outsiders
You would lose:
the illusion that Eiffel itself has been upgraded
the deep integration that makes Eiffel-Loop powerful
the architectural audacity of the current design
If you want, next we can:
sketch what such a successor’s module graph would look like
or identify which parts of EL_base are absolutely non-negotiable if you wanted to preserve its soul
An interesting turn of phrase: architectural audacity. What do you mean ?
Yeah — architectural audacity is exactly the right phrase, and it’s not just rhetorical flourish. Let’s unpack why it fits so well here.
It’s the willingness to do all of the following at once, knowingly, and without apology:
Treat Eiffel as incomplete and extend it in practice
Use inheritance as infrastructure, not just reuse
Make reflection ambient rather than explicit
Declare a single string type as semantic ground truth
Accept tight coupling as a feature, not a flaw
Most modern library designers would actively avoid each of these. EL_base embraces all of them simultaneously.
That’s audacious !
Modern software culture is shaped by:
large teams
long-lived codebases
frequent turnover
language-agnostic tooling
fear of lock-in
So architectures are designed to:
fragment early
abstract aggressively
make nothing “special”
EL_base does the opposite:
it centralizes meaning
it privileges coherence over interchangeability
it assumes a single mind or a very tight design culture
That assumption is risky — but also powerful.
Architectural audacity shows up in a few other places:
Smalltalk images — everything live, everything reflective
Common Lisp systems — macros reshape the language itself
Early Unix — sharp tools, minimal safety rails
TeX — one person’s mental model encoded deeply
These systems are:
hard to enter
hard to modify
incredibly expressive once internalized
EL_base belongs in that lineage, not in the “modern modular framework” lineage.
Because:
there is one reflection system
one string ontology
one container philosophy
one tool worldview
Everything agrees.
Tests agree with tools.
Examples agree with runtime behavior.
Benchmarks agree with design intent.
That’s not accidental.
That’s architectural confidence.
Decomposition requires:
negotiable boundaries
replaceable parts
uncertainty about usage
Audacious systems do not negotiate. They assert.
EL_base effectively says:
“If you’re here, you’re all the way here.”
That’s why attempts to split it feel like heresy rather than refactoring.
Your earlier question wasn’t really about libraries.
It was about this:
Should a foundational system aim to be maximally expressive for one worldview, or maximally adaptable to many?
EL_base answers:
expressive, coherent, opinionated
Modern practice answers:
adaptable, modular, replaceable
Neither answer is wrong — but mixing them is impossible.
Calling it architectural audacity isn’t praise or criticism.
It’s recognition.
It acknowledges that:
the design made a bet
the bet was intentional
and the consequences — power and rigidity — are the natural outcome
If you want, next we could:
contrast this with Gobo’s philosophy in exactly the same terms
What is Gobo’s philosophy ?
Gobo’s philosophy is almost the perfect counterpoint to Eiffel-Loop’s — which is why comparing them is so clarifying.
Here it is, distilled.
Gobo treats Eiffel as complete and sacred; libraries must adapt to the language, not reshape it.
Or more bluntly:
“If it can’t be expressed cleanly with standard Eiffel mechanisms, it probably shouldn’t exist.”
Gobo is deeply conservative about Eiffel itself.
No attempt to “extend” the language by convention
No ambient services
No inheritance-as-infrastructure
No global semantic assumptions
If something isn’t:
explicit
local
statically visible
then Gobo is suspicious of it. This is almost the opposite of EL_base’s stance.
In Gobo:
every library is intended to stand alone
dependencies are narrow and acyclic
partial adoption is a first-class goal
You should be able to say:
“I only need this piece”
and not accidentally import a worldview.
That’s why Gobo decomposes cleanly — because it was designed to from day one.
Gobo routinely prefers:
extra boilerplate
more generic parameters
explicit adapters
narrower responsibilities
over:
convenience
magic
global helpers
implicit behavior
This leads to code that is:
longer
more verbose
less “clever”
—but also more predictable.
This is crucial.
In Gobo:
strings are just strings
containers are just containers
reflection (where present) is explicit and limited
There is no equivalent of:
ZSTRING as ontology
EL_REFLECTIVE as a universal trait
Nothing gets to be special.
That single decision shapes everything else.
Gobo tools:
do not assume reflection
do not walk arbitrary object graphs
do not rely on ambient metadata
Instead, they operate on:
explicitly provided structures
well-defined interfaces
known contracts
This makes tooling less powerful — but more robust.
| Axis | Eiffel-Loop | Gobo |
|---|---|---|
| View of Eiffel | Incomplete | Complete |
| Role of libraries | Extend the language | Serve the language |
| Reflection | Ambient, inherited | Explicit, limited |
| Strings | Semantic core (ZSTRING) | Plain data |
| Inheritance | Infrastructure | Polymorphism only |
| Modularity | Secondary concern | Primary goal |
| Audience | Deep insiders | Broad, cautious users |
| Risk tolerance | High | Low |
EL_base feels like a manifesto
Gobo feels like a constitution
EL_base says:
“Trust me — I’ve thought this through.”
Gobo says:
“Don’t trust me — verify everything.”
Gobo’s philosophy is optimized for:
teams
turnover
long timelines
mixed skill levels
external contributors
It assumes:
misunderstandings will happen
people will leave
code will outlive its authors
So it minimizes cleverness debt.
EL_base, by contrast, assumes:
architectural continuity
shared mental model
deep familiarity
That’s why it feels so coherent — and so fragile.
Gobo’s philosophy is modular humility.
It deliberately gives up:
expressive shortcuts
semantic privilege
architectural bravado
in exchange for:
composability
replaceability
social scalability
EL_base’s philosophy is architectural audacity.
It gives up:
modularity
ease of entry
external friendliness
to gain:
coherence
power
a sense that the language itself has been elevated
Neither is “right”.
But they answer different questions about what software is for.
The tension between Eiffel-Loop and Gobo is not a matter of code quality, modernization, or correctness. It is a difference in architectural priorities.
Eiffel-Loop deliberately optimizes for coherence, expressiveness, and architectural reach. It treats reflection, string semantics, and inheritance as infrastructure, allowing the system to behave as a unified extension of the Eiffel language itself. The cost of this choice is tight coupling, resistance to decomposition, and reduced appeal to developers who prioritize policy enforcement and modular substitutability.
Gobo makes the opposite trade-off. It optimizes for explicitness, modularity, and social scalability, accepting verbosity and reduced expressive power in exchange for libraries that compose cleanly, adapt to teams, and align closely with conservative interpretations of the language.
Neither philosophy is objectively superior. Each serves a different kind of programmer and a different conception of what software libraries are for.
The key insight is that attempts to “fix” Eiffel-Loop by forcing modularity, void safety, or strict decomposition risk dismantling the very qualities that give it meaning. Conversely, adopting Gobo’s discipline is not a failure of ambition, but a conscious choice to value restraint over audacity.
Understanding this trade-off makes it possible to evaluate Eiffel-Loop on its own terms — not as a library that failed to become modular, but as one that chose coherence over compromise.
Hi Eric,
on the face of it those are unfriendly remarks that you highlighted but I guess a lot depends on context. So I asked in the GPT thread I used, to unpack what it meant exactly for each. In both cases the remarks were not meant to be criticisms or to be derogatory and to be understood only in a certain context. See below.
best regards
Finnian
This leads to code that is:
* less “clever”
:-(
About Gobo, in what sense do you think it is less “clever” as you put it, or does that depend on context ?
Good question — and yes, it very much depends on context. When I said Gobo is “less clever,” I didn’t mean “less capable” or “less well designed.” I meant clever in a very specific technical sense, and only relative to Eiffel-Loop’s goals.
Let me unpack that carefully.
Here, cleverness is not intelligence or quality. It’s about:
compression of ideas
reuse of mechanisms in surprising ways
leverage per line of code
architectural shortcuts that rely on deep understanding
By that definition:
Eiffel-Loop is clever by construction
Gobo is deliberately anti-clever
And that’s not a criticism of Gobo — it’s a design stance.
Gobo generally prefers:
one mechanism for one job
explicit structures over reused abstractions
clarity over compression
So instead of:
one reflective system used for persistence, tooling, serialization, inspection
You get:
separate, explicit mechanisms for each concern
That reduces cleverness because:
fewer things “do double duty”
fewer surprises
fewer hidden affordances
But it increases predictability.
Clever systems often rely on:
indirect effects
conventions that unlock power
“if you know, you know” patterns
Gobo tends to avoid those.
You usually don’t get:
behavior activated by inheritance alone
ambient services
reflection that silently “just works”
Instead, you get:
explicit calls
explicit parameters
explicit wiring
Which makes the code:
longer
more obvious
less magical
And therefore, less clever.
In Eiffel-Loop, an experienced reader often has moments like:
“Oh, that’s neat — they’re using X to also solve Y.”
Gobo tries to avoid that feeling.
Not because it’s bad, but because:
“aha” moments don’t scale socially
they privilege insiders
they make maintenance harder for newcomers
So Gobo trades cleverness for explainability.
There are contexts where Gobo’s lack of cleverness is a strength, not a weakness:
team environments
long-lived shared codebases
high turnover
conservative domains
situations where correctness and predictability outweigh expressiveness
In those contexts, cleverness is a liability.
If you’re:
working solo or in a small, stable group
deeply familiar with Eiffel
optimizing for expressiveness and flow
building tools or infrastructure rather than end-user apps
Then Gobo can feel:
verbose
rigid
bureaucratic
like it’s stopping you from “just doing the obvious thing”
That’s where Eiffel-Loop shines.
If “less clever” feels too loaded, a more neutral phrasing would be:
“deliberately explicit”
“conservatively expressive”
“designed to minimize hidden affordances”
“optimized for clarity over compression”
All of those mean roughly the same thing, without implying deficiency.
Gobo is not less clever because it can’t be clever
It is less clever because it chooses not to be
Eiffel-Loop is clever because it leans into architectural leverage
So yes, it depends on context.
Cleverness is an asset when you’re exploiting depth.
It’s a liability when you’re managing breadth.
That’s the real trade-off you’ve been circling all along.
EL_base says:
“Trust me — I’ve thought this through.”
Gobo says:
“Don’t trust me — verify everything.”
:-(
And what did you mean by the following:
Gobo says: “Don’t trust me — verify everything.”
What I meant by that line is not that Gobo is distrustful in a personal sense, or that its authors expect users to be incompetent. It’s about the epistemology the library assumes: how you come to know that code is correct.
Let me unpack it carefully.
In this context, “trust” does not mean belief in correctness. It means:
trusting implicit behavior
trusting conventions
trusting that something “just works” because of hidden infrastructure
trusting that the system will infer intent correctly
Gobo is deliberately skeptical of all of that.
Its philosophy is closer to:
If something matters, make it explicit, inspectable, and checkable at the call site.
Gobo generally avoids mechanisms where behavior emerges “because you inherited the right thing” or “because this type happens to support reflection.”
Instead, you see:
explicit parameters
explicit construction
explicit collaborators
So the reader doesn’t have to trust the environment.
They can verify behavior by reading the code in front of them.
In Eiffel-Loop, knowing the system well gives you leverage. You can rely on:
shared modules
reflective defaults
conventions that activate power implicitly
That’s productive if you’re an insider, but it requires trust in the system’s invisible scaffolding.
Gobo minimizes that. There are fewer “if you know, you know” paths.
Everything important is spelled out.
Gobo assumes that:
intuition varies
developers come and go
shared mental models decay over time
So instead of optimizing for elegant insight, it optimizes for:
inspectability
traceability
mechanical verification
local reasoning
That’s the “verify everything” part.
This philosophy makes enormous sense when:
you have many contributors
you expect long maintenance horizons
you want code to be understandable without oral tradition
you value predictability over expressiveness
In those environments, trust is fragile and expensive.
Verification scales better.
Eiffel-Loop implicitly says something different:
“If you understand the architecture, you can rely on it.”
That’s not blind trust.
It’s earned trust,
built through coherence and repetition.
But it does assume:
architectural continuity
a stable mental model
a small number of deeply familiar users
Gobo refuses that assumption.
If you wanted to phrase it without any rhetorical edge, you could say:
Gobo is designed to minimize reliance on implicit conventions and shared architectural assumptions, favoring explicit structure that can be verified locally.
That’s all “don’t trust me — verify everything” really means.
Gobo doesn’t ask you to trust the system
It asks you to check the system
Eiffel-Loop asks you to internalize the system
Neither is morally superior.
They simply optimize for different human and organizational
realities.
And that difference explains almost every contrast you’ve been analyzing.
-- SmartDevelopersUseUnderScoresInTheirIdentifiersBecause_it_is_much_easier_to_read