Arctus Blog: Shifting mindsets: MVC for .NET applications http://blog.arctus.co.uk/articles/2007/05/04/shifting-mindsets-mvc-for-net-applications en-us 40 Shifting mindsets: MVC for .NET applications <p>Change is something that blows gently through the world of computer programming. Old best-practices from years ago remain in use long after new best-practices have been invented.</p> <p>For example, it might surprise you to learn that the &#8216;new kid on the block&#8217;, Ruby, has been around for over 10 years. That&#8217;s over twice as long as .NET! It is only now taking off, and I suspect that is because it is closely aligned with the current thinking of leading programmers.</p> <p>.NET, as a framework, is slightly exceptional in that it gained quite a lot of traction in just a couple of years. That probably had more to do with Microsoft&#8217;s tactics (encouraging people to upgrade), and the strong need to replace <span class="caps">ASP</span> and <span class="caps">VB6</span> than any particular special properties of .NET as a whole (after all, it&#8217;s little more than Java-in-Disguise).</p> <p>One of the strange consequense is that we now have a relatively good language (C#), and a rather good technical framework, but that many practices and methods are lagging behind.</p> <h3><span class="caps">DAL</span> &#38; <span class="caps">BLL</span></h3> <p>Let me be clear: <span class="caps">DAL</span> and <span class="caps">BLL</span> have no future. They are not a good way to structure an application. I want to say that <span class="caps">DAL</span> and <span class="caps">BLL</span> are dead, but sadly they are not. Developers throughout the Microsoft kingdom are still using <span class="caps">BLL</span> and <span class="caps">DAL</span> on a daily basis.</p> <p><span class="caps">DAL</span> and <span class="caps">BLL</span> were invented to solve a problem that doesn&#8217;t (and never did) exist for most developers. It allows you to run the &#8216;business&#8217;, the &#8216;data&#8217; and the &#8216;presentation&#8217; layers on seperate servers. The layers would communicate over <span class="caps">COM</span> interop. However, the business layer very rarely needs its own server.</p> <p>Let me re-phrase that slightly: your application will never actually need to run <span class="caps">DAL</span> and <span class="caps">BLL</span> components on seperate servers, and you&#8217;re jumping through hoops for absolutely no reason whatsoever. (If you are actually running the layers on seperate servers, you could probably get a useful speed boost and save yourselves some major headaches by re-writing the application and consolidating).</p> <p>What we&#8217;re doing when we force an application to use a <span class="caps">BLL</span>/DAL split is completely at odds with the natural structure of our programs.</p> <p>Most often, what we get is something like the simple example below. This code is for an imaginary quotation system:</p> Presentation layer (the web page): <div class="CodeRay"> <div class="code"><pre><span style="color:#080; font-weight:bold">protected</span> <span style="color:#080; font-weight:bold">void</span> Page_Load(...) { QuotationManager qm = <span style="color:#080; font-weight:bold">new</span> QuotationManager(MyConnectionString); ActiveQuotationDataSet aqds = qm.GetActiveQuotations(m_txtField.Text); ActiveQuotationList.DataSource = aqds; ActiveQuotationList.DataBind(); }</pre></div> </div> Business layer (BLL) <div class="CodeRay"> <div class="code"><pre><span style="color:#080; font-weight:bold">public</span> <span style="color:#080; font-weight:bold">class</span> QuotationManager { <span style="color:#080; font-weight:bold">private</span> <span style="color:#339; font-weight:bold">string</span> _ConnectionString; ... <span style="color:#080; font-weight:bold">public</span> ActiveQuotationDataSet GetActiveQuotations(<span style="color:#339; font-weight:bold">string</span> SearchText) { QuotationDAL qd = <span style="color:#080; font-weight:bold">new</span> QuotationDal(_ConnectionString); <span style="color:#080; font-weight:bold">return</span> qd.GetActiveQuotations(SearchText); } }</pre></div> </div> <p>I don&#8217;t really need to illustrate the data layer because we can assume that it will simply call a stored procedure and return the results to the business layer, which in turn will return the results to the web page, which finally binds the dataset to a list.</p> <p>I see many applications with hundreds and hundreds of these methods, all of which perform this strange ritual of passing data back and forth while adding no value. Methods that add no value have no right to exist.</p> <p>Additionally, the methods might as well be static. This is not object oriented programming&#8212;and this is especially true if what goes in and comes out of the <span class="caps">BLL</span> are nothing more than datasets and basic values.</p> <p>This is basic procedural programming, a la <span class="caps">VB6</span>. It is 15 years out of date. It is time to move on.</p> <p>You might be looking at the above example and thinking &#8220;actually, it&#8217;s not that bad, the <span class="caps">BLL</span> is just a little redundant&#8221;. For lists of data I can see this point, but I see it used for everything &#8211; loading a single object &#8211; saving that object &#8211; creating new objects &#8211; deleting objects. Everything.</p> <h3><span class="caps">MVC</span></h3> <p><span class="caps">MVC</span> is a pattern described by the &#8216;gang of four&#8217; in their famous book on software design patterns. This pattern is nothing like a Microsoft &#8216;pattern&#8217; (an article on that to come soon). It is an idea, wrapped up in a concise description. It describes a nice way of using real-objects to create programme structure.</p> <p>The M in <span class="caps">MVC</span> stands for Model. By Model, we mean classes that model your real-world situation, not helper classes or web pages.</p> <p>V and C stand for View and Controller respectively. While it is difficult to completely seperate V and C in .NET, we can assume, for the time being, that the View is the <span class="caps">ASPX</span> pag and the Controller is the code-behind. That distinction is Good Enough.</p> <p>When writing <span class="caps">MVC</span> we create objects (classes) that represent our real-world artifacts (our adjectives). These classes will have methods that describe the verbs we use when talking about the artifact. For example, instead of a Qutation <span class="caps">DAL</span> and <span class="caps">DLL</span> that have operations like &#8216;GetListOfQuotations()&#8217;, &#8216;GetSingleQuotation()&#8217;, &#8216;CreateNewQuotation()&#8217;, &#8216;SaveSingleQuotation()&#8217;, and so on, we would have a Quotation object:</p> <div class="CodeRay"> <div class="code"><pre><span style="color:#080; font-weight:bold">public</span> <span style="color:#080; font-weight:bold">class</span> Quotation { }</pre></div> </div> <p>This would have methods analagous to those that we previously had in our <span class="caps">BLL</span> and <span class="caps">DAL</span>, but considered in relation to the operation it performs directly on or with the object:</p> <div class="CodeRay"> <div class="code"><pre>Load(<span style="color:#339; font-weight:bold">int</span> QuotationId) Save() Delete() Find() <span style="color:#080; font-weight:bold">static</span> Quotation[] Search(<span style="color:#339; font-weight:bold">string</span> SearchText)</pre></div> </div> <p>I&#8217;ll produce another article soon that gives examples of the way these classes and methods can be written and structured, and later I&#8217;ll also show you how you can express relationships between two such objects.</p> <p>The upshot is that you can write code like this:</p> <div class="CodeRay"> <div class="code"><pre>Quotation[] quotations = Quotation.FindAllByConsultant(ActiveConsultant); Quotation quotation = Quotation.Load(_QuotationId); Quotation q = <span style="color:#080; font-weight:bold">new</span> Quotation(ActiveConsultant); q.Customer = txtCustomerName.Text; q.Price = txtEstimatedCost.Text; q.Save();</pre></div> </div> <p>This is fully compatible with the concept of using relational databases to back the applications. We simply make the object responsible for loading/saving itself to/from the database. For high-performance databases we can use techniques like lazy load and batch fetching of data (with the use of Helper classes) to speed things up.</p> <p>Finally, to replicate our earlier example:</p> <div class="CodeRay"> <div class="code"><pre><span style="color:#080; font-weight:bold">protected</span> <span style="color:#080; font-weight:bold">void</span> Page_Load(...) { ActiveQuotationList.DataSource = Quotation.SearchActive(txtSearch.Text); ActiveQuotationList.DataBind(); }</pre></div> </div> <p>It is clear to see that using models correctly is much neater.</p> <h3>What next?</h3> <p>I appreciate that there is much that I have not discussed in this article. For example, it would be good if I gave you an example of such <span class="caps">MVC</span>-based classes and web pages. It would also be useful to see how I structure my <span class="caps">MVC</span> solutions and projects. I intend to address these matters very soon and shall also provide sample code.</p> <p>I also appreciate that if you are coming from a background of <span class="caps">BLL</span>/DAL it might be difficult to see at first what the difference truly is. Some of the differences are subtle, and you must remember that you are used to working in a certain way. I can, however, guarantee that if you are passionate about the art of programming that you will absolutely prefer this way of writing software once you are used to it.</p> <h3>But but but!</h3> <p>OK, what about heavy-use distributed apps running on server-farms? Don&#8217;t they absolutely need <span class="caps">DAL</span>/BLL? Well, if you went with Microsoft <span class="caps">COM</span>+ instead of one of the significantly better alternatives you either a) made a bad choice, b) employed Microsoft consultants or c) were paid/incentivised by Microsoft to do it that way.</p> <p><span class="caps">DAL</span>/BLL, even when used for its intended purpose, is just plain wrong.</p> Fri, 04 May 2007 07:25:00 -0400 urn:uuid:659460a3-3c05-447f-9843-2c37bc072205 adrian@arctus.co.uk (Adrian O'Connor) http://blog.arctus.co.uk/articles/2007/05/04/shifting-mindsets-mvc-for-net-applications .NET