by Dick Wilson, Wednesday, January 23, 2008
Best Practices in Software DesignDoing It My WayI have always been an engineer, developer, builder that appreciates the simpler things in life. Although I pay great attention to details, it has always been my experience that
the simpler, the better, the easier to maintain. While it is true that a architectural foundation of your business web site should mirror the business model (or layout of departments), in my opinion. The layering and classifications are another aspect of the model that should apply the general layout of the web site.
The BasicsThe root folder of your web site should contain those basic HTML or ASPX files. Typically these are the navigational pages. Most web sites, in this configuration, only have one default.aspx file that may redirect the user to any number of other folders or base files based on the user request or user security. In otherwords, if a user is
joe public coming from the internet with
guest clearance, default.aspx may redirect joe to the public folder which houses a default.aspx web application or bunch of generic HTML pages promoting the business, business services, or products. If the user logs into the system and is found in the users database to be a subscriber with membership status, then they are redirected to user accounts pages. And if the logged in user is found to be a staff member of our company, then they are taken to the content manager system pages so they may conduct business related functions per access group and department. This description, in a nutshell, is how our FRAMEWORKS product is laid out.
Lets assume the guest user selects a link that goes to the products catalog pages; another folder with a separate web application for catalog pages. And the user elects to create an eCommerce shopping cart, add products to it, and will eventually checkout, purchasing the products (we hope). The shopping cart is another folder, another web application project, and the cart pages are included with products pages. This can be of your design in the product pages to include cart pages when the cart has been selected by the user; or it could also be part of the master pages used by product pages and available only when the user creates the cart. Again, design choices to suit your needs and business model practices.
The overall layout is to break down each piece or part of the processes into their own folders with their own project. It makes it much easier to design them, build them, and debug them. Once you know each project (or piece) is working, you can implement it within the overall web site.
Classification, Layering, and LayoutI will tell you right up front, I do not subscribe to the MVC (Model-View-Controller), Data-Transfer Objects, Business Entities, or any other type of MODEL. I like the good old standard client-server relationship with n'tiers where my business rules reside in the main middle tiers. I think of the backend, those objects or classes living beyond the middle tiers, as a 3-D object oriented world; like juggling balls, each with its own classification and maybe even distinct namespace. If the front end (the GUI) needs to speak with some object or get some functionality from the backend, typically it is done through the middle tiers. Although there maybe exceptions, the GUI NEVER speaks directly to the back end library objects or classes. That would walk around the layer of business rules. And even though I may not require a business rule for all requested functionality coming from the GUI, if I do not follow this
PATTERN of Coding, then I will certainly end up playing the exceptions game for every possible functionality requested from the GUI that may need to change. That is a mouth full. I hope it makes sense to you.
The middle tiers are a central point for application communications where all backend classes meet and where the GUI can make ONE CALL methods to acquire all the funcationality of the backend without direct interaction. This isolates the back end from the front end while making a very nice plateau (class) where I can write intermediate code to form business rules; or just make generic methods that utilize the back end methods as I wish in this web site; or describe the relationships and amount of interaction I wish to allow in the backend between backend classes.
Here is the magic of this layout. You can have many middle tiers, designed for a purpose, grouped by folder location, grouped by namespaces, and distinct to a business process or rule. You should always have a container class that carries the application configuration data and a container class for user security. These classes can be implemented, just like the back end classes, in the middle tier. So there is typically at least one main middle tier with these kinds of implemented classes. This is also the cental point class for error handling and event logging. So if any of the back end classes results in an error, the middle class is informed about, processes it accordingly and notifies the GUI if required. In a winforms application, the instantiation of the middle tier is always available while the program is running. In a web application, you can save the middle tier classes to the
session object to carry between pages posting and navigating. In fact I typically implement the main middle tier in such a way that it asks if the class exists in the session object, if so, then get it. If not then implement it new.
For pages that require user login, if the user is not logged into my system, then I redirect (via the middle tier) to the login page. In this way I do not have to rely on the security of IIS, SQL, or other. I decide what pages are available to what group of users and to what degree. If I need to pass critical data between pages (either
get or
post), I encrypt it. If I suspect that others might like to hack these pages or do a
man-in-the-middle attack on my pages, then I devise a security schema that changes per page and checks for verification on every submission so I know origination. If security descriptors do not match, the page is redirected automatically via the middle tier to the login page, default page, or somewhere in the galaxy; including the users own machine via IP address.
In this layout that I call
the n-tier-3D Object Oriented Programming, you may add as many middle tiers for processes as you wish or back end functionality as you wish without ever breaking current functionality. And if you stick hard and fast to these design concepts and keep the exceptions to a minimum, I think you too, will find it easily supportable and extensible.
A Bonus... GENERICSFirst off, let me tell you that I am a great believer in GENERICS methodology. That is the idea that you may create a method of class that offers some functionality or processing of data while passing a data container class the use for the processing. And I have NO PROBLEMS with the idea of also telling the processing class what type of output object I expect via enumerable choices. So while the List
function offered in the System.Collections.Generic namespace is the new method of choice in FRAMEWORK 2.0 (strongly typed because we tell it how to cast the object in the call); I have NO PROBLEMS with ArrayList as long as I, THE DEVELOPER, know what the casted output should be. GEE, I was smart enough as a developer to get to the IDE and start coding... I think I am smart enough to figure out the casting of an object via ArrayList. And actually I find the List functions to be sometimes restrictive for my purposes and coding. YES, I do use them, alot. But I have NO PROBLEMS with ArrayList and find little agreement with those that argue for STRONGLY TYPED methods. The strongly type DataSet with its XML data schema is baggage I need NOT carry around in my pages. If I do not use SQL as my business rules, then I will never have to wait on SQL Server to tell me whether I have requested a valid request before telling my user they can or cannot do some requested function. In my pages, if the user cannot do something, we don't EVER take him to a page to make it available in the first place. That makes it impossible to hack something the user can never see and does not waste CPU on any of the servers waiting for error results to tell the security.
Strongly Typed vs Loosely Coupled
In the textbooks I have read on the topic, any declaration that does not return the type of object, is considered strongly typed because it returns a well defined type. Again referring to the DataSets mentioned above. If you, as a developer, drag a table object from the server explorer view of an available SQL Server database; you end with a Data Transfer Object in your web page (for instance). This operation also creates a couple other files in XML format describing the details of the table, its attributes, and its associated security. And in creating all this information for one data adapter, tightly coupled to the database-table; it is considered strongly typed. Anything else that does not have the associated files and XML information, is considered loosely coupled. Likewise, if something changes about the table after the creation of the DTO (data transfer object), then your page is BROKEN. And the only way to fix it is to go back and repeat the process of creation. While this may or may not be the case for loosely coupled designs depending on how you implemented the coding for coupling.
Now this might be fine for a single page coupled to a table that will NEVER EVER change in the history of this web site, but I would not want this problem across 700 pages in an enterprise web application doing reporting.