{"id":47,"date":"2023-09-01T21:01:26","date_gmt":"2023-09-01T20:01:26","guid":{"rendered":"https:\/\/codeblog.xyz\/?p=47"},"modified":"2023-10-23T21:07:39","modified_gmt":"2023-10-23T18:07:39","slug":"onion-architecture-concepts","status":"publish","type":"post","link":"https:\/\/codeblog.xyz\/?p=47","title":{"rendered":"Onion Architecture &#8211; concepts"},"content":{"rendered":"\n<p><strong>Conceptual Understanding<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Onion Architecture is about the positioning of concerns and flow of dependencies, primarily toward the center. Dependencies flow inward, not outward.<\/li>\n\n\n\n<li>The center of the onion, the Domain layer, should have no dependencies on any outer layers. It defines the business rules and data.<\/li>\n\n\n\n<li>The layers include: Domain Model (center), Application Layer, Infrastructure (outermost).<\/li>\n\n\n\n<li>The inner layers define interfaces that outer layers implement, leading to an architecture that is easy to maintain, easy to test, and less coupled.<\/li>\n\n\n\n<li>The infrastructure is just a detail and the application should not be dependent on it.<\/li>\n<\/ol>\n\n\n\n<p><strong>Domain Layer<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"6\">\n<li>This is the innermost layer representing enterprise-wide business concepts.<\/li>\n\n\n\n<li>It includes Entities, Value Objects, and Domain Events.<\/li>\n<\/ol>\n\n\n\n<p><strong>Example 1:<\/strong><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">\/\/Entity\npublic class User\n{\n    public Guid Id { get; private set; }\n    public string Email { get; private set; }\n    public string Name { get; private set; }\n\n    private User() { }\n\n    public User(string email, string name)\n    {\n        \/\/business rules go here\n        if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(name))\n            throw new ArgumentException(&quot;Email and Name cannot be null or empty.&quot;);\n\n        Id = Guid.NewGuid();\n        Email = email;\n        Name = name;\n    }\n}\n<\/pre><\/div>\n\n\n\n<ol class=\"wp-block-list\" start=\"8\">\n<li>It is technology-agnostic and has no dependencies on outer layers.<\/li>\n\n\n\n<li>Contains business rules that should be common to multiple applications in the same domain.<\/li>\n\n\n\n<li>Defines interfaces for repositories that outer layers will implement.<\/li>\n<\/ol>\n\n\n\n<p><strong>Example 2:<\/strong><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">\/\/Interface for repository\npublic interface IUserRepository\n{\n    Task AddAsync(User user);\n    Task&lt;User&gt; GetByEmailAsync(string email);\n}\n<\/pre><\/div>\n\n\n\n<p><strong>Application Layer<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"11\">\n<li>Contains use case specific business rules.<\/li>\n\n\n\n<li>This layer orchestrates the domain layer and the infrastructure layer.<\/li>\n\n\n\n<li>It&#8217;s responsible for calling infrastructure layer interfaces like repository interfaces or infrastructure services.<\/li>\n\n\n\n<li>It communicates with the domain layer using interfaces.<\/li>\n\n\n\n<li>Services in this layer serve as the entry point to the application.<\/li>\n<\/ol>\n\n\n\n<p><strong>Example 3:<\/strong><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">public class UserService\n{\n    private readonly IUserRepository _userRepository;\n\n    public UserService(IUserRepository userRepository)\n    {\n        _userRepository = userRepository;\n    }\n\n    public async Task CreateUserAsync(string email, string name)\n    {\n        var existingUser = await _userRepository.GetByEmailAsync(email);\n\n        if (existingUser != null)\n            throw new ArgumentException(&quot;User with the same email already exists.&quot;);\n\n        var user = new User(email, name);\n\n        await _userRepository.AddAsync(user);\n    }\n}\n<\/pre><\/div>\n\n\n\n<p><strong>Infrastructure Layer<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"16\">\n<li>This is the outermost layer.<\/li>\n\n\n\n<li>It provides concrete implementations for interfaces defined in the inner layers, like database repositories, file system interactions, network communication, etc.<\/li>\n\n\n\n<li>It communicates with the inner layers through interfaces.<\/li>\n\n\n\n<li>This layer should be easily replaceable.<\/li>\n\n\n\n<li>It may contain implementations of domain services if they involve infrastructure concerns.<\/li>\n<\/ol>\n\n\n\n<p><strong>Example 4:<\/strong><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">public class UserRepository : IUserRepository\n{\n    private readonly MyDbContext _context;\n\n    public UserRepository(MyDbContext context)\n    {\n        _context = context;\n    }\n\n    public async Task AddAsync(User user)\n    {\n        await _context.Users.AddAsync(user);\n        await _context.SaveChangesAsync();\n    }\n\n    public async Task&lt;User&gt; GetByEmailAsync(string email)\n    {\n        return await _context.Users.FirstOrDefaultAsync(u =&gt; u.Email == email);\n    }\n}\n<\/pre><\/div>\n\n\n\n<p>In this example, <code>MyDbContext<\/code> would be your Entity Framework Core DbContext, which is a part of the Infrastructure layer and provides a gateway to your database.<\/p>\n\n\n\n<p><strong>Architectural Advantages<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"21\">\n<li>High level of maintainability due to the decoupled nature of the architecture.<\/li>\n\n\n\n<li>Highly testable as dependencies can be easily mocked.<\/li>\n\n\n\n<li>Independent of technology, making it flexible and adaptable to changes.<\/li>\n\n\n\n<li>Changes in the database or UI do not affect the core logic of the application.<\/li>\n<\/ol>\n\n\n\n<p><strong>Architectural Disadvantages<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"25\">\n<li>It can be an overkill for small applications, adding unnecessary complexity.<\/li>\n\n\n\n<li>Can be time-consuming to set up due to the strict separation of concerns.<\/li>\n<\/ol>\n\n\n\n<p>The Onion Architecture promotes separation of concerns, maintainability, and testability, making it a great choice for large and complex applications. However, always analyze your project&#8217;s requirements to ensure that this architectural style is a suitable choice.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Conceptual Understanding Domain Layer Example 1: Example 2: Application Layer Example 3: Infrastructure Layer Example 4: In this example, MyDbContext would be your Entity Framework Core DbContext, which is a part of the Infrastructure layer and provides a gateway to your database. Architectural Advantages Architectural Disadvantages The Onion Architecture promotes separation of concerns, maintainability, and [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":225,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[1],"tags":[33,35,31],"class_list":["post-47","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-architecture","tag-concepts","tag-onion-architecture"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/codeblog.xyz\/index.php?rest_route=\/wp\/v2\/posts\/47","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codeblog.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codeblog.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codeblog.xyz\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/codeblog.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=47"}],"version-history":[{"count":1,"href":"https:\/\/codeblog.xyz\/index.php?rest_route=\/wp\/v2\/posts\/47\/revisions"}],"predecessor-version":[{"id":48,"href":"https:\/\/codeblog.xyz\/index.php?rest_route=\/wp\/v2\/posts\/47\/revisions\/48"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codeblog.xyz\/index.php?rest_route=\/wp\/v2\/media\/225"}],"wp:attachment":[{"href":"https:\/\/codeblog.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=47"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codeblog.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=47"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codeblog.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=47"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}