notes-books-beautifulArchitecture

notes from chapter 2 of "Beautiful Architecture: Leading Thinkers Reveal the Hidden Beauty in Software Design", "a tale of two systems: a modern day software fable) by Pete Goodliffe:

at the microlevel

interaction between the microlevel and the global level

execution paths should not cross over multiple modules in unpredictable ways

at the global level

the system as a whole should have a comprehensible design. symptoms of incomprehesibility:

the system as a whole should have a written "map". the map should look as little like spaghetti as possible.

when looking at the map, there should not be "many routes to get from one end of the system to the other" without it being obvious what the preferred route is (?: why would you want to "get" from one end to the other? what entity is traveling?)

functionality and data should be located at the "right place", e.g. something that you would consider a "core service" should be implemented in the system's hub. (bayle: i would say that both this and the previous is like Python's "only one obvious way to do it"; the point is that something should be implemented where you expect it to be, a principal of least surprise which allowed the design to be "compressed" into a small mental workspace, because you can omit storing the parts that can be correctly guessed in your mental workspace, and the principal of least surprise maximizes the amount that can be guessed) note: sometimes putting code in the "right" place entails extra work over putting it in a more convenient, but less tasteful place. this is worth it in the long run.

the system should be extensible; when you want to make a change, you shouldn't have to choose between an ugly hack on the one hand, and a major refactoring of the system on another

"good software design limits the lines of communication to only those that are absolutely necessary. these communications lines are part of what determines the architecture."

you should be able to "bring up a skeletal system without creating every single component"

the top-level file structure should make sense

at the module and module interface level

modules should have an easily-understandable function, a "clearly defined role"; knowing this, it should be possible for people to predict which module a given piece of functionality is in. modules shouldn't feel like grab bags of unrelated functionality.

when possible, the system should have layering. when possible, communication between modules should be unidirectional, not bidirectional. components should communicate through interfaces, not "reach into the innards" of each other (bayle: a mental model of volumes which can only interact through their perimeters).

modules should "make sense in isolation"

write down interfaces between modules

in general

there should be "unifying concepts drawing the separate parts together" (?)

data should be "kept near where it is used" (?: what do you mean, data is "kept"?)

minimize duplication

cohesion should be maximized, coupling should be minimized. cohesion is "a measure of how related functionality is glued together and how well the parts inside a module work as a whole". coupling is "a measure of the interdependency between modules, the amount of wiring to and from them". (bayle's note: like the Fischer's linear discriminant criterion).

you should be able to change one part of the code without it necessitating a change in many other parts

the inital steps in the process of designing

the process of designing continues beyond this. if you use iterative development, design continues in each iteration of iterative development. following YAGNI, if you use iterative development, don't make a complicated design up front, because it's not simple, and you don't have enough information about what you'll need yet. "One of the worst things you can do is design something you don't yet understand."

The architecture should not be set in stone; "Change it if you need to. To be changable, the architecture must remain simple. Resist changes that compromise simplicity."

"Defer design decisions until you __have__ to make them. Don't make architectural decisions when you don't know the requirements yet. Don't guess."

"design for testability"; the requirement that every piece of code be unit tested enforces good structure, because it ensures that each unit which is testable must be able to be constructed without constructing the rest of the system.


not from that chapter but,

Tom Demarco's definition: "An architecture is a framework for the disciplined introduction of change." -- http://www.systemsguild.com/GuildSite/TDM/Architecture.html

also, Software architecture in practice By Len Bass, Paul Clements, Rick Kazman

notes that you should start implementation by implementing a "skelaton" of the modules of the architecture, which shouldn't do much, but it should exercise the communications paths defined in the architecture (i think Goodliffe thought this too but i'm not sure if he said it as clearly)

they also say you should:

---

see also [[notes--computer--programming--softwareArchitecture?]].