Something about Layered
Architecture patterns
Overlapped vs. Concentric
(Classic) Layered Architecture
Architectural styles
Layers vs. Tiers
https://
www.baeldung.co
m/cs/layers-vs-tiers
Separation of concerns
• Each layer has a distinct responsibility, ensuring that business logic
remains decoupled from infrastructure or presentation concerns.
• This separation improves code maintainability and facilitates testing.
• It allows developers to easily change or replace any layer without
affecting the other layers.
• It also enables automated testing at each layer, which makes it easier
to ensure the correctness and quality of the application.
https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch01.html
layers of
isolation
Layers of Isolation
• The layers of isolation concept means that changes made in one layer of
the architecture generally don’t impact or affect components in other
layers: the change is isolated to the components within that layer, and
possibly another associated layer (such as a persistence layer containing
SQL).
• If you allow the presentation layer direct access to the persistence layer,
then changes made to SQL within the persistence layer would impact both
the business layer and the presentation layer, thereby producing a very
tightly coupled application with lots of interdependencies between
components.
• This type of architecture then becomes very hard and expensive to change.
in https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch01.html
Sink-hole (“cano de
esgoto”) happens when, in
a function, a layer does
very little.
How much can it happen?
Typically, up to 20%.
Open layer is a layer that
can is overpassed in
some requests: the
request is made to the
layer not immediately
bellow.
How much can it
happen?
Depends on the
architectural pattern.
SOLID (review)
• Single Responsibility Principle
• “A class should only have a single responsibility, that is, only changes to one part of the
software's specification should be able to affect the specification of the class.”
• Open/Closed Principle
• "Software entities ... should be open for extension but closed for modification."
• Liskov Substitution Principle
• "Objects in a program should be replaceable with instances of their subtypes without altering
the correctness of that program."
• Interface Segregation Principle
• "Many client-specific interfaces are better than one general-purpose interface."
• Dependency Inversion Principle
• “depend upon abstractions, [not] concretions”
In Wikipedia: Martin, Robert C. (2000). "Design Principles and Design Patterns" (PDF).
Archived from the original (PDF) on 2015-09-06.
Layered Architecture vs. SOLID
• Single Responsibility Principle
•  Adopted: each layer (e.g. controller) has a single responsibility. Other components (e.g. DTO) has a single responsibility too.
• Open/Closed Principle
•  Not explicitly adopted.
• Liskov Substitution Principle
•  Not explicitly adopted.
• Interface Segregation Principle
 Not explicitly adopted.
 Should any API be segregated? How?
