Wrong Idea re: Classes?

  • Thread starter Thread starter MLecrone
  • Start date Start date
M

MLecrone

Seeking a bit of advice from the folks that manage or work in a group
producing multiple .Net web applications for a single
customer/company...

I have a nagging suspicion I have misunderstood what a class should be
truly used for - please feel free to provide any insight based on your
experience(s)...

My team is transitioning from our classic ASP environment to .Net
(yay!). I am attempting to construct a "big picture" view of how
future .Net web applications will be able to access shared resources
like our classic ASP applications do today.

In today's environment (briefly), we have a folder in the root of our
web into which we put subroutines and functions commonly used among
all web applications. To make use of these only requires a simple
server side include (SSI) and then away we can go without rewriting
code. Easy enough.

The most common functions/subroutines reused among all apps are those
that have to do with getting and then displaying employee-related
information (from backend SQL db). Most of our apps require some form
of that information to be displayed on their pages such as "You are
logged in as [UserName]" as well as being able to customize page
rendering based on who the person is, etc., etc.

The following thoughts are now my assumptions which may need to be
seriously corrected. Please feel free to do so...

The above seems to translate quite obviously into the need to create
an Employee class containing those common functions designed to get
and display employee info that can then be referenced in all apps that
need it. However, it seems that when one creates an object based on a
class, the intent is to SET the properties of that object (such as
Employee.FirstName = [value]) rather than dynamically pass the
employee's unique identifier to that object, have it go get and set
all the properties, and THEN be able to simply code something like
Employee.FirstName which would render the name retrieved from a
function that resides within the Employee class.

Is this overkill perhaps? Not the true purpose of a class? Any
thoughts are welcome.

Many Regards,
MEL
 
It sounds to me that you need to create a business layer and a data layer
for your application.

The business layer would contain classes that deal with your business logic
(employee information and employee classes would be created here). In the
data layer, you have classes that simply pass data back and forth from the
business layer to/from the database.

You could have in your business layer a method called getEmployee(arg) that
invokes the data layer and returns data from an employee record into a
dynamically created employee object. This employee object would have its
property values set by the data returned from the getEmployee() call.

Depending on whether these properties are set to readonly or not, the end
user can look and possibly edit the data.


MLecrone said:
Seeking a bit of advice from the folks that manage or work in a group
producing multiple .Net web applications for a single
customer/company...

I have a nagging suspicion I have misunderstood what a class should be
truly used for - please feel free to provide any insight based on your
experience(s)...

My team is transitioning from our classic ASP environment to .Net
(yay!). I am attempting to construct a "big picture" view of how
future .Net web applications will be able to access shared resources
like our classic ASP applications do today.

In today's environment (briefly), we have a folder in the root of our
web into which we put subroutines and functions commonly used among
all web applications. To make use of these only requires a simple
server side include (SSI) and then away we can go without rewriting
code. Easy enough.

The most common functions/subroutines reused among all apps are those
that have to do with getting and then displaying employee-related
information (from backend SQL db). Most of our apps require some form
of that information to be displayed on their pages such as "You are
logged in as [UserName]" as well as being able to customize page
rendering based on who the person is, etc., etc.

The following thoughts are now my assumptions which may need to be
seriously corrected. Please feel free to do so...

The above seems to translate quite obviously into the need to create
an Employee class containing those common functions designed to get
and display employee info that can then be referenced in all apps that
need it. However, it seems that when one creates an object based on a
class, the intent is to SET the properties of that object (such as
Employee.FirstName = [value]) rather than dynamically pass the
employee's unique identifier to that object, have it go get and set
all the properties, and THEN be able to simply code something like
Employee.FirstName which would render the name retrieved from a
function that resides within the Employee class.

Is this overkill perhaps? Not the true purpose of a class? Any
thoughts are welcome.

Many Regards,
MEL
 
I think that you are on the right track. I have been using the business object model with CRUD design pattern for years and I am very, very happy with it

I disagree a little with the other poster who replied to you, I believe that the data layer should be implemented via stored procedures, and the load/update/save methods should be members of you class

In the case of you employee object, there are two different ways you can go about getting the behavior you are after. You can make a constructor for your class that takes the employee ID as a parameter, and then fills in all of the employee info like

