the ideal world

220 views
Skip to first unread message

Paul Becker

unread,
May 11, 2026, 6:17:00 PMMay 11
to software-design-book
Hello all,

There is a part in APOSD which has been bothering me for some time now:

"In an ideal world, each module would be completely independent of the
others: a developer could work in any of the modules without knowing
anything about any of the other modules. In this world, the complexity
of a system would be the complexity of its worst module. /
Unfortunately, this ideal is not achievable. Modules must work together
by calling each other's functions or methods. As a result, modules must
know something about each other. [...] The goal of modular design is to
minimize the dependencies between modules." (4.1)

I don't think that this is a good description of the ideal world; it
takes it too far. Modules that don't interact at all cannot function
together. The goal is a functioning program, and thus any ideal must
still be a functioning program. But the clue to the actual ideal is
right there in the text: "modules must work together," and "the goal
[...] is to minimize the dependencies." I propose something like this
instead:

In an ideal world, each module would be completely independent of most
others: a developer could work in any of the modules without knowing
anything about most of the other modules. In this world, the complexity
of a system would be close to the complexity of its worst module. / This
ideal can be hard to achieve. Modules must work together by calling each
other's functions or methods. It can be difficult to design modules so
that they don't need to know something about each other. [...] The goal
of modular design is to minimize the dependencies between modules.

Thoughts?

paul

Mahmoud Fayed

unread,
May 11, 2026, 6:30:21 PMMay 11
to software-design-book
Hello Paul

>> "I don't think that this is a good description of the ideal world; it takes it too far. Modules that don't interact at all cannot function together."

IMHO, the book description is correct and amazing, 

>> "Modules that don't interact at all cannot function together"

They can, if they are used by a program/system that can call them
For example, think of unix programs where each program could get an input and produce an output
And we can pass the output of a program to another program as input

Also, think of us (humans) we could discover new people, interact with them and learn about them
Programs could apply this pattern and (discover other programs based on need) and interact with them (through a protocol) 

i.e. we can design programs/modules that don't know about other modules (during the design time) but could (interact) with them through input/output or through (discover & use) or (through an external program who manage the process).

>> " In this world, the complexity of a system would be close to the complexity of its worst module. / This ideal can be hard to achieve. Modules must work together by calling each
other's functions or methods"

When we build a programming language we could build a package manager, such packages could be used together even if they are designed by different people for different purpose. 
The point is finding a way of communication but defer it to be at usage time (not design time) 

Simple example: I could use a library for GUI, another library of database, they don't know about each other, but I can write the glue so I can control my GUI to display the data in my database.

Greetings,
Mahmoud

John Ousterhout

unread,
May 11, 2026, 11:21:43 PMMay 11
to Paul Becker, software-design-book
On Mon, May 11, 2026 at 3:16 PM Paul Becker <rainc...@gmail.com> wrote:
Hello all,

There is a part in APOSD which has been bothering me for some time now:

"In an ideal world, each module would be completely independent of the
others: a developer could work in any of the modules without knowing
anything about any of the other modules. In this world, the complexity
of a system would be the complexity of its worst module. /
Unfortunately, this ideal is not achievable. Modules must work together
by calling each other's functions or methods. As a result, modules must
know something about each other. [...] The goal of modular design is to
minimize the dependencies between modules." (4.1)

I don't think that this is a good description of the ideal world; it
takes it too far. Modules that don't interact at all cannot function
together. The goal is a functioning program, and thus any ideal must
still be a functioning program. 

Technically you are right, of course. I exaggerated in order to make a point. When someone says "ideally" they are almost always talking about something that isn't actually practical. In a truly ideal world I would be able to use other modules without having to know anything about them. I have no idea how that could be achieved, but it would be nice, no? :-)

-John-

Mahmoud Fayed

unread,
May 12, 2026, 5:30:20 AMMay 12
to software-design-book
Hello John

>> "In a truly ideal world I would be able to use other modules without having to know anything about them. I have no idea how that could be achieved, but it would be nice, no? :"

