Information Leakage and Dependencies

56 views
Skip to first unread message

Diego Tsutsumi

unread,
Feb 10, 2025, 4:55:53 PMFeb 10
to software-d...@googlegroups.com
Hi John, I don't think I need to repeat all the good things others said about your book, I just finished chapter 5 and I really like clarity and the concepts presented. I'll post comments as I read rather than putting all comments together into a single thread.

A first impression feedback I have is the way you frame, define and communicate the principles (as far as chap5). Chapter 5 reads to me as if every information shared among the modules "are 100% wrong", but we need exceptions to make software work, which is told to readers only at the end on the "Taking it too far". I also got a similar impression in chapter 3 where you say something like "unfortunately not all modules are 100% independent...".

I feel we need a better way to frame the principles so that it's very hard to "Take it too far", which is a difficult task, but let me make a humble suggestion:

Information leakage is very dependent on the way modules are split and interfaces are defined. In my opinion suggesting a way to split modules and build interfaces would automatically address information leakage, any information shared among modules that aren't following that principle would be a leakage.

In chap 3, a very related topic to information leakage is dependencies (maybe should be put into the same principle? haha). The goal I put when designing dependencies is not minimizing themselves, but rather minimizing future changes on the dependency graph and module split. That minimization should give you "the correct split and dependency graph" given current understanding, which might be drastically different design than minimizing the total number of dependencies.

Tying back to my first impression, aiming for a minimal number of dependencies automatically adds a need for a "Taking it too far" recommendation that is "easy to fall into". While aiming for minimizing future changes in a dependency graph would make it harder to to "Take it too far".

Thank you! I'll keep reading the book, I'm enjoying it so far.
Diego Tsutsumi

Diego Tsutsumi

unread,
Feb 11, 2025, 6:48:26 PMFeb 11
to software-d...@googlegroups.com

I have now finished the book and am following up on feedback for other chapters. I have spotted many good stuff that I agree with, but I'm only writing topics I found worth a constructive conversation.


Sorry for my relatively raw notes below, they are first hand comments without much rewriting not re-structuring.


--


Section 6.3 uses open and closed principle, which is a clearer way to frame the improvement. The property of "having fewer methods" doesn't capture the benefits of the new design, it's a better split of responsibilities that in this case happens to have fewer methods.



Section 6.4 I wouldn't say generality leads to better information hiding, but the "correct module split and interfaces" lead to that. This is a case where splitting modules and adding a dependency between them is super beneficial, because it removes the need for changing the interfaces in future use cases. A good design minimizes the need of changing it in the future.



Section 6.5: I didn't think less methods imply more general purpose interface, you could have a very specific method being the single one in the interface. A better definition would be how many use cases it covers.



Section 6.6 It's hard to see an up and down direction for a general dependency graph. I wouldn't say up or down here, but to the edges of the graph. A good usage of "final class" Java keyword class is an example of being aware of edges vs core as distinct types of modules.



Section 7.1 "distinct and coherent set of responsibilities" is one way to say "the correct module split and interfaces" I refer to in my comments, I think that's central to good software design. This is the core the book seem to avoid defining in a more crisp way, it talks briefly in chapter 21 about it.


Chap. 7 I don't think decorators add much complexity, their interface is exactly the same as the original one, so that callers are already dealing with that interface. I'm not too allergic to shallow modules if they are at the edge and have few dependers. Indeed it's best to always rethink the module responsibility scope, and after rethinking it's quite common to reach to a conclusion a decorator is a good solution. Decorators only add interface duplication in a Java codebase because Java libraries don't offer a good way to handle it. Python decorators (for functions) have a lot of boilerplate hidden away in more generic libraries than Java.


Section 8.3 again an easy principle to overdo (aligning with my previous email in this thread). Pulling complexity downwards is really another case of designing "the right module split" and or "the right responsibility split". Analogous to information leakage concept, this can be viewed as Problem leakage. Which I think is addressed by a principle similar to "what is the responsibility split that minimizes future changes", this principle, in my experience, often correlates with "single responsibility" and "open for extension and closed for modification" principles. 


Section 9.7 that's exactly single responsibility principle. Maybe we need a concept of "atomic responsibility" to avoid breaking a single atom into nonsense.


Chapter 10 I'm also allergic to excessive exception handling! Have you thought about Monadic patterns here like Optional or Result? I think they offer cleaner ways of handling errors. It does exactly what your example of TCL unset does in section 10.3


Section 12.1 I disagree with the statement that adding a bunch of private shallow methods to "name" blocks of code adds complexity. I've seen multiple cases similar to "a complex non-obvious REGEX wrapped around an understandable function name" that significantly decreased cognitive load, even though makes code inner dependencies tiny slightly more complex.


Chapter 21 pull that entire chapter up to early in the book. I think "deciding what matters" is the single most important topic in software design. It guides engineers on "what is the correct module/problem split".


Stuff I wish I saw in the book:


- Functional programming examples. Monads can solve error handling in a similar way you propose. Some other functional patterns like immutability, pure functions, are concretions of principles described in the book.


- A richer variety of problems, I can almost count on my fingers the few examples that were repeated throughout the book.


- Problem decomposition techniques. There's a lot of content on the surroundings of that, such as, examples of how a system becomes more complex if you make bad choices. But the core, as preface tells, of problem decomposition is not developed much. I think that's crucial to produce "the correct module split".


Thank you!

Diego Tsutsumi

Reply all
Reply to author
Forward
0 new messages