A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.
I was under the impression that as a software engineer I was supposed to try to keep the business logic away from the GUI logic, just in case I needed to change the GUI, or the business logic that affects lots of parts of the GUI in the future. I am reasonably new to asp.net, but almost every example I have seen has a button_click method that includes business logic and data access layer logic. As I am coming from windows forms this bothers me _a lot_. Am I missing something? Can somebody validate my observation and then point me to examples where that isn't the case please? Thanks.
Well, in ASP.NET the UI is supposed to be rendered in the .aspx file (with the help of server side controls that emit HTML) while the business logic is supposed to be located in the .aspx.cs (or .aspx.vb) file that is the "code behind" file. This is a step ahead of traditional ASP where you'd have one file with mixed HTML and script tags.
Now, to your point about including business logic and data access routines in an ASP.NET code behind class, I'd agree that you shouldn't do that and should delegate whatever processing needs to be done to another class (or library). The simple answer is 99% of examples aren't done using the best architectural patterns/practices in order to keep them simple.
Saturday, July 09, 2005
If you are a follower of the MVC pattern, you could consider the code-behind file to be the controller to the aspx's view.
Business logic doesn't belong in the controller. It belongs in the model. Putting business logic in the code-behind, then, is probably not right for an MVC-style application.
Saturday, July 09, 2005
Speaking as an ASP.NET developer, I think I would actually give this question two different answers, for different situations:
1. No. In a lot of situations, the "business logic" is almost exactly the same thing as the database schema, with the exception of the security system and other minor pieces. When this is the case, most of the 'logic' of adding, editing and deleting records is the responsibility of the O/R Mapper (LLBLGen Pro), which makes the project just as simple as it should be and doesn't involve as much work for us. (If you haven't tried an O/R mapper, LLBLGen Pro is excellent.)
2. Yes, if there is a LOT of business logic beyond just the database tables and relationships. It should probably be moved into a simple class or set of classes or something.
I am doing this extensively for my current project; the business logic will be in several classes, in two different projects, and will be a few thousand lines of C#, mostly wrapping the O/R mapper activity and some searches and sorts, but it is already saving me effort of replication for some things.
Saturday, July 09, 2005
These are all good answers. I don't think I made myself entirely clear, and I apologize.
I don't consider the code behind the place to put business logic. I consider that code behind part of the GUI because that is where events are caught, like button clicks. I have separate business logic and data access layers (DAL), so the database manipulations are all done in the DAL.
My concern was that if I put the business logic somewhere other than the code behind then I can't get to useful variables like this.Session, this.Application, this Response, this.Request, and this.Cache that are available from within the code behind (a subclass itself of System.Web.UI.Page). Is there some standard solution for this that I just don't know about because all the asp.net examples are smashed into the code behind?
Forgive my ignorance,
Also, I just figured out that Trace doesn't work in my business logic classes either. So, since I am building a website that is "Forms" authenticated and since I am trying to use business logic, there is no standard way to debug. Because I am "Forms" authenticating VS.NET won't go into debug mode. Further, Trace isn't available unless I pass it as an arugment to the business logic. This is starting to get on my nerves. I must be missing some business logic design paradigm or something. Where am I going wrong?
What you're missing is the HttpContext class. From your non-code-behind classes, you can use the following, for example:
The HttpContext class defines properties for Application, Session, Cache, Request, Response and Trace (among others - check the documentation for more).
For a large ASP.NET project that I worked on we used CodeSmith to generate the data layer automatically from the tables on the database. This way if we needed to add fields, we just added them to the table and then re-ran CodeSmith to get new base classes for the data layer. We then put custom code in a derived class that was used in the aspx code behinds. The nice thing is that you can then setup some nice tests with NUnit or whatever system you like to test the data layer separate from the website UI and this can help to find problems easier.
Josh - you're right; logic in the code-behind should properly be presentation logic, not business logic. That's if you're following a tiered or decoupled model. Of course, many people don't do that, and put their business logic in the Web pages because their stuff is zero-tier, and while this is A Bad Thing from many points of view, from a business point of view it can make eminent sense to throw some stuff together quickly.
If you do wish to build in a tiered manner, you need to strongly decouple your tiers. This means that, while you can get access to Page.Request, Page.Response etc from your business logic classes using HttpContext.Current as outlined above, you shouldn't do so. Your business logic should be isolated (as a separate assembly, usually a DLL) from the presentation logic, and ideally from the data access logic as well (use of a good OR mapper gets you around having to build a big DAL every time).
The ideal of decoupling is that you should be able to take each tier and re-use it (provided you can satisfy any contracts the API implies). The canonical example of this is a middle tier API which can be hooked into a Web app or a Windows forms app with equal ease. Such an API has to be totally decoupled from the presentation tier, so no use of System.Web or System.Windows.Forms.
A system which is built in tiers but where there is strong coupling between the tiers is better from an architectural point of view, but doesn't accrue as much advantage in terms of potential for re-use.
My own strategy for building n-tier Web systems has been to establish a core set of base services that I can pull together in the form of APIs and frameworks; these are generic and can be re-used across multiple projects. Then I build specialised business logic frameworks on top of these, and finally the presentation layer (or layers) on top of that API.
Hope that helps...
Monday, July 11, 2005
I completely agree with your assessment concerning using the HttpContext in the business logic; I don't want to. It is a good idea to build up functionality from a core set of business logic. Someone else also mentioned using CodeSmith to create the data access layer (DAL) files. I do something similar to that with a homegrown tool. My tool takes a database and write the DAL and data containers. I have used it for both Winforms and Web applications. I had not considered trying to generalize the business logic so that it would work in both cases as well.
I think I was just disappointed that it was so hard to implement the tiered model in ASP.NET. I was disappointed also with the documentation that is available on msdn.com. I just wanted to make sure that I wasn't overlooking the "good" documentation.
All of your suggestions have been good, thank you everybody!
Tuesday, July 12, 2005
>>I think I was just disappointed that it was so hard to implement the tiered model in ASP.NET.
C'mon guys, it's the same as Java. No harder. Tiered model is fundamental thing and can be implemented on almost any oo language (even PHP & Perl).
Wednesday, July 13, 2005
Joshua Volz, they figure you'll know better and be bothered by it. However, it suits their textbook examples.
Generally I have found the following work with me. I have business tiers that are fairly object-oriented. Methods and assertions are associated with these logical objects. However, there are two school of thought on how such business objects should interact with your front-end, and this results from how people really use asp.net. The problem is your data tier. And really, it's about what the proponents of Custom Entities call Data Access tiers.
In the Custom Entities (CE) school of thought, Basically you have a school of thought that thinks you should expose datasets/datatables generated in the data tier all the bloody way to the DataGrids and Repeaters in Webforms. You'll read about them in . In this format, the business tiers will be CustomCollections (generated by fine tools like CodeSmith) of logical inheritable objects with all the relationship established by containment/references and all the fields represented by typed intrinsic types. The Data Access tier/layer would be responsible for defreezing/freezing these CEs. With the help of a Data tier that does little more than helper functions like build sqlcommand calls to stored procedures or dynamic sqls (I personally prefer stored procedures, for sucurity reasons). The CE people love the fact that you aren't always trying to remember hard-coding offsets of collections within offsets of connections. You aren't doing type-checking at run-time. The fact that the relationships between objects are C# friendly. Those are some of the benefit of Custom Entities.
The other school of thought says , you CEs are a bunch of architectual astronauts. Yes, we don't argue with your assertions about the difficulties caused by hard=coding offsets being bad due to breaking builds if you check row order in the db backend (for ex), but CustomCollections are too minimum, you lose a lot of the functionality of DataSets. And for RAD development with unknown specifications and ever more complicated requirements, it's better to bet on a heavyset struct like DataSet--you don't seriously think your CTO is going to sit around while you reimplement what DataSet has already done come crunch time? Unsafe? Typed DataSets are always available. Give me DataSets and DataTables and that's what I'll store internally in my business tiers. We have no shame passing those objects onto DataGrids and Repeaters.
At the moment I am trying the latter school of thought, which is to maintain 3 tiers, but let go of the idea that I shouldn't use DataSets talking to DataGrids. If RAD prototypes turn into billable projects, I would then rework them into typed DataSets/DatasTables talking to lighter web widgets like repeaters. It has been working out pretty well. It's pretty maintainable.
 Karl Seguin wrote an excellent introduction here: http://msdn.microsoft.com/asp.net/default.aspx?pull=/library/en-us/dnaspp/html/CustEntCls.asp