Maybe through the next steps
(1) Design/implement each module in isolation from other modules (No knowledge about other modules)
(2) For each module provide an API that can be used with other module (i.e. public - but not known to other modules)
(3) For communication a mix of the next ideas/features could be used
* Reflection ---> To discover public API provided by modules
* Automatic Code Generation (Maybe using Eval() too if we are using a dynamic language)
* Prompts to LLMs (where we could share the modules documentation/API/reflection results with the LLM)

The point is to have a communication between two modules, this could be (direct) or (indirect)
And it it's (indirect) this could be (manual) or (automatic)

I guess if it's (indirect) and (automatic) ---> Then we achieved the goal of designing modules that can work together without knowing each other.
But in reality, a system will know, like the reflection system or LLM, etc.

Greetings,
Mahmoud

Jim Lyon

unread,
May 12, 2026, 12:20:30 PMMay 12
to software-design-book
I'm with John when he describes his ideal, but I also realize that the ideal is not obtainable. In most large projects, there are overarching decisions that affect everything: what's your threading model, your persistence model, your logging / error reporting model, etc. In older C/C++ code bases that pre-date high-quality STL implementations, this even includes things like which string and container classes you will use. Will you throw exceptions, or will you return error codes? How is your system broken up into processes, and how to they communicate? And so forth.

For any individual module, many of these decisions will not affect the interface, but only the implementation. But in a huge number of cases, these "architectural" [scare quotes intended] decisions affect many interface decisions. Ideally, they wouldn't, but in practice they do.

-- jimbo

Paul Becker

unread,
May 16, 2026, 8:41:36 AMMay 16
to software-d...@googlegroups.com

I think that the distinction i'm trying to make is between these two positions:

1. Dependencies are bad. Our work is to eliminate them.

2. Dependencies are essential. Our work is to identify, organize, simplify, and clarify them.

It's not about ideal versus practical---it's about our basic values and where they take us in the extreme.

I don't think that having to know things about other modules is a problem. Learning about and using a good module is one of my favorite experiences in programming. I think that the problem is when that knowledge is difficult to acquire or use---namely, complexity.

Even just the idea of using a module at all---"creating a dependency"---is the essence of modularity. It's a way to manage complexity. Perhaps i am saying that dependencies in themselves aren't a source of complexity, but obscure dependencies are.

Many thanks for the discussion,

paul

--
You received this message because you are subscribed to the Google Groups "software-design-book" group.
To unsubscribe from this group and stop receiving emails from it, send an email to software-design-...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/software-design-book/434e3bf2-8df5-4a52-b70b-741f139a13f0n%40googlegroups.com.

Jim Lyon

unread,
May 16, 2026, 11:11:29 PMMay 16
to software-design-book
It's not that dependencies are intrinsically bad. In fact, they are essential. The problem is that when you draw a graph of the dependencies between modules, your ability to understand and change the system is inversely proportional to [the square of] the density of the graph. Therefore, the job is to minimize unnecessary dependencies.

-- jimbo

PS: Regarding the bracketed phrase [the square of] ...  I believe that your inability to change something increases more than linearly with the density of dependencies, but I don't have empirical evidence to support that statement. Caveat lector.

John Ousterhout

unread,
May 18, 2026, 11:56:10 PMMay 18
to Paul Becker, software-d...@googlegroups.com
On Sat, May 16, 2026 at 5:41 AM Paul Becker <rainc...@gmail.com> wrote:

I think that the distinction i'm trying to make is between these two positions:

1. Dependencies are bad. Our work is to eliminate them.

2. Dependencies are essential. Our work is to identify, organize, simplify, and clarify them.

It's not about ideal versus practical---it's about our basic values and where they take us in the extreme.

I don't think that having to know things about other modules is a problem. Learning about and using a good module is one of my favorite experiences in programming. I think that the problem is when that knowledge is difficult to acquire or use---namely, complexity.