• Dependency Inversion Principle
•  Not explicitly adopted.
This layered architecture
does not conform to
clean/onion
pattern/style.
From overlapped to concentric
Adopting SOLID in Layer Architecture
Architecture Patterns adopting SOLID
• Hexagonal Architecture (a.k.a. Ports and Adapters) by Alistair
Cockburn and adopted by Steve Freeman, and Nat Pryce in their
wonderful book Growing Object Oriented Software
• Onion Architecture by Jeffrey Palermo
• Screaming Architecture from a blog of mine last year
• DCI from James Coplien, and Trygve Reenskaug.
• BCE by Ivar Jacobson from his book Object Oriented Software
Engineering: A Use-Case Driven Approach
from: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
Onion architecture
Clean Architecture
https://herbertograca.com/2017/09/21/onion-architecture/
NB: The responsbilities
assigned to the layers vary
between
models/patterns/styles.
!!!!!
Cf. next slide
The adoption of DDD in
Domain, implies that
Repositories interfaces are
defined in Domain.
Cf. next slides.
Overlapped Layered Architecture
This layered architecture
does not conform to
onion pattern/style.
This is not what
Onion pattern/style
is about.
Each of these architectures produce systems
that are
1. Independent of Frameworks
The architecture does not depend on the existence of some library of feature laden software. This
allows you to use such frameworks as tools, rather than having to cram your system into their limited
constraints.
2. Testable
The business rules can be tested without the UI, Database, Web Server, or any other external element.
3. Independent of UI
The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a
console UI, for example, without changing the business rules.
4. Independent of Database
You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your
business rules are not bound to the database.
5. Independent of any external agency
In fact, your business rules simply don’t know anything at all about the outside world.
in https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
Common characteristics
• Separation of Concerns
• The business logic (domain) is isolated from technical concerns (e.g., UI,
database, external services).
• Dependency Inversion
• Higher-level modules should not depend on lower-level modules but on
abstractions, allowing the core logic to remain independent.
• Testability and Maintainability
• By isolating dependencies and creating clear boundaries between layers,
these architectures allow for easier unit testing and long-term maintenance.
Business-related
Technical-related
The Dependency Rule
• The concentric circles represent different areas of software. In general, the further in you
go, the higher level the software becomes. The outer circles are mechanisms. The inner
circles are policies.
• The overriding rule that makes this architecture work is The Dependency Rule. This rule
says that source code dependencies can only point inwards. Nothing in an inner circle can
know anything at all about something in an outer circle. In particular, the name of
something declared in an outer circle must not be mentioned by the code in the inner
circle. That includes, functions, classes. variables, or any other named software entity.
• By the same token, data formats used in an outer circle should not be used by an inner
circle, especially if those formats are generated by a framework in an outer circle. We don’t
want anything in an outer circle to impact the inner circles.
in https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
From overlapped to concentric:
metaphoric representation
The dependency rule
in simple code
public class ControllerX {
ServiceX _service;
public ControllerX(ServiceX service) {
_service = service;
}
public int method1(int value) {
X x1 = _service.method2(value);
return 1;
}
}
public class ServiceX {
IRepositoryX _repository;
public ServiceX(IRepositoryX repository) {
_repository = repository;
}
public X method2(int value) {
X x1 = new X(value);
return _repository.method3(x1);
}
}
public class X {
int _value;
X(int value) {
_value = value;
}
}
public interface IRepositoryX {
X method3(X x);
}
public class RepositoryX2 implements IRepositoryX {
public X method3(X x1) {
// specific implementation 2
return x1;
}
}
public class RepositoryX1 implements IRepositoryX {
public X method3(X x1) {
// specific implementation 1
return x1;
}
}
The dependency rule
in simple code
public class ControllerX {
ServiceX _service;
public ControllerX(ServiceX service) {
_service = service;
}
public int method1(int value) {
X x1 = _service.method2(value);
return 1;
}
}
public class ServiceX {
IRepositoryX _repository;
IMsgAdapter _msgAdapter;
public ServiceX(IRepositoryX repository,
IMsgAdapter msgAdapter) {
_repository = repository;
_msgAdapter = msgAdpater;
}
public X method2(int value) {
X x1 = new X(value);
_repository.method3(x1);
_msgAdapter.sendMsg(“Funcionou!!”);
}
}
public class X {
int _value;
X(int value) {
_value = value;
}
}
public interface IRepositoryX {
X method3(X x);
}
public class RepositoryX2 implements IRepositoryX {
public X method3(X x1) {
// specific implementation 2
return x1;
}
}
public class RepositoryX1 implements IRepositoryX {
public X method3(X x1) {
// specific implementation 1
return x1;
}
}
public interface IMsgAdapter {
void sendMsg(String s);
}
public class MsgAdapterEm
IMsgAdapter {
public void sendMsg(Str
// specific implementa
return;
}
}
public c
IMsgAd
publi
// s
ret
}
}
DIP: Dependency
Inversion Principle
The Domain Model define the contract that
the Repository classes must implement.
The Repository implements interface
(contract).
The Application Service does not need to
know in development time the Repository
class that implements the interface. Instead,
the Repository class/object can be provided
during execution (dependency injection).
Hence, the Application Service behavior (i.e.
which object is called) is controlled by the
upper layers (Inversion of
Control/Dependency Inversion Principle).
Cf. next slides
Classify and layout layers (i)
Colors are semantically
meaningless but may help
following from the onion
metaphor diagram to the
UML representation.
BTW, what
component should
be here?
Classify and layout layers (i)
(with isolation models)
Colors are semantically
meaningless but may help
following from the onion
metaphor diagram to the
UML representation.
e.g. HTTP
Server+Routing;
or Tests, or UI
Including a filesystem-based repository
Is it necessary?
If its interface is different from
that of the “Repository”, in
order to apply the ISP, yes.
Otherwise, no.
Just another layout
DIP: Dependency
Inversion Principle
The Domain Model define the contract that
the Repository classes must implement.
The Repository implements interface
(contract).
The Application Service does not need to
know in development time the Repository
class that implements the interface. Instead,
the Repository class/object can be provided
during execution (dependency injection).
Hence, the Application Service behavior (i.e.
which object is called) is controlled by the
upper layers (Inversion of
Control/Dependency Inversion Principle).
Cf. next slides
Bootstrap
Optional: the
Container may be
used to keep the
injected objects.
Dependency Injection in
constructor.
Dependency Injection.
Implementation View
(from logic to implementation)
Implementation Views (increased finer granularity)
Class diagram (i)
Class diagram (ii)
Class diagram (iii)
Class diagram (iv)
With or without inward interfaces?
NB: because the
dependency is from
exterior to interior, it is not
mandatory to adopt DIP,
Interface or Dependency
Injection.
Class diagram (i) (with inward interfaces)
Class diagram (ii) (with inward interfaces)
Class diagram (iii)
(with inward interfaces)
Class diagram (iv)
(with inward interfaces)
It would be uncommon that
the DBDriver implements an
interface defined in/by
Repositories.
It would be uncommon that
the FilesystemDriver
implements an interface
defined in/by Repositories.
Class diagram (v)
Sequence diagram (with DTO and DataModel)
References and Bibliography
• https://blog.ploeh.dk/2013/12/03/layers-onions-ports-adapters-its-all
-the-same/
• https://jeffreypalermo.com/tag/onion-architecture/
• https://stackoverflow.com/questions/23479879/clean-architecture-vs
-onion-architecture
• https://herbertograca.com/2017/09/21/onion-architecture/

