{"id":677,"date":"2010-04-11T14:07:00","date_gmt":"2010-04-11T13:07:00","guid":{"rendered":"http:\/\/blog.eweibel.net\/?p=677"},"modified":"2010-08-19T09:46:06","modified_gmt":"2010-08-19T08:46:06","slug":"round-up-of-a-data-centric-architecture","status":"publish","type":"post","link":"https:\/\/blog.eweibel.net\/?p=677","title":{"rendered":"Round-up of a data centric architecture"},"content":{"rendered":"<p>In my last big project we had to use a data centric architecture. There was a learning curve which architecture was the most appropriate one. The result is visible in the picture bellow:<\/p>\n<p><a href=\"http:\/\/blog.eweibel.net\/wp-content\/uploads\/Architektur.jpg\" class=\"lightbox\"><img loading=\"lazy\" decoding=\"async\" style=\"border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto\" title=\"Architektur\" border=\"0\" alt=\"Architektur\" src=\"http:\/\/blog.eweibel.net\/wp-content\/uploads\/Architektur_thumb.jpg\" width=\"600\" height=\"640\" \/><\/a><\/p>\n<p>Lets explaining the diagram. The data (or state) is managed by the database layer and the common layer which contains the .Net class <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.data.dataset.aspx\" target=\"_blank\">DataSet<\/a> and the DataTables (logic representation of the physical table in the database). This architecture makes use of the patterns <a href=\"http:\/\/martinfowler.com\/eaaCatalog\/tableModule.html\" target=\"_blank\">Table Module<\/a> for domain logic and <a href=\"http:\/\/martinfowler.com\/eaaCatalog\/tableDataGateway.html\" target=\"_blank\">Table Data Gateway<\/a> for data access logic.<\/p>\n<p>There is no need for <a href=\"http:\/\/en.wikipedia.org\/wiki\/Data_transfer_object\" target=\"_blank\">DTOs<\/a>, the state is loaded by the data access layer into the DataSet which is transported through the upper layers. That means, that all layers (except the database layer) know the common layer. Instead of using the DataSet, you could realize that also with <a href=\"http:\/\/en.wikipedia.org\/wiki\/POJO\" target=\"_blank\">POJOs<\/a>. But that leads in a data centric approach to an <a href=\"http:\/\/martinfowler.com\/bliki\/AnemicDomainModel.html\" target=\"_blank\">anemic domain model<\/a>.<\/p>\n<p>The domain layer contains the core business logic (domain logic). When you use a data centric architecture, then you couldn\u2019t program in a pure OO-way. All methods have to have a pointer to the data. In this architecture you have possibility to solve that problem: One pointer to the data-structure (here DataSet) and another to the DataRow by a key (for example the primary key). The other possibility is, that you get a DataRow once and pass it around. The problem with this solution is, that you could get a mess with several DataSets.<\/p>\n<p>One important lesson that was learned, was the need of a service layer (<a href=\"http:\/\/martinfowler.com\/eaaCatalog\/serviceLayer.html\" target=\"_blank\">Service Layer pattern<\/a>) which we called use case layer. This layer contains the services, here Controller called. A Controller represents a use case, for example an activity in a workflow process or a simple <a href=\"http:\/\/en.wikipedia.org\/wiki\/Create,_read,_update_and_delete\" target=\"_blank\">CRUD<\/a> window. The responsibility of a Controller is to control and to coordinate what happen in a use case:<\/p>\n<ul>\n<li>Prepare initial data structure, load data for combo boxes <\/li>\n<li>Coordinates load or validation of data for additional AJAX calls <\/li>\n<li>Coordinates the validation of the data structure <\/li>\n<li>Delegate the persistence of the data structure <\/li>\n<\/ul>\n<p>The layers report data source, workflow and remoting (contains facades which realize the <a href=\"http:\/\/martinfowler.com\/eaaCatalog\/remoteFacade.html\" target=\"_blank\">Remote Facade<\/a> pattern) are just technical layers. They don\u2019t contain any relevant logic. They just delegate to the use case layer.<\/p>\n<p>Finally, the two layers report and web represent the user interface. The report layer talks only with the report data source layer and the common layer. The web layer talks only with the remoting and common layer and asynchronous with the workflow layer. As web layer technology we used <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms973868.aspx\" target=\"_blank\">ASP.Net Web Forms<\/a>.<\/p>\n<p><strong>Using silos<\/strong><\/p>\n<p>We used the term silo to define what you have to do to realize a use case. There were two major use cases: Simple CRUD dialog or a workflow activity (which have also a dialog).<\/p>\n<p>The silo for a simple CRUD dialog contains: Code behind, View, Document, Facade Interface, Facade, Use Case Interface and a Controller.<\/p>\n<p>The silo for a workflow activity contains: Code behind, View, Document Facade Interface, Facade, WFModule, Use Case Interface and a Controller.<\/p>\n<p>The big advantage of a silo is, that it is clear what you have to do and where what kind of logic has to be. It is also clear that you shouldn\u2019t reference classes of an other silo. This rule helps to minimize the side effects.<\/p>\n<p>But there is also a disadvantage: A silo generate boilerplate code (Interfaces, WFModule, Facade). This leads to the anti pattern <a href=\"http:\/\/en.wikipedia.org\/wiki\/Accidental_complexity\" target=\"_blank\">accidental complexity<\/a>. To reduce this problem, you could use wizards in your IDE or some code generation tools.<\/p>\n<p><strong>Make clear decisions where reuse should happen<\/strong><\/p>\n<p>The use of silo arise the question where the reuse of logic happens. This was an other important lesson learned. It is important that it is clear where the reuse has to happen. In this architecture it happens in the domain layer with the methods of the BusinessObject and TableModule. Those methods are driven by the domain and have specific names, what simplifies the reuse.<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>After understanding the architecture, we were quite productive. But I\u2019m still a fan of simple and clean OO architectures, for several reasons: avoid accidental complexity, encapsulation, information hiding or inheritance. Most of those reasons are a problem with this architecture.<\/p>\n<p>A nice side effect of this architecture is a good support for testability. You could set up every state what you want because there is no encapsulation. The problem of dependencies between classes still has to be solve with dependency injection and a <a href=\"http:\/\/blog.eweibel.net\/?p=376\">mocking framework<\/a>.<\/p>\n<p>If you use a technical environment which gives you strong instrument for a data centric architecture you should consider to use them. Important for a data centric architecture is that you define rules where you place your logic and where the reuse happens.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my last big project we had to use a data centric architecture. There was a learning curve which architecture was the most appropriate one. The result is visible in the picture bellow: Lets explaining the diagram. The data (or state) is managed by the database layer and the common layer which contains the .Net class DataSet and the DataTables (logic representation of the physical table in the database). This architecture makes use of the patterns Table Module for domain&#8230;<\/p>\n<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/blog.eweibel.net\/?p=677\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4],"tags":[],"class_list":["post-677","post","type-post","status-publish","format-standard","hentry","category-software-architecture"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/plOV9-aV","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":797,"url":"https:\/\/blog.eweibel.net\/?p=797","url_meta":{"origin":677,"position":0},"title":"NHibernate day in Bologna","author":"Patrick","date":"25. Oct 2010","format":false,"excerpt":"During a whole day several speakers spoke about NHibernate and related topics. This conference was in Bologna and was very well prepared and organized. You could watch the slides and the videos of the sessions here. I joined the following sessions: Keynote Simone Chiaretta opened the conference and showed during\u2026","rel":"","context":"In &quot;.NET&quot;","block_context":{"text":".NET","link":"https:\/\/blog.eweibel.net\/?cat=13"},"img":{"alt_text":"NHDay_3","src":"https:\/\/i0.wp.com\/blog.eweibel.net\/wp-content\/uploads\/NHDay_3_thumb.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":160,"url":"https:\/\/blog.eweibel.net\/?p=160","url_meta":{"origin":677,"position":1},"title":"When to use stored procedures","author":"Patrick","date":"13. May 2009","format":false,"excerpt":"Recently I discussed with a colleague when to use stored procedures. As exptected it was quite a religious conversation. A few days later I found the following screencast: The Pros and Cons of Stored Procedures Based on the discussion and the screencast I tried to summarize my Pros and Cons:\u2026","rel":"","context":"In &quot;Good practices&quot;","block_context":{"text":"Good practices","link":"https:\/\/blog.eweibel.net\/?cat=5"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1198,"url":"https:\/\/blog.eweibel.net\/?p=1198","url_meta":{"origin":677,"position":2},"title":"Are stale data evil?","author":"Patrick","date":"27. Feb 2012","format":false,"excerpt":"When you're a software engineer who produces software for enterprises like banks or assurances, then it is normal you have huge databases (several gigabytes). Such systems have an operative application where users do the daily business of the company and there are more informative parts (or strategic parts) of the\u2026","rel":"","context":"In &quot;Software architecture&quot;","block_context":{"text":"Software architecture","link":"https:\/\/blog.eweibel.net\/?cat=4"},"img":{"alt_text":"Sexy young woman as devil in fire","src":"https:\/\/i0.wp.com\/blog.eweibel.net\/wp-content\/uploads\/Fotolia_37310173_S_thumb.jpg?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":34,"url":"https:\/\/blog.eweibel.net\/?p=34","url_meta":{"origin":677,"position":3},"title":"Are 100% code coverage reasonable?","author":"Patrick","date":"2. Mar 2009","format":false,"excerpt":"When you use a code coverage tool one of the first question is what is a good code coverage. Recently I listened to different podcasts (stackoverflow, scott hanselman) where they discuss this topic. I wasn't really surprised that there wasn't one unique opinion.One opinion was that 100% is a good\u2026","rel":"","context":"In &quot;Software architecture&quot;","block_context":{"text":"Software architecture","link":"https:\/\/blog.eweibel.net\/?cat=4"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1182,"url":"https:\/\/blog.eweibel.net\/?p=1182","url_meta":{"origin":677,"position":4},"title":"Anti-Pattern &#8216;Validation by Execute &#8216;n&#8217; Rollback&#8217;","author":"Patrick","date":"21. Feb 2012","format":false,"excerpt":"Recently in some reviews I saw an anti-pattern. First you have to know, in the code, there was a validation of the data before it was stored in the database. So far so good. But when I looked at the validation code, I saw the following: public void Validate() {\u2026","rel":"","context":"In &quot;Anti patterns&quot;","block_context":{"text":"Anti patterns","link":"https:\/\/blog.eweibel.net\/?cat=8"},"img":{"alt_text":"Fotolia_20233238_S","src":"https:\/\/i0.wp.com\/blog.eweibel.net\/wp-content\/uploads\/Fotolia_20233238_S_thumb1.jpg?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1014,"url":"https:\/\/blog.eweibel.net\/?p=1014","url_meta":{"origin":677,"position":5},"title":"Master of Advanced Studies in Information Technology","author":"Patrick","date":"9. May 2011","format":false,"excerpt":"During the last three years I was a part-time student again because I did at the university of applied science in Berne a post-grade study. Last week I received my certificate and the new title on the CV is now \u201cMaster of Advanced Studies in Information Technology\u201d. I chose the\u2026","rel":"","context":"In &quot;Private&quot;","block_context":{"text":"Private","link":"https:\/\/blog.eweibel.net\/?cat=9"},"img":{"alt_text":"image","src":"https:\/\/i0.wp.com\/blog.eweibel.net\/wp-content\/uploads\/image_thumb16.png?resize=350%2C200","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=\/wp\/v2\/posts\/677","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=677"}],"version-history":[{"count":19,"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=\/wp\/v2\/posts\/677\/revisions"}],"predecessor-version":[{"id":728,"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=\/wp\/v2\/posts\/677\/revisions\/728"}],"wp:attachment":[{"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=677"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=677"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.eweibel.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=677"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}