Even just the idea of using a module at all---"creating a dependency"---is the essence of modularity. It's a way to manage complexity. Perhaps i am saying that dependencies in themselves aren't a source of complexity, but obscure dependencies are.


I disagree with this. I don't think there's any such thing as a "good" dependency; we may not be able to get rid of all them but they are all undesirable. Imagine two systems that are identical in every respect except one has an additional dependency not present in the other; can you identify a scenario where the system with the extra dependency is better?

In my view, defining a good module doesn't add dependencies; it eliminates them. Without a clean module, the rest of the system has a large number of dependencies on myriad details of the implementation of the functionality. By defining a clean module we eliminate most of those dependencies, replacing them with a smaller and simpler set.

-John-

Artie Shevchenko

unread,
May 19, 2026, 8:25:32 PMMay 19
to Paul Becker, software-design-book, John Ousterhout
Hi Paul,

I've been wrestling with very similar questions for years, as I found it hard to convince both myself and my students that dependencies are a cause of complexity. Eventually, I evolved John's model a bit. I've retained obscurity there, but replaced dependencies with several more specific practical complexity causes:




I've also added a subjective but at the same time important "Unfamiliarity" cause there, because in practice it's *perceived* complexity that matters most.

Hopefully you'll find this helpful. That's the complexity model that I'm using in my recently published book "Code Health Guardian: The Old-New Role of a Human Programmer in the Al Era."

--
Kind regards
Artie Shevchenko

--
You received this message because you are subscribed to the Google Groups "software-design-book" group.
To unsubscribe from this group and stop receiving emails from it, send an email to software-design-...@googlegroups.com.

Artie Shevchenko

unread,
May 19, 2026, 8:43:38 PMMay 19
to HQ K, Paul Becker, software-design-book, John Ousterhout
Well, as Paul said dependencies by themselves are not bad, it's dependencies that are obscure, unstable, and too many of them that causes issues.

On Wed, 20 May 2026, 10:28 am HQ K, <wan...@gmail.com> wrote:
solution: not dependency injection but dependency extraction :)

HQ K

unread,
May 19, 2026, 8:52:06 PMMay 19
to Artie Shevchenko, Paul Becker, software-design-book, John Ousterhout
solution: not dependency injection but dependency extraction :)

On Tue, May 19, 2026, 5:25 PM Artie Shevchenko <shevchen...@gmail.com> wrote:

Vitor Paciello

unread,
May 20, 2026, 1:34:02 PMMay 20
to software-design-book
Reading the comments in this thread, I believe the root cause of this discussion isn't necessarily the existence or absence of dependencies between modules, but something deeper: the lack of consensus on what is software complexity and how to measure it. Today, we don't have any magic/universal equation that can clearly show us that software A is, for example, x% more complex than software B. Unfortunately, we are still in a world dominated by subjectivity on this topic. What is complex for me, may not be for someone else, and vice versa. In this world of subjectivity, any generalization to more extreme cases (such as, the ideal software) becomes fragile and questionable.

I believe that this topic of "complexity of dependencies" fits well into this scenario of subjectivity. To reduce the number of dependencies, we may end up making changes that increase complexity in other parts of the software. Without effective metrics to measure whether this decrease in complexity at the "dependencies" level compensates for the increase in complexity elsewhere, the answer to the question "are dependencies good or bad?!" remains entirely subjective. It will depend heavily on the type of software and the programmer's prior experience.

But, even if we have direct ways to measure all the causes of complexity in a software, I still believe that dependencies can be good or bad depending on the context in which they are created. Let's consider a very simple example where there are only two measurable types of causes of complexity.
1- BETWEEN-module complexity - the dependencies themselves. The more modules and the more dependencies in a software, the greater the complexity of the software.
2- INTRA-module complexity - measures how difficult it is to understand the code within a specific module. For example, the greater the number of nested "ifs" and "loops", the greater the complexity.

