Practical object-oriented design

I am making the transition to a more object-oriented approach to ASP.NET web applications on a new system I am developing.

I have a general structure that most people will be familiar with. I have a school structure with several departments; courses belonging to one department; and students belonging to multiple courses.

In the department view, I am listing all the courses that are specific to the department and I want aggregates for each course like enrollments, withdrawals, men / women, etc.

However, on an individual basis, I need an actual list of students, as well as their details such as: they are enrolled, they are taking the course, gender, etc.

And then the individual student view, where all the details about the student are displayed, including registration for other courses, address, etc.

In the past, I would have a data access layer returning all the data I need in each case and returning it as SQLDataReader

or DataSet

(running on VB.NET). I am now trying to model this in an object oriented way. I am creating objects in DAL and returning them to BLL . I'm not sure how to handle this though, when I need aggregated data in objects. For example, in a department view with a list of courses, I will have summaries for each of the courses. Will I keep a collection of some light course objects in a department where these light course objects store aggregated values?

My guess is that different scenarios require different levels of abstraction and I'm not sure what is the best way to handle this. Do I have to have an object model where there is a very simple course object that stores the aggregates and a child that will hold the complete part?

Also, if there are any helpful resources that can help me figure out how to model things like that that would be good.

+2


source to share


4 answers


Don't overload things or do unnecessary work. Databases are ideal when it comes to data manipulation, so let the DB do the aggregation. From the code side, add another object to your object model and you will be fine and dandy:

class CourseStats
    string Name { get; }
    int Enrollments { get; }
    int Withdrawals { get; }

      



The SQL for performing aggregation is pretty straightforward. However, make sure you are using an ORM (think NHibernate ) or the less complex Result-Set Mapper (think BLToolkit ): you really don't want to manually moisten these objects.

An added benefit is that you can cache both query results (and invalidate the cache as soon as course related changes).

+4


source


This is actually a pretty big problem that many people struggle with.

As far as I have been able to identify, there are at least two schools of thought in this issue:

  • Permanently unaware domain objects with OR / M that support lazy loading.
  • Domain driven development and explicitly modeled (and explicitly loaded) aggregates


Jeremy Miller has an article in MSDN magazine that looks at some of the save patterns.

The Domain-Driven Design book has a good discussion of aggregate modeling.

+1


source


If there are multiple departments and each has a small number of courses, just download everything and your objects will do the math (i.e. the department goes through the list of courses and just sums up what you need).

An alternative approach would be to run the sums against the database using some custom, native SQL. You can hide this in the DAL. The DAL will then return, for example, a virtual course (which does not exist in the database, but contains amounts).

The third approach is to store these values ​​somewhere in the department object and update them every time a course is changed / added / removed.

0


source


One thing you should learn if you are working with .NET is LINQ to SQL . This will allow you to have a very elegant interface in your DAL. LINQ will allow you to create aggregate queries in your BLL that preserves the plumbing code, as well as the hideous SQL snippets circulated throughout your source. An example from the previous link of an aggregated SQL query expressed using LINQ:

var averageOrderTotals =
  customers.
  Select(c => new {
      c.Name,
      AverageOrderTotal = c.Orders.Average(o => o.Total)
   });

      

I switched my database layer to LINQ, although in my case I am not using MS SQL Server, so I used the DbLinq library instead .

The very last thing you want to do is change your classes to match your level of database access, making this approach very fragile.

0


source







All Articles