dim emp as new Employee(12345

txtFirstName.Text = emp.FirstNam

Or you can add a Load() type of method to your employee class

dim emp as new Employee(

emp.Load(12345
txtFirstName.Text = emp.FirstNam

Remember the golden rule of encapsulation in OOP: Objects should take care of them selve

This means that your object should contain all of the functionality related to an Employee. So you could also add a method to your employee called GiveRaise(amt as Single) that would call a stored procedure and update the Employee's salary (Though really this method should only be implemented in the derived ProgrammerEmployee class, as we are the only ones who really deserve it right? :-)) like

dim programmer as new Employee(12345

programmer.GiveRaise(10000000.99

Now the programmer instance of your employee class should completely know how to handle the GiveRaise method, because when the new(12345) constructor is called you would store the 12345 in a protected member variable like this

public class Employe

'protected member
protected m_lnEmployeeID as int3

public sub new(lnEmployeeID as int32

m_lnEmployeeID = lnEmployeeI

end su

public sub GiveRaise(amt as Single

'.... sql code her

cmd.parameters.add("@lnEmployeeID",m_lnEmployeeID
cmd.parameters.add("@snAmount", amt
cmd.ExecuteNonQuery(

'... more code her

end su

Hope this helps, please feel free to email me if you have other question

-Cla

clayton(dot)c(dot)gulick(at)verizon(dot)co
 
Scott and Clayton, thank you very much for the excellent information
and such clear examples! I can't describe enough how much this has
helped (or how fast I printed both posts off). :)

Scott, your comment about properties being read only or not has
*really* got me thinking. What if our user community could update
some pieces of their "profile" info from *any* of our applications
that made use of it rather than having to navigate to our online
profile manager? Awesome idea. I'm sure they get sick of jumping out
of one app just to correct a misspelling in their job title or name or
something...

Clay, I will definitely be implementing the GiveRaise() method at my
earliest opportunity - our team sure could use a boost what with
unending company mergers and all. :) And although I definitely need
more education of data and business layers, I am proud to say that I
wholeheartedly believe in encapsulation! Completely understood, thank
you.

There's so much to learn... Thanks again to you both.
MEL
 
MLecrone said:
Scott and Clayton, thank you very much for the excellent information

I also think Scott and Clayton gave excellent advise on object models.
However, there are reasons to question the whole idea of wrapping all your
businesslogic in classes.

In the 'Pure Object Model' the database should be hidden in a set of classes
that encapsulate and shield the rest of the application from it's
implementation. This is all very neat model, but takes it time to develop
and is a considerable codebloat.

Also, you loose some nifty features in .NET hiding all your data in classes.
With your own objects for all data in your application, you won't be able to
databind or expose functionality in web-services without considerable work.
This is a serious factor. Telling your management that you'll need days to
espose some functionality in a datagrid while your competition does the same
in hours or minutes is very dangerous in these times.

I use an adaptation of the Microsoft Reference Application Architecture
where 'Enteties' and 'DataTransferObjects' (DTO) are the core concepts. The
DTO is simply a typed dataset. The enteties are simple classes for handling
a DTO.

In this model I never try to hide primary-keys and such but expose them
happily in the application. The entity classes mostly have static methods
for manage entities. Hence a entity could look like this:

public class MyCustomerEntity
{
public static MyCustomerDTO FetchAll() { ... }
public static MyCustomerDTO Fetch(int customerID) { ... }
public static MyCustomerDTO Add() { ... }
public static void Delete(int customerID) { ... }
//etc
}

Hope this makes you think lateral and not make you run for the pure object
model without some serious thought

- Michael S
 
Hope this makes you think lateral and not make you run for the pure object
model without some serious thought

- Michael S

Michael, it does indeed provide some serious food for thought. I will
definitely take your advice into consideration going forward. Our
group's scope is smaller in nature and focused (mainly) on automation
of internal business processes rather than company-wide applications
that handle daily business transactions. And due to that, it is our
responsibility to implement an extremely flexible .Net programming
model so that adjustments (enhancements) can be addressed quickly as
our customers' processes change in line with business direction. You
have pointed out a potential corner we may paint ourselves into and
for that, I thank you very much.

Serious thought will be given indeed.
Regards,
Mel
 
Clayton Gulick said:
Michael,

I must respectfully disagree with a few of your points:

I have respectfully read your reply, and take your disagreement seriously.
Great food for thought.
The methodology you are using are most effective if you only ever have to
interop with other .Net code.

I guess here is where my model fall short. If in a mixed blend of platforms
and envirnments, I with you all the way. A business-layer is the only real
way to go.

Typed DataSets work best in a .NET only environment. Guess I was stuck in a
microsoft-mode when I wrote my post, as this is a ms-forum. But if database,
middle-tier and webserver are all microsoft, moving a typed dataset from
middle-tier, via webservices to a webserver and having it hydrate to the
viewstate and all the way back again is made easy with datasets.

I have a fundamental disagreement with the notion of publicly exposing my
"guts" to the world via a web service. In true "classic" OO fashion, I
believe that consumers should only see the data they care about (FirstName,
LastName etc) NOT lnEmployeePKID. I find this to be messy and confusing to
anyone who needs to consume my web service.

Guess here is where we disagree. I have no fundamental opinion on the pure
object model. Also, all sql in stored procedures can have aliases for
fieldnames, hence a lnEmployeePKID could be expressed as EmployeeId.

Anyways, I think both models are good. And if you go for the pure model
there are always tools to help you build classes around a database.
Thanks,
-Clay

Thanks,
- Michael S
 
Michael

I appreciate your insightful response, but here are a couple more points
Typed DataSets work best in a .NET only environment. Guess I was stuck in
microsoft-mode when I wrote my post, as this is a ms-forum. But if database
middle-tier and webserver are all microsoft, moving a typed dataset fro
middle-tier, via webservices to a webserver and having it hydrate to th
viewstate and all the way back again is made easy with datasets

I understand the temptation to use some of the "productivity enhancing" APIs that Microsoft provides both with the Visual Studio IDE and with ADO.NET. I also believe that DataSets and DataTables definately have thier place and can be major time-savers when doing a "View all my orders" type of web page or screen. That being said, I personally dislike typed datasets. Some of my reasons follow

1. If your database schema changes, it means you have to go back and regenerate your dataset. This can, in turn, break alot of code that references that dataset. Also, any custom code or behavior that you may have included in the generated code will be lost when you regenerate. I disagree with relying on a code-generator for business centric classes

2. One of the main advantages of untyped datasets are their incredible flexibility with regards to schema changes. Also the ability to dynamically modify and update the schema (for example adding a temporary column to store volitile data assiciated with a row) is a powerful feature set, and I think you lose alot of that when you go to the strongly typed model (I know that you can still do this with a typed dataset, but it really breaks your development paradigm if you do)

3. You must be very careful when using "out of the box" generated code. For example, some time run a trace log on your SQL Server and look at the actual queries that are executed by the DataAdapter for its default update implementation. It is very ineffecient

Using datasets and datatables can be a great time saver, but IMHO if you are ever doing updates or modifications to core business objects they should be formally modeled (UML is great for that)
Guess here is where we disagree. I have no fundamental opinion on the pur
object model. Also, all sql in stored procedures can have aliases fo
fieldnames, hence a lnEmployeePKID could be expressed as EmployeeId

I'm not sure we disagree as much as we are discussing two different paradigms. From an OO perspective, the classes should be modeled without consideration for how they will be persisted. It is not relevant to the consumer of your class that the Buyer's phone number is going into a phone table, or that the Buyer table is a header/detail relation. All the consumer should have to do is, for exampl

buyer.load(Session("BuyerID")
txtPhoneNum.Text = buyer.PhoneNumbe

o

buyer.PhoneNumber = txtPhoneNum.Tex
buyer.Save(

how and where that buyer is persisted should be completely hidden from the consumer of the class. In the above example, the Buyer could be serialzed out to XML, stored in Access, MySQL, MS Sql Server etc... and it makes absolutely no difference to the calling application. This makes the Buyer class relevant and reusable across the enterprise. In the situation that you describe, the code that you write for the consuming application has no conceptual encapsulation, and the storage details are hard-coded into every application, for example

dim ds as new DataSet(
dim da as new DataAdapter(
dim cmd as new SqlCommand(
dim rows() as DataRo

da.SelectCommand = cm
etc...

rows = ds.Tables("Buyer").Select("lnBuyerID=" & Session("lnBuyerID"

....now nest through your relation (to get to the phone table entry for that buyer

....get the relevant dataro

txtPhoneNum.Text = phoneRow("PhoneNumber").Valu

Even if you used a view of some sort to simplify the above code, you are still locking your consuming application down to a particular storage method and schema, not to mention that every time you want to access the phone number or some other property of a buyer in any other application, you are basically writing all the same code all over again

With a well modeled business object paradigm, you can put all of your core business objects into a shared assembly and reuse all that functionality across your enterprise in any application without any additional work. Then, when you decide to denormalize the Phone table into the Buyer table to decrease an expensive join, you only have to modify your code in one place, the Save() method of the Buyer, and none of your other applications are affected.

In summary, while I appreciate the points you have made, I think that you might find that in the long run it is better to resist the temptation of using auto-generated code and schema specific applications. It will improve the overall quality of your code and drastically decrease your development time.

Thanks,
Clayton Gulick, MCSD

----- Michael S wrote: -----


Clayton Gulick said:

I have respectfully read your reply, and take your disagreement seriously.
Great food for thought.
The methodology you are using are most effective if you only ever have to
interop with other .Net code.

I guess here is where my model fall short. If in a mixed blend of platforms
and envirnments, I with you all the way. A business-layer is the only real
way to go.

Typed DataSets work best in a .NET only environment. Guess I was stuck in a
microsoft-mode when I wrote my post, as this is a ms-forum. But if database,
middle-tier and webserver are all microsoft, moving a typed dataset from
middle-tier, via webservices to a webserver and having it hydrate to the
viewstate and all the way back again is made easy with datasets.

I have a fundamental disagreement with the notion of publicly exposing my
"guts" to the world via a web service. In true "classic" OO fashion, I
believe that consumers should only see the data they care about (FirstName,
LastName etc) NOT lnEmployeePKID. I find this to be messy and confusing to
anyone who needs to consume my web service.

Guess here is where we disagree. I have no fundamental opinion on the pure
object model. Also, all sql in stored procedures can have aliases for
fieldnames, hence a lnEmployeePKID could be expressed as EmployeeId.

Anyways, I think both models are good. And if you go for the pure model
there are always tools to help you build classes around a database.
Thanks,
-Clay

Thanks,
- Michael S
 
Clayton Gulick said:
Michael,

I appreciate your insightful response, but here are a couple more points:

I appreciate our conversation. Issues of great importance are discussed in a
friendly manner.
1. If your database schema changes, it means you have to go back and
regenerate your dataset. This can, in turn, break alot of code that
references that dataset.

No! The typed dataset is a xml-schema. the empleyee-schema is in fact the
employee. Interfaces typically describes behavour, while schema describes
properties and structure. A schema is like any interface, immutable.

You never ever change a interface or schema. This is a fundamental rule in
the facade/schema pattern.

If I realize that my original employee schema was to limited and I want to
change it, my only solution is to create a new schema Employee2 and the same
goes for my Facade, perhaps a webservice. Once exposed I connot simply
change its signature, I would indeed break a lot of code if I did. In the
real world however sometimes you find that you can do changes in exposed
interfaces/schemas if you control all consumers and find it easy to
implement the changes.

But this is also true for the pure object model. You can't simply change a
string into int in your public methods.
Also, any custom code or behavior that you may have included in the
generated code will be lost when you regenerate. I disagree with relying on
a code-generator for business centric classes.

Have a look at Hibernate for Java. This is a mighty tool.
2. One of the main advantages of untyped datasets are their incredible
flexibility with regards to schema changes. Also the ability to dynamically
modify and update the schema (for example adding a temporary column to store
volitile data assiciated with a row) is a powerful feature set, and I think
you lose alot of that when you go to the strongly typed model (I know that
you can still do this with a typed dataset, but it really breaks your
development paradigm if you do).

Yes, I agree. But I can always have both. As all typed datasets is inherited
from the dataset class, I can always upcast.
3. You must be very careful when using "out of the box" generated code.
For example, some time run a trace log on your SQL Server and look at the
actual queries that are executed by the DataAdapter for its default update
implementation. It is very ineffecient.

An issue today, but this will improve in future .NET versions.

However, I agree that in a heavily used, high transactual enterprise
solution, like a banking application or a billing application, my model
simply does not cut it. The performance penalty is too high.

Using datasets and datatables can be a great time saver, but IMHO if you
are ever doing updates or modifications to core business objects they should
be formally modeled (UML is great for that).

Yes, and I think that schemas should be formally modeled as well (UML sucks
at that). I am in no way promoting having a developer playing around with a
database generating datasets at will.

A schema that is used on enterprise level, should be defined on enterprise
level. This goes for the pure model as well.
I'm not sure we disagree as much as we are discussing two different
paradigms.

Indeed. And I like that we argue with both facts and personal preference.
Makes for a dynamic conversation.
From an OO perspective, the classes should be modeled without consideration
for how they will be persisted. It is not relevant to the consumer of your
class that the Buyer's phone number is going into a phone table, or that the
Buyer table is a header/detail relation.

Here I run to daddy for help (*s*) by citing my hero Anders Hejlsberg:

<hejlsberg article_is_from="http://www.artima.com/intv/abstract.html">
The prevailing wisdom five or ten years ago about how distributed systems
would be built in the future was CORBA, IIOP, object request brokers. The
rave at the time was to make the world look like objects, in particular, to
have a bunch of infrastructure that shrouds the fact that objects are
distributed. The nirvana ideal was that you could just say Object obj =
CreateMeAnObject(), and then call obj.ThisMethod(), obj.ThatMethod(), and
you wouldn't know if that object was over in Thailand, right next door, or
in the same process. The problem with that type of programming is: it works
great in a single process; it works quite well across processes; it works
fairly well in a small intranet; but then it completely sucks thereafter.

If you hide the fact that messages go across a network, and don't know when
they go across, you end up with chatty conversations. And all of a sudden,
the speed of light can become a big problem for you. You can't engage in a
conversation with an object out in New York that goes, obj.LetMeGetX(),
obj.LetMeGetY(), obj.LetMeGetZ(). No, you need to say, obj.LetMeGetXYAndZ(),
and have everything come back in one chunk. But you can't really do that
unless you actually make people understand that they are building a
distributed application. In other words, you shouldn't try to pretend that a
remote object is just a local object, because there is a difference. That's
one thing that works so well about web services.
....
It reminds me of the discussion we had earlier about CORBA and attempting to
provide the illusion that an application is not distributed. Well, this is
the same. You may want to have the illusion that the data is not in a
database. You can have that illusion, but it comes at a cost.
</hejlsberg>

While you describe the pure object model, I describe SOA, Service oriented
archtitecture where DTO (schema) is a core medium for transportation of data
in .NET. I can see Microsoft moving to towards this paradigm and we'll see
better and better implementation for this. Indigo is a good example of what
is yet to come.
Even if you used a view of some sort to simplify the above code, you are
still locking your consuming application down to a particular storage method
and schema, not to mention that every time you want to access the phone
number or some other property of a buyer in any other application, you are
basically writing all the same code all over again.

Well, this argument have always been put forward by POO-advocates and sales
people. But really, how many times do you change your database but keep your
application these days? The pure object model sure allow you to just that,
but I have yet to see that happen.

Hehe. But maybe this is because we don't use a pure object model, that hides
the persistance, in the first place. =)
With a well modeled business object paradigm, you can put all of your core
business objects into a shared assembly and reuse all that functionality
across your enterprise in any application without any additional work. Then,
when you decide to denormalize the Phone table into the Buyer table to
decrease an expensive join, you only have to modify your code in one place,
the Save() method of the Buyer, and none of your other applications are
affected.

Exactly the same goes for schema. The schema does not represent the
structure of a database, however mostly populated with data from a database,
but that is orthogonal. Keep all DTOs in one (or a few) assemblies. The
schema is the contract for data. The enterprise owns the contract.
In summary, while I appreciate the points you have made, I think that you
might find that in the long run it is better to resist the temptation of
using auto-generated code and schema specific applications. It will improve
the overall quality of your code and drastically decrease your development
time.

Well, I have the great fortune in working in a shop that typically offer
100% Java or .NET solutions. Our Java-teams mostly use
apache/tomcat/jsp/struts/j2ee/jboss/hibernate/mysql with great success. I
tend (try real hard) to hide from java-projects and work with
IIS/.NET/MSMQ/SQL Server, also with great success. Both the object-oriented
model and the message-driven model are obviously very successful.

Remember the old chinese curse:
- May you live in interesting times...

Best Regards
- Michael S
 
MLecrone said:
Michael, it does indeed provide some serious food for thought. I will
definitely take your advice into consideration going forward.
...
Serious thought will be given indeed.
Regards,
Mel

Mel, if you go for the DTO-model, don't forget that ADO.NET is not (lame)
ADO with a cool name stuck at its end. ADO.NET is an entirely different
beast....

As an example you could write a stored procedure with three selects in them.
Let's say one customer (where on inparameter @customerID), all his orders
and all corresponding orderitems. Simply drag and drop this stored-procedure
onto a dataset and visual studio will create three tables for you. Don't
forget to make it into a typed dateset by selecting 'make type global'.

Tada, you have intellisense on all attributes in your three tables. No more
run-time errors for refering to a field that doesn't exist. Compare using
the compile-time type-safe rs[0].CustomerID with the old run-time
rs("CuustomerID").

Now you can bind relations between order and orderitems in you dataset,
databind this dataset in GUI. Use simple filtering on orders to show correct
orderitems.

This simple example can be created as a demo-prototype in about 15 minutes.

QED - Quite easily done! =)

Compare that to a pure object model appraoch.

- Michael S
 
Clayton, I just thought of something.

In the future, Microsoft will give us 'ObjectSpaces' that, to my knowledge,
will be a toolset and a meta-framework for buildning pure object
business-frameworks.

So there is a future support for the pure object model in .NET even though
you have to do a lot of plumbing by hand in .NET 1.1

- Michael S
 
Back
Top