Now let's consider a hypothetical software "A," consisting of a single module responsible for executing all the software's tasks. This single module will contain all the software's code. There will be hundreds, thousands, maybe millions of nested "ifs" and "loops", and no dependencies. The complexity of understanding the code inside this single module (e.g., INTRA-module complexity) is insanely high. In contrast, the "BETWEEN-module complexity" is zero. Once I understand everything this module does, I don't need to understand its connections with any other interface, because they don't exist. Now let's think about possible improvements to this software. Let's take some lines of code that are repeated within this single module and create a new function that is called whenever these parts of the code is executed. This simplifies the code within this single module and consequently reduces the software's "INTRA-module complexity." On the other hand, we create a second module and now we need to understand the dependencies between these two software modules to work on them. So, the "BETWEEN-module complexity" is not zero anymore. In this hypothetical scenario, if the decrease in "INTRA-module complexity" of the software compensates for the increase in the "BETWEEN-module complexity", then adding dependencies becomes good.

Now let's consider another hypothetical software "B," where we take the idea of ​​"one-line per method" to the extreme. In this case, it would be relatively simple to understand what each module does by itself, the "INTRA-module complexity" is very low. On the other hand, this software would have hundreds to thousands modules. And it would require a lot of work to try to understand all the connections among these modules. In this case, the "BETWEEN-module complexity" is extremely high. Now, let's improve this software a little. We can take some similar modules and combine them into a single one. The "INTRA-module complexity" might increase slightly, since this new module would have inside it a few more lines of code than any one-line module. However, the "BETWEEN-module complexity" of the system would decrease, since we would remove some nodes in the entaglement of modules and dependencies of the software. In this case, if the decrease in the "BETWEEN-module complexity" compensates for the increase in the "INTRA-module complexity", then eliminating dependencies becomes good.

Interestingly, we can plot these scenarios on a graph and analyze how complexity varies according to the number of modules/dependencies (figure below).
    Blue line is the "INTRA-module complexity", that decreases with the number of modules in the system.
    Red line is the "BETWEEN-module complexity", that increases with the number of modules in the system.
    Green line is the overall complexity of the software (sum of the two types of complexity causes).

download.png

In this plot, the optimal point of lowest software overall complexity would be obtained at point C. If the software you work with is to the left of it, adding some dependencies may be good. But, if the software is to the right of it, eliminating some dependencies becomes the goal.

In the example, I made an extreme simplification with only two causes of complexity. In the real world, we will have an n-dimensional space to analyze. There will be dozens of causes of complexity competing with each other at different levels and with different measurement methods (if they exists).

In the end, our goal with software design is not to follow a single rule to the extreme. It is necessary to look at the whole picture and try to find an optimal balance between all possible causes of complexity. That tiny little point on a n-dimensional plot that results in the lowest overall complexity of the system. In some cases, it may be necessary to increase a specific type of cause of complexity to achieve a reduction in the overall complexity of the software.

HQ K

unread,
May 20, 2026, 2:04:31 PMMay 20
to Vitor Paciello, software-design-book
photoshop manages complexity: layering :)
2d connections vs 3d layering

John Ousterhout

unread,
May 20, 2026, 2:58:20 PMMay 20
to Vitor Paciello, software-design-book
Hi Vitor,

I mostly agree with the logic in your email, but I think you may have a misconception about dependencies. Dependencies don't just occur between modules; they can occur within a module as well. A large monolithic module probably has complex dependencies internal to itself that must be considered when making changes. I think these could fit under your term "INTRA-module complexity", but your email seemed to imply that all dependencies fall under the category "BEWTEEN-module complexity", and I think that's incorrect. I don't think this nit changes the overall point you make, though.

-John-

Ivan Yordanov

unread,
May 25, 2026, 11:12:54 AMMay 25
to software-design-book
Hello,

