Sep
21
2006
Class design considerations - howto part 9
Posted by admin under
In practice
Please read this article serie In practice from the beginning.
Background and repeating our object model
I now want to discuss the classes we have created, lets take a look at Customer in detail. Our key goal was to get objects to work with from our ASPX pages:
CustomerClasses.Customer oCustomer = GetCustomer();
if (oCustomer == null)
{
header.InnerText = "New customer";
}
else
{
header.InnerText = "Edit customer";
txtName.Text = oCustomer.Custname;
//Setup repeater existing
rptExistingFiles.DataSource = oCustomer.Files;
rptExistingFiles.DataBind();
}
Code like that sure looks pretty nice. It's from the Page_Load event in editcust.aspx and we load an existing customer through GetCustomer() -
private CustomerClasses.Customer GetCustomer()
{
if (Request["id"] == null)
return null;
CustomerClasses.Customer oCustomer = new CustomerClasses.Customer();
if (oCustomer.Open(Convert.ToInt32(Request["id"])) == false)
return null;
return oCustomer;
}
which pretty much just instantiates a Customer object and calls .Open( Request["id"] ) on it.
We can then use the properties from the customer object to set our GUI control values. However lets look at the Save function (save button click event ):
int lId = -1;
if (Request["id"] != null)
lId = Convert.ToInt32(Request["id"]);
lId = CustomerClasses.Customer.Save(lId,
txtName.Text);
Notice the difference? Here we are still working against the CustomerClasses.Customer class, but we are using it in a stateless way - calling the static function Save and feeding it with Id and name from the textbox.
Design considerations
Why is that? Why don't we use a stateful approach with code like this:
int lId = -1;
if (Request["id"] != null)
lId = Convert.ToInt32(Request["id"]);
CustomerClasses.Customer oCust = new CustomerClasses.Customer();
if ( oCust.Open( lId ) == false )
{
oCust.Id = -1;
}
oCust.Custname = txtName.Text;
oCust.Save();
a) the stateful approach above would lead to an extra database roundtrip when saving.
b) that object would just be thrown away after saving - ( we are in affect calling Response.Redirect just after this). The stateless nature of web applications makes us (or at least me) use more stateless programming - even when modelling. In contrast when developing a stateful Windows form application we can trust more on state.
as for b) you might think that I am stupid - when developing the BLL you shouldn't take into consideration which type of GUI layer should be using it (Windows Forms state or Web forms stateless). And you are of course right about that - at least by the books.
However, to defend myself - I kind of believe that object modelling is overrated. What I mean by that is the kind of object modelling where you try to model the world excactly as it looks. I always try to look at it from the other way around : try designing an object model which makes coding the overlying layer (in this case the GUI) as easy as possible. The overlying layer code should look good - programming that layer should be as easy as possible. Try to design your object model a little more from that perspective I say.
In the case of our objects in this project being modelled a little to much around stateless programming (read Web Forms) instead of stateful (read Windows forms) - yes I admit it. But the facts as of now are
1. we KNOW for sure this object model IS gonna be used from a Web Forms GUI
2. we DON'T know if it's ever gonna be used from a Windows Forms GUI. Or in fact - we KNOW it will NOT be as of right now
Based on these facts, to me it makes sense to do some optimizations for the Web Forms type of GUI.
If someone later told me, "Stefan - now it's time to use your famous Customer class from our Windows Forms GUI" the options would be to
a) add stateful calling as described above (oCust.Save();). It could call the static Save function. Nothing have to exclude the other
b) create a new class deriving from CustomerClasses.Customer
My whole point is: when it comes to designing - don't make it too hard. Model against your requirements (of course you should take into consideration some expected future requirements) - but there's no need overdoing things. Cause the world does constantly change - and if you model the whole world your model will need to change as well.
Disclaimer
As I have said before - my point with this article serie is not to say my way is the best. I created this particular article to make you see there are many different ways of object design - and my best advice to you is CODE, CODE, CODE. Try different ways, see what works for you. Noone can say something about best practice for you but you!