I've been working on a project for the former Polish state telco and the codebase was mostly Java EE as written in the mid-00's. Since you cannot really be productive in Java without an IDE, standard English conventions for naming have been pushed onto the devs from early on - a getter must start with `get` or `is` if the return type is boolean, class names have to contain standardized postfixes corresponding to the design pattern used, such as `AbstractFactoryBean` etc. But since few people spoke English back then, they ended up with awful hybrid names such as `getCennikSluchawkiKeySet` or `OfertaManagerPrzylaczeProxy`.
A lot of software design from the English world centers around "design patterns." And these "design patterns" have advanced nomenclature and often make things more convoluted then necessary. The whole concept of these "patterns" are actually an arbitrary style that got invented in the English speaking world. In non-english countries people program in ways that are more straightforward.
First, we create an AbstractFactory to generate objects that conform to our standardized output structure, ensuring extensibility in case "Hello, World!" ever needs additional variants. The Singleton manages our PrintManager, enforcing a single, controlled point of access to the output stream while Double-Checked Locking ensures thread-safe initialization. Dependency Injection provides our PrintHandler with a flexible logging system, allowing it to notify an Observer whenever "Hello, World!" is printed. The Mediator coordinates between components to ensure the PrintHandler doesn’t have direct dependencies on the OutputStrategy.
To maintain optimal efficiency, a Flyweight is used for the "Hello, World!" string, preventing redundant memory allocation. The Proxy regulates access to the print function, ensuring only authorized modules can invoke it. The Composite structure organizes potential multiple output streams, making it easy to expand the system beyond just console printing. A Factory of Factories, or MetaFactory, oversees creation of our AbstractFactories to maintain consistency and scalability.
Before execution, Encapsulation hides implementation details while Cohesion ensures the PrintHandler remains single-responsibility. Loose Coupling ensures that changing one component won’t break the system. Interfaces dictate behavior, and Abstract Classes provide reusable codebases. Dynamic Dispatch selects the appropriate OutputStrategy at runtime.
To enhance modularity, a Decorator wraps the PrintHandler for additional formatting options, an Adapter ensures compatibility with different logging frameworks, a Memento preserves state in case a rollback is needed, and a Facade simplifies access for higher-level modules. The Chain of Responsibility delegates different logging levels, while the Command Pattern encapsulates the printing request for possible queuing or delayed execution.
By adhering to Open-Closed, we can extend our print functionality without modifying core logic. Liskov Substitution ensures all output strategies remain interchangeable. Interface Segregation ensures smaller, focused contracts. Dependency Inversion prioritizes abstractions over concrete implementations.
Finally, SOLID principles uphold scalability, reusability, and maintainability. UML diagrams map out relationships, Sequence flows depict interactions, and Design Contracts enforce constraints, ensuring the system remains adaptable.
After all this, we simply call PrintManager.getInstance().print("Hello, World!"); and marvel at our masterpiece.
This is very much a Java phenomenon. These things do have value .. when correctly applied. But sometimes it's like seeing someone make a gadget with fifty different types of bolts rather than one or two simply because they want to use all the bits of their socket set.
No it’s from a book called design patterns. It forever influenced a huge number of American programmers to think about programming in a very specific way following very specific patterns.
I’m working for a company that’s doing things in typescript using IOC and dependency injection everywhere. It pervades the minds of Americans such that they walk and talk like a parrot parroting that book.
What Americans don’t realize is that those patterns are arbitrarily made up. It’s as arbitrary and localized as the Japanese having to bow for politeness. There’s nothing intrinsically hugely beneficial for following this style. In fact, modern languages push against it. Languages like golang and rust are examples. Even JavaScript was an example although recent es6 syntax makes patterns more easier now
I think you will find most Java programmers were using these patterns before they came across the book. The language naturally leads you in that direction. The book just put a name on them.