About first part of the discussion related to ideal world
I agree with Mahmoud and linux pipeline example. Modules could work without explicitly encoded knowledge of each other. But there must be something in common - usually the output of one must be compatible with input of the other (line in linux pipeline)
Decomposition plays a key role in implementation of ideal world. But after decomposition we need to compose the pieces. If pieces could form a pattern (pipeline/chain, graph/network, recursion, etc.) we can compose them runtime given some more sophisticated input like DSL. Then create an engine that processes given input and invoke decomposed pieces - that's how browsers, databases, spreadsheets, games, AI and many other systems work.
Here are my thoughts on this: https://legacyfreecode.medium.com/solving-essential-complexity-8f932de3a467 (I shared this post earlier).

About dependencies:
I think we should limit their spread in the system. Usually we do this by wrapping them (Adapter, Facade, Decorator, etc.) and use the wrapped object instead of directly using the dependency. In this way we can replace them (when new version is released or better alternative emerge) by changing a single file and in same time fit them in our design (like understanding input from the previous step).
Some more details about this idea: https://legacyfreecode.medium.com/how-to-use-external-libraries-the-right-way-d06becb0736e

Greetings,
Ivan

HQ K

unread,
May 25, 2026, 1:15:38 PMMay 25
to Ivan Yordanov, software-design-book
There must be dependencies, there must be the encoded knowledge of dependency between modules somewhere in the system regardless of whatever method :)
I found there were some debates between the author of OOP/Module Driven Design/Whatever about how and where to define the dependency. 
One thing is up to air, not settled yet, but it was moved forward and entered the industry at scale: define dependency at template level.
Templates are notorious for their complexity but are flexible. Class is template, C++ inventor recently mentioned he did not want C++ support OOP like 1.plus(2). He wanted to support class oriented. Alan Kay neven accepts C++, Java OOP. Tryve, MVC invertor, worked his entire life to improve MVC and worked on DCI, a runtime model to define dependency between objects. In one of Alan Kay's video, he showed that his lab tries to learn how dependency works from bio cells, but never has a satisfactory implementation (how your brain cells "talk" to your muscle cells, general way or specific way in a specific use case). In my domain (game development), our designer wants us to support prefab (object template to create many objects) which is good for "reuse", but like template system, it is super complex when each prefab has script (logic) which might have dependency to other script in child prefabs. everything might be not too bad before instantiating them, but at runtime instantiating them, linking them together, everything is out of control. Fun fact: in that term javascript object is run time object, we can add dependency at run time :)


Jim Lyon

unread,
May 28, 2026, 2:48:30 PM (13 days ago) May 28
to software-design-book
Reasoning about the case where program A produces output consumed by program B (maybe through a pipe, maybe through a file), there is an inevitable dependency between A and B. A must produce something that B can consume, and B must consume whatever A produces.  In a good world, there's a specification defining the data format and semantics. Then A has a dependency on this spec (it is constrained to produce only what the spec allows), and B also has a dependency (it must consume anything allowed by the spec). 

But look at what we have just done: we've replaced one dependency between A and B with two dependencies (each A and B depend on the spec). So I conclude that software quality is not solely about the number of dependencies; it also depends on the nature of the dependencies. Some things that make dependencies bad include:

Vagueness: A produces what B consumes and vice versa is vague. If you have a bug where A produced something that B couldn't consume, whose fault is it? Nobody knows for sure. Introducing a spec for the data transfer replaced one vague dependency with two explicit dependencies. This is usually a win.

Concept Count: A dependency where you need to understand many concepts is clearly worse than a dependency where only understand fewer concepts (usually because somebody on one side of the dependency has encapsulated something). But worse than both of these is a dependency that pretends to encapsulate concepts, but they actually leak through.

Hiddenness: The bane of software maintenance is discovering dependencies that you didn't know exist, and that are not discoverable until after you've changed something and the system no longer works.

And there are lots more.

In my experience, a badly designed system ends up with a dependency count on the order of the square of the number of modules. (Modules, sub-modules, classes, assemblies, I think the observation holds at every level of abstraction). In a well-designed system, the dependency count is more like O(n * log n) in the number of modules. In a great system, it's more like O(n)

Brent Welch

