Fundamentals 10 min read

Designing Good System Architecture: Isolation, Concerns, and AOP

The article explains how to design clean, decoupled system architectures by isolating concerns, using AOP, dependency injection, factory methods, and DSLs, while illustrating concepts with city‑building analogies and Java code examples.

Architecture Digest
Architecture Digest
Architecture Digest
Designing Good System Architecture: Isolation, Concerns, and AOP

This chapter discusses how to design a good system architecture, emphasizing the principle of isolation (concern separation) across all abstraction layers.

Conclusion

Overall architecture should be simple and elegant, ensuring decoupling between abstraction layers.

Each layer must have a clear purpose (single responsibility, non‑intrusive); achieve this with AOP.

Always prefer the simplest implementation when designing systems or modules.

Building a system is likened to building a city: isolation of concerns and multiple abstraction layers enable efficient management.

Distinguish between building a system and using it; the startup phase focuses on different concerns than the runtime phase.

Example of lazy‑initialization code (code 10‑1):

//代码10-1
public Service getService() {
    if (service == null)
        service = new MyServiceImpl(...); // Good enough default for most cases?
    return service;
}

This pattern introduces tight coupling and testing difficulties; extracting initialization into separate components is recommended.

Separation via main()

Placing all initialization in main() centralizes object creation, but can waste resources.

Separation via Factory Method

Using an abstract factory lets the program decide when to create objects while keeping creation details separate.

Dependency Injection

DI encapsulates object creation and assembly in dedicated containers, enforcing the single‑responsibility principle.

Scaling (Scale Up)

Systems evolve from small to large; focus on current needs and iteratively refactor and extend.

Techniques like TDD, refactoring, and clean code support progressive expansion.

EJB examples illustrate tight coupling problems that hinder testing and inheritance.

Aspect‑Oriented Programming (AOP)

Cross‑cutting concerns (e.g., persistence, security, transactions) are best handled with AOP. Three Java AOP solutions are presented:

Java Proxy (requires interfaces; otherwise use CGLIB, ASM, Javassist).

Pure Java AOP frameworks such as Spring AOP.

AspectJ, which offers richer capabilities but requires new tools and language constructs.

Using AOP enables test‑driven architecture by keeping core logic simple and decoupled.

Avoid big‑design‑up‑front (BDUF); instead, make decisions as late as possible based on the best available knowledge.

Adopt standards wisely; when better solutions exist, don’t follow standards rigidly.

Domain‑Specific Languages (DSLs) can abstract system concepts, freeing designers from implementation details.

architectureAOPsoftware designDependency Injectionmodularity
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.