Something About Layered Architecture Patterns: overlapped vs. concentric layers vs. SOLID

  • 1.
    Something about Layered Architecturepatterns Overlapped vs. Concentric
  • 2.
  • 3.
    Architectural styles Layers vs.Tiers https:// www.baeldung.co m/cs/layers-vs-tiers
  • 4.
    Separation of concerns •Each layer has a distinct responsibility, ensuring that business logic remains decoupled from infrastructure or presentation concerns. • This separation improves code maintainability and facilitates testing. • It allows developers to easily change or replace any layer without affecting the other layers. • It also enables automated testing at each layer, which makes it easier to ensure the correctness and quality of the application.
  • 5.
  • 6.
  • 7.
    Layers of Isolation •The layers of isolation concept means that changes made in one layer of the architecture generally don’t impact or affect components in other layers: the change is isolated to the components within that layer, and possibly another associated layer (such as a persistence layer containing SQL). • If you allow the presentation layer direct access to the persistence layer, then changes made to SQL within the persistence layer would impact both the business layer and the presentation layer, thereby producing a very tightly coupled application with lots of interdependencies between components. • This type of architecture then becomes very hard and expensive to change. in https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch01.html
  • 8.
    Sink-hole (“cano de esgoto”)happens when, in a function, a layer does very little. How much can it happen? Typically, up to 20%.
  • 9.
    Open layer isa layer that can is overpassed in some requests: the request is made to the layer not immediately bellow. How much can it happen? Depends on the architectural pattern.
  • 10.
    SOLID (review) • SingleResponsibility Principle • “A class should only have a single responsibility, that is, only changes to one part of the software's specification should be able to affect the specification of the class.” • Open/Closed Principle • "Software entities ... should be open for extension but closed for modification." • Liskov Substitution Principle • "Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program." • Interface Segregation Principle • "Many client-specific interfaces are better than one general-purpose interface." • Dependency Inversion Principle • “depend upon abstractions, [not] concretions” In Wikipedia: Martin, Robert C. (2000). "Design Principles and Design Patterns" (PDF). Archived from the original (PDF) on 2015-09-06.
  • 11.
    Layered Architecture vs.SOLID • Single Responsibility Principle •  Adopted: each layer (e.g. controller) has a single responsibility. Other components (e.g. DTO) has a single responsibility too. • Open/Closed Principle •  Not explicitly adopted. • Liskov Substitution Principle •  Not explicitly adopted. • Interface Segregation Principle  Not explicitly adopted.  Should any API be segregated? How? • Dependency Inversion Principle •  Not explicitly adopted. This layered architecture does not conform to clean/onion pattern/style.
  • 12.
    From overlapped toconcentric Adopting SOLID in Layer Architecture
  • 13.
    Architecture Patterns adoptingSOLID • Hexagonal Architecture (a.k.a. Ports and Adapters) by Alistair Cockburn and adopted by Steve Freeman, and Nat Pryce in their wonderful book Growing Object Oriented Software • Onion Architecture by Jeffrey Palermo • Screaming Architecture from a blog of mine last year • DCI from James Coplien, and Trygve Reenskaug. • BCE by Ivar Jacobson from his book Object Oriented Software Engineering: A Use-Case Driven Approach from: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
  • 14.
  • 15.
  • 16.
    https://herbertograca.com/2017/09/21/onion-architecture/ NB: The responsbilities assignedto the layers vary between models/patterns/styles. !!!!! Cf. next slide The adoption of DDD in Domain, implies that Repositories interfaces are defined in Domain. Cf. next slides.
  • 17.
    Overlapped Layered Architecture Thislayered architecture does not conform to onion pattern/style. This is not what Onion pattern/style is about.
  • 18.
    Each of thesearchitectures produce systems that are 1. Independent of Frameworks The architecture does not depend on the existence of some library of feature laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints. 2. Testable The business rules can be tested without the UI, Database, Web Server, or any other external element. 3. Independent of UI The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules. 4. Independent of Database You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database. 5. Independent of any external agency In fact, your business rules simply don’t know anything at all about the outside world. in https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
  • 19.
    Common characteristics • Separationof Concerns • The business logic (domain) is isolated from technical concerns (e.g., UI, database, external services). • Dependency Inversion • Higher-level modules should not depend on lower-level modules but on abstractions, allowing the core logic to remain independent. • Testability and Maintainability • By isolating dependencies and creating clear boundaries between layers, these architectures allow for easier unit testing and long-term maintenance. Business-related Technical-related
  • 20.
    The Dependency Rule •The concentric circles represent different areas of software. In general, the further in you go, the higher level the software becomes. The outer circles are mechanisms. The inner circles are policies. • The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in the inner circle. That includes, functions, classes. variables, or any other named software entity. • By the same token, data formats used in an outer circle should not be used by an inner circle, especially if those formats are generated by a framework in an outer circle. We don’t want anything in an outer circle to impact the inner circles. in https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
  • 21.
    From overlapped toconcentric: metaphoric representation
  • 22.
    The dependency rule insimple code public class ControllerX { ServiceX _service; public ControllerX(ServiceX service) { _service = service; } public int method1(int value) { X x1 = _service.method2(value); return 1; } } public class ServiceX { IRepositoryX _repository; public ServiceX(IRepositoryX repository) { _repository = repository; } public X method2(int value) { X x1 = new X(value); return _repository.method3(x1); } } public class X { int _value; X(int value) { _value = value; } } public interface IRepositoryX { X method3(X x); } public class RepositoryX2 implements IRepositoryX { public X method3(X x1) { // specific implementation 2 return x1; } } public class RepositoryX1 implements IRepositoryX { public X method3(X x1) { // specific implementation 1 return x1; } }
  • 23.
    The dependency rule insimple code public class ControllerX { ServiceX _service; public ControllerX(ServiceX service) { _service = service; } public int method1(int value) { X x1 = _service.method2(value); return 1; } } public class ServiceX { IRepositoryX _repository; IMsgAdapter _msgAdapter; public ServiceX(IRepositoryX repository, IMsgAdapter msgAdapter) { _repository = repository; _msgAdapter = msgAdpater; } public X method2(int value) { X x1 = new X(value); _repository.method3(x1); _msgAdapter.sendMsg(“Funcionou!!”); } } public class X { int _value; X(int value) { _value = value; } } public interface IRepositoryX { X method3(X x); } public class RepositoryX2 implements IRepositoryX { public X method3(X x1) { // specific implementation 2 return x1; } } public class RepositoryX1 implements IRepositoryX { public X method3(X x1) { // specific implementation 1 return x1; } } public interface IMsgAdapter { void sendMsg(String s); } public class MsgAdapterEm IMsgAdapter { public void sendMsg(Str // specific implementa return; } } public c IMsgAd publi // s ret } }
  • 24.
    DIP: Dependency Inversion Principle TheDomain Model define the contract that the Repository classes must implement. The Repository implements interface (contract). The Application Service does not need to know in development time the Repository class that implements the interface. Instead, the Repository class/object can be provided during execution (dependency injection). Hence, the Application Service behavior (i.e. which object is called) is controlled by the upper layers (Inversion of Control/Dependency Inversion Principle). Cf. next slides
  • 25.
    Classify and layoutlayers (i) Colors are semantically meaningless but may help following from the onion metaphor diagram to the UML representation. BTW, what component should be here?
  • 26.
    Classify and layoutlayers (i) (with isolation models) Colors are semantically meaningless but may help following from the onion metaphor diagram to the UML representation. e.g. HTTP Server+Routing; or Tests, or UI
  • 27.
    Including a filesystem-basedrepository Is it necessary? If its interface is different from that of the “Repository”, in order to apply the ISP, yes. Otherwise, no.
  • 28.
  • 29.
    DIP: Dependency Inversion Principle TheDomain Model define the contract that the Repository classes must implement. The Repository implements interface (contract). The Application Service does not need to know in development time the Repository class that implements the interface. Instead, the Repository class/object can be provided during execution (dependency injection). Hence, the Application Service behavior (i.e. which object is called) is controlled by the upper layers (Inversion of Control/Dependency Inversion Principle). Cf. next slides
  • 30.
    Bootstrap Optional: the Container maybe used to keep the injected objects. Dependency Injection in constructor. Dependency Injection.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
    With or withoutinward interfaces? NB: because the dependency is from exterior to interior, it is not mandatory to adopt DIP, Interface or Dependency Injection.
  • 38.
    Class diagram (i)(with inward interfaces)
  • 39.
    Class diagram (ii)(with inward interfaces)
  • 40.
    Class diagram (iii) (withinward interfaces)
  • 41.
    Class diagram (iv) (withinward interfaces)
  • 42.
    It would beuncommon that the DBDriver implements an interface defined in/by Repositories. It would be uncommon that the FilesystemDriver implements an interface defined in/by Repositories. Class diagram (v)
  • 43.
    Sequence diagram (withDTO and DataModel)
  • 44.
    References and Bibliography •https://blog.ploeh.dk/2013/12/03/layers-onions-ports-adapters-its-all -the-same/ • https://jeffreypalermo.com/tag/onion-architecture/ • https://stackoverflow.com/questions/23479879/clean-architecture-vs -onion-architecture • https://herbertograca.com/2017/09/21/onion-architecture/

Editor's Notes

  • #8 Sink-hole: quando os pedidos não são tratados ou são pouco tratados por determinado closed layer. Regra: ainda será em camadas se estes sink-holes (pouco ou nenhum tratamento numa camada) não ultrapassarem os 20%
  • #9 Open layer: determina que os pedido não têm que passar por essa camada.