unread,
May 29, 2026, 1:23:10 AM (13 days ago) May 29
to Jim Lyon, software-design-book
These days I do a lot of data analysis - mostly ad hoc in my day to day, but I've built systems that consume data for production reasons.  Database tables are a well formed thing that is equivalent in my thinking to an API.  Something produces information according to a schema, and other users can consume that information. They get to share the schema, and these days there are ways to add things such that consumers do not break.  Removing fields is always problematic, of course, but protobuf and DB schemas have ways to stage deprecation and removal of fields/columns.

In the olden days of Unix pipes the database was a character string with newline termination, and it was and still is quite handy.

All that is to say I am 100% OK with depending on the data model as the spec.  In fact, I think it is a great way to go.  I've seen a lot of good systems built this way, and I've seen systems that got into trouble when they didn't realize that such an interface was in play.  I can give one old example, and one less old.

The system controller for a clustered file system used a database to store configuration information. One day someone changed an Enum in a source file such that X meant Apple instead of Banana. Upon a system upgrade, hilarity ensued. In response, that same software evolved an upgrade/downgrade system where version N+1 could install code that version N would look for and run in order to downgrade the database.  So not only did we have somewhat standard "upgrade the database logic", but we supported downgrade.  I suppose that highlights a problem with data-as-an-interface, which is that it is hard to change schemas.  But every database developer knows that.

A more recent example is where systems emit metrics of all kinds, and other systems observe those metrics and implicitly take dependencies on them.  That's clearly bad, but it happens. "Oh, that's cool, such and such tells me this thing, and I can act on it!  How convenient!"  That ecosystem is great for dashboards and observability, but clearly (heh - no, I never took that kind of dependency, no sir) is not the right way to build systems.

Ciaran McHale

unread,
May 29, 2026, 4:08:27 AM (13 days ago) May 29
to Jim Lyon, Brent Welch, software-design-book
Both Jim and Brent gave their thoughts on having data dependencies instead of API dependencies. Their comments caused me to remember something along those lines...

The Model-View-Controller (MVC) design pattern tries to reduce tight coupling between the Model and View by having the Controller act as a go-between. I have not had reason to use this design pattern in my work, but where I have read about it the most is in the use of string template engines, such as Apache Velocity, when used in a webserver for formatting web pages from the back-end data model. In essence:
- The Model is, say, a database that the web server interacts with.
- The Controller queries the Model and puts name=value pairs into a map.
- The View is an actual webpage that is formatted from the name=value pairs in a map. This is where a String template engine comes into play. It parses a template file containing boilerplate HTML code plus some ${name} placeholders, and it replaces those placeholders with values from a supplied map.

Whenever the Model is modified, the Controller is also modified, so it can still create a map containing the same name=value pairs. There is a cost to writing and maintaining the Controller (which is bad), but it replaces a fragile API dependency of the View on the Model with a more robust data dependency (which is good).

In a sense, a dependency-injection mechanism, such as the Spring Framework, works in a sort-of similar manner: tedious code for initializing and connecting objects is replaced with tedious configuration information (in XML syntax) that declares how the initialization and connective code should behave. In this case, both the Model and View are Java classes,  and the XML configuration file acts as the controller.

Brent mentioned the UNIX philosophy of having independently-developed applications communicate via data in pipes/files as a way of replacing API dependencies with data dependencies, and this has mostly worked. However, there is a gradual tendency for the data in the pipes/files to become more structured over time: instead of the data being lines of text with a newline character to separate records, it is increasingly common for the data to be in XML or JSON format.

Regards,
Ciaran.


Paul Becker

unread,
May 30, 2026, 2:39:46 PM (11 days ago) May 30
to John Ousterhout, software-d...@googlegroups.com

John,

Hopefully this clarifies how i see it:


On 5/18/26 11:55 PM, John Ousterhout wrote:

Imagine two systems that are identical in every respect except one has an additional dependency not present in the other; can you identify a scenario where the system with the extra dependency is better?

I'm not sure that i fully understand the question.

