{"id":915,"date":"2010-06-18T00:00:00","date_gmt":"2010-06-18T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/back-to-basics-wiring-up-a-web-application\/"},"modified":"2021-05-17T18:36:33","modified_gmt":"2021-05-17T18:36:33","slug":"back-to-basics-wiring-up-a-web-application","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/back-to-basics-wiring-up-a-web-application\/","title":{"rendered":"Back to Basics: Wiring up a Web Application"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"start\">As we have pieced together the  components of a web application we have explored how best to structure the  markup, and how to pull business logic out of the UI by following the Model View  Presenter Pattern. Now let&#8217;s turn our attention to the Model as we pull all  the pieces together and explore what a well behaved model might look like.&#160; <\/p>\n<p>The Model will be the piece that handles  storing and retrieving our data. Just as we did with the markup and view, we  want to provide a separation of concerns and try to shield ourselves from the more  volatile aspects of our design.<\/p>\n<h1>Model, Model, Everywhere<\/h1>\n<p>Software development is full of  models. We have domain models, physical data models, logical models, process  models, etc. Sometimes the terminology can be confusing and the differences  subtle and often abused. Let&#8217;s try to clear some up some of the confusion.<\/p>\n<p>A domain model is an informal way of  thinking about data and how the data components relate to each other independent  of any technology or formal structure. We think about relations but not  constraints. We think about associations but not inheritance, and we think  very loosely about data types, if at all. The domain model is the ultimate in  fluid informal discussion.<\/p>\n<p>A physical data model is the  implementation of a domain model in a specific database. While the domain  model is independent of any technology, the physical data model is very  dependent on a particular database platform. It may even be dependent on a  particular version of the selected database. In some cases, it may even be  dependent on a particular disk configuration with a specific operating system.<\/p>\n<p>The domain model is free from any  technical constraints leaving many implementation details to be resolved in the  physical data model. For example, entity names in the domain model can be  anything, while entity names in the physical data model are limited to what the  RDMS can handle. The domain does not have to worry about performance or  maintenance. Most of the details in the physical model are consumed by these  concerns.<\/p>\n<p>Here we will focus most of our  discussion on the development model. The relationship between the domain  model and the development model is similar to the relationship between the  domain and physical data models &#8211; similar but not exact.<\/p>\n<p>The development model is the  implementation of a domain model in code.<\/p>\n<p>Ultimately, the development model will  be expected to store and retrieve data from the physical data model. The  development model also has restrictions and extensions that the physical data  model never has to deal with. The development model can benefit from  inheritance and polymorphism, and encapsulation, but also has to deal with the  often self-contradictory business logic.<\/p>\n<p>The development model is also the last  line of defense protecting the data in the database. Validations in your code  protect the data better than any constraint, firewall, or the best security  measures that a security administrator can put in place.<\/p>\n<h1>Relationships of Models<\/h1>\n<p>There is a strong temptation to over- simplify modeling. I have often been tempted to start with the domain model  and simply have a table for every entity and have a class for every table.  This is simple, neat, and very easy to follow, but leads to a less than optimal  solution.<\/p>\n<p>The domain model may have the concept of  Broker, Closing Agent, and Appraiser. These make nice domain entities. If  the domain model even thinks about it, we may note that each of these entities  have some common features like an address. In most cases, this will simply be  defined very vaguely with no thought to implementation, and this is appropriate  for the domain model. There will most likely not be an Address entity. <\/p>\n<p>The physical data model may refine this  further and have a separate table set up for the address, noting that each of  these entities will have the same details for the address, and centralize these  details to a common table and have a relationship to the tables for the Broker,  Closing Agent, and Appraiser.<\/p>\n<p>The development  model may extend this further realizing that there are different types of  addresses and specific types of validations and processing logic associated with  each. While the domain model referred to a vague notion of an Address without  flushing out a full entity, and the physical domain model was content with a  single table housing the various details for all possible address, the  development model may build an inheritance structure to accommodate business  logic and simplify the implementation. We may define an object hierarchy  similar to this:<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1062-NH1.JPG\" alt=\"1062-NH1.JPG\" \/><\/p>\n<p>Such an inheritance hierarchy simplifies  processing business logic without having to resort to a switch, or if statements,  to use the proper implementation based on the type of address being used. We  can simply instantiate the appropriate type based on the AddressType and call  the method from the corresponding object.<\/p>\n<p>So the domain model may only have a  vague concept of an address with no additional details. The physical data  model may have a centralized table with strongly typed columns, appropriate  indexes, and foreign key constraints, and the development model may have a full  inheritance hierarchy tracking the subtle nuances of the business logic. Each  of these models is accurate and appropriate for their purposes. The domain  model provided all the detail that it needed to, and the physical data model met  the requirements and conformed to the limitations of a relational data model and  leveraged the advantages of the relational data model. Each model has specific  strengths and weaknesses. Each has specific goals and requirements. Each  model will be unique.<\/p>\n<p>The  data model may look at the domain entities and see the common fields shared  between the Broker, Closing Agent, and Appraiser and decide that there should  really be a common table to host the common fields, with separate tables for each  entity to house the fields that are unique to each entity. The physical data  model may also see the common fields and believe that all of the information can  be stored in a single table, with a column for every attribute that any of these  entities can have. It is also quite common for the data model to ignore these  commonalities and provide a single table for each. For purposes of this  article, let&#8217;s ignore the relative merits and weaknesses of these approaches and  simply accept that each can happen.<\/p>\n<p>The development model will most likely  not ignore the commonalities, and has a single simple solution. We will  define an inheritance hierarchy similar to the one shown. While the physical  data model may not have a clear cut solution for how to represent this, we do  have clear cut directions in our code. The common properties are easily at  home in VendorBase. Common functionality can also easily find a home in  VendorBase and not have to be duplicated in each derived class. If there are  methods that we know each vendor will need but we have a different  implementation for each type of vendor, we can still define the method in  VendorBase but mark it as abstract (or mustoverride in VB). This will  guarantee that each type of vendor provides an implementation for the method.<\/p>\n<h2>What Makes a Good Development Model<\/h2>\n<p>It is probably reasonable to  conceptually start with a direct mapping from the data model. This is as good  of a starting point as any. But we can follow a few guidelines to help play  to the strengths of object oriented design.<\/p>\n<p>Any time you see a Type field, such as  AddressType, in the back of your mind, you should be thinking about  differentiation through inheritance and look for an inheritance structure.  This is what leads us to create a class for each address type.<\/p>\n<p>Any time you see a table with fields  that will not always be populated, think about inheritance with the optional  fields being defined in a derived class.<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1062-NH2.JPG\" alt=\"1062-NH2.JPG\" \/><\/p>\n<p>Anytime you see a one to one  relationship in the database, check to see if you have an opportunity for  inheritance. Quite often the development model will benefit from including a  derived class that includes properties from the other table.<\/p>\n<p>These are guidelines and may not always  hold up to close scrutiny, but they will usually warrant a closer look.<\/p>\n<p>Development models will also generally  have a split personality, or at least a split implementation. We will  generally have two components and the less these two components know about each  other the better. By this, I am referring to keeping the development model  database agnostic.<\/p>\n<p>Many people may argue the merits of  keeping the development model completely ignorant of the database, and for good  reason. Many of the arguments commonly used to support this stance talk about  switching database vendors which will rarely happen for most people, but there  are still compelling reasons for this approach. True, you may actually switch  vendors; I have had to do this before. You may also need to switch from a  database to making web service calls instead.&#160;&#160; I have also had to do this.&#160;&#160;&#160;  There is also some merit for testing and demos if you can cut the actual  database out of the loop all together.<\/p>\n<p>Let&#8217;s consider what it takes for the  development model to be database agnostic. First, do expose anything from the  System.Data namespace. This means no DataSet, no DataTable, no DataReader,  etc. In the past, I was less dogmatic about this and was OK exposing key  interfaces from this namespace, but, allowing these interfaces still ties you to  having a database somewhere. The approach we will outline here makes it  relatively easy to switch to web services or static xml documents or mock  objects, etc.<\/p>\n<p>To get just a little bit more dogmatic,  let&#8217;s further restrict to expose interfaces only and no classes. So if your  development model has entities like Broker, ClosingAgent, and Appraiser, we will  use interfaces like IBroker, IClosingAgent, and IAppraiser.<\/p>\n<p>Why interfaces? They give us extra  flexibility. Implementing business logic against interfaces means that any  object implementing the interface can be used. This has some very nice  implications for testing. It also allows us to develop and test the business  logic without having a database connection. This can be useful to expedite  development. You can start developing before you even have the database  created. Once you have the interfaces defined, you are ready to implement  business logic.<\/p>\n<p>This also provides some exciting  opportunities for giving software demos in isolation. Just as you can test the  application using any object implementing the interfaces, you can also run the  application with any object implementing these interfaces. It can be very  useful to provide a series of objects implementing these interfaces pulling data  from xml files. This way every time the application runs, you can be guaranteed  to get the same results and you won&#8217;t have to worry about external influences on  the database compromising the demonstration.<\/p>\n<h2>Pulling It All Together<\/h2>\n<p>To follow data  from Model through View, we can have both ends implement a common interface.  For our Broker entity, these interfaces may look like this model. A couple of  important thing to note are the use of base interfaces and the repeated use of  IVendorBase. By using IBroker as the base interface for IBrokerModel and  IBrokerEditorView we are guaranteed that every property will be available at  both ends. By using the reflective data mapper outlined in <a href=\"http:\/\/www.simple-talk.com\/dotnet\/.net-framework\/a-defense-of-reflection-in-.net\/\"> an earlier article<\/a> we are guaranteed to have every property mapped on both  the save and data bind.<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1062-NH3.JPG\" alt=\"1062-NH3.JPG\" \/><\/p>\n<p>For the Presenter, which has both the  View and the Model, saving and data binding is a simple straightforward  operation.<\/p>\n<p>MapData can handle mapping data from the  model to the viewThe details lies in the View implementing simple properties  that manipulate the UI.<\/p>\n<pre class=\"lang:c# theme:vs2012\">\t\/\/\/  &lt;summary&gt;\n\t\/\/\/ Maps the data.\n\t\/\/\/  &lt;\/summary&gt;\n\t\/\/\/  &lt;param id=\"model\"\"&gt;The model.&lt;\/param&gt;\n\tprivate void MapData(IModelBase model)\n\t{\n\t&#160;&#160;&#160; var mapper = new Mapper();\n\t&#160;&#160;&#160; mapper.CopyTo(model, view );\n\t}\n<\/pre>\n<p>The save event raised by the view is  equally straightforward:<\/p>\n<pre class=\"lang:c# theme:vs2012\">\tprivate void View_Save(object sender, EventArgs e)\n\t{\n\t&#160;&#160;&#160; IBrokerModel&#160; model;\n\t&#160;&#160;&#160; if (view.PrimaryKey &gt; 0)\n\t&#160;&#160;&#160;&#160;&#160;&#160;&#160; model = Model.Model.Load(view.PrimaryKey);\n\t&#160;&#160;&#160; else \n\t&#160;&#160;&#160;&#160;&#160;&#160;&#160; model = new Model.Model();\n\t&#160;&#160;&#160; var mapper = new Mapper();\n\t&#160;&#160;&#160; mapper.CopyTo(view, model);\n\t}\n<\/pre>\n<p>Because the View exposes the Save event,  the Presenter can wire up to it and handle the saving when the view raises the  event.<\/p>\n<pre class=\"lang:c# theme:vs2012\">\tpublic ProfilePresenter(IBrokerEditorView&#160; editorView)\n\t{\n\t&#160;&#160;&#160; view = editorView;\n\t&#160;&#160;&#160; view.Save += View_Save;\n\t&#160;&#160;&#160; if (view.PrimaryKey &gt; 0)\n\t&#160;&#160;&#160; {\n\t&#160;&#160;&#160;&#160;&#160;&#160;&#160; IBrokerModel model&#160; = Model.Model.Load( view.PrimaryKey );\n\t&#160;&#160;&#160;&#160;&#160;&#160;&#160; MapData(model);\n\t&#160;&#160;&#160; }\n\t}\n<\/pre>\n<p>In the Page_Load&#160; event, the view can  introduce itself to the presenter:<\/p>\n<pre class=\"lang:c# theme:vs2012\">\tprotected void Page_Load(object sender, EventArgs e)\n\t{\n\t&#160;&#160;&#160; ProfilePresenter presenter = new ProfilePresenter((IBrokerEditorView) this);\n\t}\n<\/pre>\n<p>Alternately, if the View is implemented  in a user control, then the introduction can take place in the containing  page.&#160;&#160; Regardless, the view does not need to know anything about the presenter  beyond this initial introduction.&#160;&#160; When it comes to raise the save event, the  View is once again completely oblivious to the presenter:<\/p>\n<pre class=\"lang:c# theme:vs2012\">\tprotected void btnSave_Click(object sender, EventArgs e)\n\t{\n\t&#160;&#160;&#160; if (Save != null)\n\t&#160;&#160;&#160; {\n\t&#160;&#160;&#160;&#160;&#160;&#160;&#160; Save(this, e);\n\t&#160;&#160;&#160; }\n\t}\n<\/pre>\n<p>All the View has to worry about is  responding to UI events and interact with UI controls. The Business logic is  implemented in the Presenter. The View does not have to worry about the  business logic and the Presenter does not have to worry about the UI.  Similarly, the Model handles interacting with the database or whatever  persistence strategy is being followed. The Presenter does not have to worry  about any of the mechanics of data persistence and retrieval, and the Model does  not have to worry about the business logic stored in the Presenter.<\/p>\n<h2>Conclusion<\/h2>\n<p>Separating the layers and dividing the  concerns results in multiple components that need to be implemented, but each  component is relatively simple. Such separation also makes the application as  a whole more resilient to change. Properly structured, the individual layers  are separated through interfaces and shielded from changes in the other layers.<\/p>\n<p>This is a great way to structure a web  application. The resulting implementation can be spread over a larger team  than would be practical without this separation. The final product will be  more stable and easily maintained since each layer can be treated independently.<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the third of a series on Web Application design, Nick turns his attention to the Model part of the Model View Presenter (MVP)  pattern, and discusses what a well-behaved model might look lik&hellip;<\/p>\n","protected":false},"author":221853,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4229,5221,4242,5168,5222],"coauthors":[],"class_list":["post-915","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-net-framework","tag-back-to-basics","tag-basics","tag-nick-harrison","tag-web-application"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/915","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221853"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=915"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/915\/revisions"}],"predecessor-version":[{"id":91124,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/915\/revisions\/91124"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=915"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=915"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=915"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=915"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}