Id,AcceptedAnswerId,CreationDate,Score,ViewCount,Body,Title,Tags,AnswerCount,CommentCount,FavoriteCount,ClosedDate
"455807","","2024-11-23 13:33:24","0","35","
I am reading "Fundamentals of Software Architecture" by Mark Richards & Neal Ford. They introduce the notion of an architectural quantum (p 92):
An independently deployable artifact with high functional cohesion and synchronous connascence.
Let's break that apart.
By independently deployable they mean it includes "all the necessary components to function independently from other parts of the architecture". They don't define "to function", but it is stated that "if an application uses a database, it is part of the quantum because the system won't function without it."
By high functional cohesion they mean "how well the contained code is unified in purpose."
By synchronous connascence they draw on a little-known measure of coupling—connascence—introduced in "What Every Programmer Should Know About Object-Oriented Design". Confusingly, for the purpose of their definition, they repurpose the term "connascence" to denote coupling on a higher-level architectural component level, e.g., a software package. Synchronous connascence (coupling) then implies "synchronous calls within an application context or distributed services" which prevent choosing meaningful differing "architectural characteristics" (the author's preferred name for non-functional requirements) for different components. For example, they state: "If the caller is much more scalable than the callee, timeous and other reliability concerns will occur."
I'm a sucker for good definitions with clear delineations (I'm an architect after all). But, at a glance, I see several problems with the proposed terminology:
- "To function" is ill-defined and depends on an ambiguous scope of functionality, which goes beyond the deployed artifact, to consider. The authors imply here that in microservice architectures a single microservice can "function" independently. But, even in an appropriate microservice decomposition, parts of an end-user's workflow will still stop "functioning", even if only temporarily in case eventual consistency is applied, if some of the dependent services are unavailable.
- Is there value in using a different name for the same concept at a different level of abstraction? I.e., connascence vs. coupling? Personally, I always understood "coupling" as a concept which can be applied to any level of abstraction in a codebase, i.e., within functions, between functions, between classes, or implicit knowledge a developer needs to know for two different parts of the codebase (semantic coupling). If connascence is a specific measure of coupling, why overload that term?
- This definition seems to mix architectural goals with a way to classify existing architectural components.
While reading this, I kept thinking: isn't this just a subsystem? As in, "subsystem decomposition", and "deployment diagrams" in UML (emphasis mine).
In UML models, subsystems are a type of stereotyped component that represent independent, behavioral units in a system. Subsystems are used in class, component, and use-case diagrams to represent large-scale components in the system that you are modeling.
Certainly, I appreciate the attempt at a more precise definition, since UML keeps it intentionally vague:
Definitions of subsystems may vary among different domains and software methods. It is expected that domain and method profiles will specialize this element.
But, I have a hard time understanding how the notion of "architecture quantum" can improve architectural discussions (especially given the esoteric definitions it relies on) over pre-existing terminology such as "subsystem", "coupling", "non-functional requirements", "deployment", "microservice", and "eventual consistency".
In what ways is "architecture quantum" more specific or meaningful than "subsystem" or "microservice"?
","In what way is an ""architecture quantum"" distinct from UML subsystems?","","2","0","",""
"452353","","2024-03-08 16:01:11","1","132","I have been doing a lot of thinking lately about the implications of event-based/responsive programming and UML statecharts.
I believe my thinking up to this point has been flawed. Take, for example, a toggle button/switch. It has an internal state: pressed or released. It also generates events: press and release. The events represent the transitions between states. Up until now, if I were to design a state machine that "reacted" to the button's state changes, but I needed a particular transition to be conditionally based upon the current state of the button, I would "query" the internal state of the button as part of a conditional transition/pseudostate (e.g., if the button were a class, the state machine would directly call button.state() before making its transition).
I now think that this is flawed approach because it exposes the internal state of the button, couples the other state machine to an implementation (event if it may be abstract) of the button (rather than just reacting to its events), and it "mixes metaphors" by being reactive (to events) while simultaneously being sequential (blocking) programming. This problem becomes more pronounced when the process of "querying" the internal state of something on which to make a decision is not so trivial (or, as mentioned in the book "Practical Statecharts in C/C++", impossible if, for example, you are trying to "view" the state of a quantum particle; the very act resulting in the state being affected).
With that discovery, I am trying to come up with other options that are truly reactive (i.e., based solely upon events).
As an example, suppose I want to design a state machine with 3 states: A, B, and C. It will handle 4 different events: B1_PRESS, B1_RELEASE, B2_PRESS, B2_RELEASE (i.e., events from two toggle buttons). If in state A, B1_PRESS transitions to state B. If in state B, B1_RELEASE transitions to state A. If in state A or B, B2_PRESS transitions to state C. However, when in state C, B2_PRESS transitions either to state A (if B1 is not pressed) or B (if B1 is pressed). In other words, B2 has higher priority than B1 in determining the state.
Option 1
Introduce an extended state variable used to store the current state of B1 based upon the events it produces. Then use a conditional/choice pseudostate to transition based upon this extended state variable.
![]()
The problems I have with this option are a) I have to use an extended state variable and b) The state of B1 is now technically stored twice: once in the button itself and once in my state machine. This might get pretty messy if I need to add more states and events.
Option 2
Defer the B1_PRESS and B1_RELEASE events while in state C.
![]()
This option is cleaner in notation than option 1. It also doesn't add any extended state.
The problem I have with this option is that, if while in state C the state of B1 does change, state B is still "temporarily" entered when exiting state C but before the deferred B1_RELEASE event is processed. So, if the ENTER event of state B does some work, it will be wasted (or could cause weird problems).
Are there other options I have not considered? Is my original "revelation" about trying to work with events only reasonable?
","Deferring/Saving State/Events in UML Statecharts","","2","0","",""
"445188","445202","2023-04-23 17:35:46","0","459","Suppose today I'm designing a new application that will employ asymmetric cryptography to allow users to securely exchange data with one another. As far as I can tell there are no quantum-safe algorithms yet generally accepted, let alone that are ready to be used in production. (Please correct me if I'm wrong!) Thus I'm assuming I'm still looking at RSA as the gold standard. Estimates for when RSA can be cracked vary from 5 to 15 years or more. 15 years doesn't bother me too much, but 5 years does, especially for a new application.
So, if I'm starting from scratch, what would be considered the best practices to be as prepared as possible for a post-quantum world? And to explain what I mean by prepared, I don't simply mean ready to change algorithms, but rather to best ensure that data transmitted today won't be vulnerable in the future.
Two things I've considered -
- Using 4096-bit keys. However I don't see a consensus on whether this actually makes much of a difference even for classical attacks, let alone quantum ones.
- Keeping public keys effectively private. My idea here is to keep even public keys within the confines of the secure application servers and unavailable to users. We would not allow clients to encrypt or verify sender signatures directly, but rather servers would hold public keys as closely as they hold their other secrets. Encrypting and verifying signatures would thus require client API calls.
I'm wondering if these ideas add any genuine security value, or if not why not, and if there are other measures that experts would recommend at this time to architect a new application to be as resilient as possible to the so-called quantum apocalypse.
","Best practices for a new application to be ready for post-quantum cryptography","","2","2","",""
"376458","","2018-08-06 11:12:36","-1","217","Is it possible to create an algorithm that will execute at the same rate and speed on faster and slow computers. What i mean is, i have a year 2000 desktop that can run a certain computational algorithm. a hundred years latter, quantum computers have arrived in their full capacity and i want to run the same algorithm. the Quantum computer should never be able to catch up with the slow computer.
The several ways i can think:
- Locking the execution of an algorithm to a specific time, but the problem with this is someone could possible alter the ticks in a second, eventually making the execution time very small, hence fastening the execution.
- Create a function that only uses a fixed amount on memory. for this i don't know how practical it is.
What could i do to achieve the desired consistency?
","Executing an algorithm constantly on slow and fast machine","","1","3","",""
"367045","367076","2018-03-04 23:09:24","4","1944","A few days ago I found a fun fact, that finding a collision of 256-bit hash using brute-force is physically impossible in solar system.
That made me think, what would happen if we used a good (uniform) 256-bit hash in a hash map. I guess, we could consider, that there are never false key hash matches, so we could get rid of the actual value of key in favor of storing only its hash.
- Would be space efficient? (No value of key, just hash)
- Would it be fast? (No collision check, but bigger hash than usual)
- Would it be safe? (Statistically)
- Has anybody done this?
Yes, there could be way fewer buckets than 2^256. The goal is to calculate the hash, find bucket and then find the actual value inside the bucket using ONLY the full 256-bit hash and without actual value check. For example in hash map where keys are strings, there could be no equality confirmation, so no actual bytes comparison and no potentially big key storage.
There seems to be a lot of disregard towards 2^256 combinations. To give you the scale, the estimated number of atoms in the known universe is between 10^78 and 10^82, roughly 2^260 and 2^270. Humankind will probably never produce all possible 256-bit numbers.
Yes, the quantum computers will be able to find collisions in split seconds. But future cryptographic safety is not the point, the point is simplification of in-memory, std-lib grade collections for internal use in applications.
","Hash map without collision check","