Is this not what you discuss in chapter 9 of APOSD, "better together or better apart?" You give examples where a single module is better split into two modules. Thus a single dependency becomes two. "When deciding whether to combine or separate, the goal is to reduce the complexity of the system as a whole and improve its modularity."

We can separate modules (thus increasing the number of dependencies) and yet reduce complexity.


By defining a clean module we eliminate most of those dependencies, replacing them with a smaller and simpler set.

Yes. That smaller and simpler set of dependencies is good. If they were removed, we would be forced to implement the functionality that they provide within the current module.

Modules are useless without dependencies. Saying that we want no dependencies is equivalent to saying that we don't want modules.


paul

Brent Welch

unread,
May 30, 2026, 8:34:52 PM (11 days ago) May 30
to Ciaran McHale, Jim Lyon, software-design-book
Rather than JSON or XML, I’ve been using Protobuf since joining Google and it is very slick. It handles schema changes nicely so version skew between client and server, or between reader and writer of some persistent data is cleanly handled. The protobuf message definition is your API, and it can be either a direct RPC API with a Request and Response protobuf, or persistent data for a Config, metrics, whatever. As a practical matter, I’m OK with having a dependency that is defined via a robust mechanism like a protobuf

John Ousterhout

unread,
Jun 1, 2026, 11:42:34 AM (9 days ago) Jun 1
to Paul Becker, software-d...@googlegroups.com
Hi Paul,

I think this horse has just about been beaten to death, so we may just have to disagree, but here are are a few comments on your email:

On 5/18/26 11:55 PM, John Ousterhout wrote:

Imagine two systems that are identical in every respect except one has an additional dependency not present in the other; can you identify a scenario where the system with the extra dependency is better?
I'm not sure that i fully understand the question.

This question was designed to show that dependencies by themselves are not good; we accept them reluctantly because they are inevitable and/or they may produce some other benefit that compensates for the dependency. 

Is this not what you discuss in chapter 9 of APOSD, "better together or better apart?" You give examples where a single module is better split into two modules. Thus a single dependency becomes two.


You seem to be equating "number of modules" with "number of dependencies", but a single module can introduce many dependencies. Thus, splitting a module into two modules does not necessarily increase the number of dependencies.
 

"When deciding whether to combine or separate, the goal is to reduce the complexity of the system as a whole and improve its modularity."

We can separate modules (thus increasing the number of dependencies) and yet reduce complexity.

If separating modules really increases the number of dependencies, then it probably doesn't reduce complexity.

-John- 

Paul Becker

unread,
Jun 1, 2026, 1:12:39 PM (9 days ago) Jun 1
to John Ousterhout, software-d...@googlegroups.com
On 6/1/26 11:41 AM, John Ousterhout wrote:
You seem to be equating "number of modules" with "number of dependencies", but a single module can introduce many dependencies. Thus, splitting a module into two modules does not necessarily increase the number of dependencies.

Here is the specific scenario that i was picturing:

A depends on B

We split B into two modules: B' and C. Now:

A depends on B'
A depends on C

Module A has gone from one dependency to two.

I don't say this as a rule, but as a possible outcome.


I don't think that you've addressed my main complaint, which is "If [all external dependencies] were removed [from a module], we would be forced to implement the functionality that they provide within the current module."

paul

John Ousterhout

unread,
Jun 2, 2026, 12:54:53 PM (8 days ago) Jun 2
to Paul Becker, software-d...@googlegroups.com
On Mon, Jun 1, 2026 at 10:12 AM Paul Becker <rainc...@gmail.com> wrote:

I don't think that you've addressed my main complaint, which is "If [all external dependencies] were removed [from a module], we would be forced to implement the functionality that they provide within the current module."

I agree with this; dependencies cannot be completely avoided. But that doesn't mean that dependencies are a good thing. I think of them as the lesser of several evils; they allow us to avoid other problems that are even worse.

-John-
Reply all
Reply to author
Forward
0 new messages