Just write the version that inspires you most. You can always refactor afterwards.
The first version has the advantage that it fits the immediate needs. The inconvenience is that it hardwires Application by coupling it to some global objects (hidden dependencies). This reduces the reusability and requires to know about the internals of that class.
It depends on your design intention:
If ApplicationState and Dimension address different concerns and may evolve due to different reasons, then it is fine.
Likewise, if ApplicationState is just there for using a Dimension with another interface/protocol, then it is an adapter and is also fine.
If ApplicationState is nothing else than a specialized ...
"Separating out code into separate files" would cover it.
C calls them "compilation units". Java tries to enforce one class per file. C# encourages this but does not require it. Python calls them "modules". And so on.
const emailService = process.env.NODE_ENV === 'production' ? new EmailService(new Sendgrid()) : new DummyEmailService()
That pattern I recognize as a feature flag
A simple approach which at least allows feature flags to be re-configured without re-building an app or service is to specify Toggle Configuration via command-line arguments or environment ...
In his classic book Large-Scale C++ Software Design, John Lakos introduced the term "physical design" to descibe this aspect: how the source code is split up into individual source files, and what goes where. Physical design, as you rightly note, is an orthogonal issue from "logical design": how classes are related by inheritance and ...
I think the term I was looking for was decomposition.
Decomposition in computer science, also known as factoring, is breaking a complex problem or system into parts that are easier to conceive, understand, program, and maintain.
While it can, it certainly doesn't mean it should. It really depends on your use case. Generally, a cache shouldn't be a single point of failure (or any failure) for that matter, and apps that "depend" on it should be able to transparently handle if the cache is down.
Rules of Thumb👍
Each microservice should be as independent from ...
Any queueing service supporting multiple consumers will do. REDIS lists are suitable for this, as are the various message brokers such as RabbitMQ or ActiveMQ.
You need to consider how you handle crashes of consumers while they hold a resource. This may get tricky. Message brokers often have an acknowledgement mechanism so that messages are only removed when ...