You are more than welcome to search google furthur for other talks about CEs, just search "custom entities".
 Effective C# - 50 Specific ways to improve Your C#
You should add method regions (#region "Methods") to your presentation code behinds. These are called by the btns and events. They then create the Business Objects (BO) like Users, ShoppingCart, etc etc and invoke logical public members on these BOs.
The BOs don't call the presentations tier, they are invoked by presentation tier or any other actors that need to act on them.
If you can check out UML Distilled and attach a drawing to what you are doing, it might explain a bit about what you are uncertain about.
If you can't trace something, a good idea is to make your BO toString able. That way your webbies debugging your system can trace the state at any time. toString would just concat the intrinsic typed instances in your object (with readable labels) and wwell, toString them.
s/In the Custom Entities (CE) school of thought, Basically you have a school of thought that thinks you should expose datasets/datatables generated in the data tier all the bloody way to the DataGrids and Repeaters in Webforms./In the Custom Entities (CE) school of thought,/In the Custom Entities (CE) school of thought,/
Sorry, I was contradicting myself. Custom entities stops the data objects from System.Data at the Data Tier, refusing to let them propagate to Business tier.
The last school of thought bounces away again bounces away from the DataSet camp's ideas and say, "Disconnected datasets and friends are way over-used, use readers. They fit with all the web widgets anyway, and save you a ton of over-head." Scalability trumps all other concerns!" This school of thought is something I subscribe to when I am trying to keep the page light if it gets enough hits. Application Center (a part of Visual Studio enterprise) will help you profile the page to tell you the performance story behind each of these methods.
This topic is archived. No further replies will be accepted.Other recent topics
Powered by FogBugz