Further separation of Data & UI Logic

This forum is for programmers who have questions about the source code.
Post Reply
User avatar
jordansparks
Site Admin
Posts: 5744
Joined: Sun Jun 17, 2007 3:59 pm
Location: Salem, Oregon
Contact:

Further separation of Data & UI Logic

Post by jordansparks » Sun Jun 17, 2007 8:22 pm

Hi,

I've been, rather for the first time, having a deeper look at the architecture of Open Dental. One thing I'd like to propose is a further separation of the Data & UI Logic.

The goal would somewhat be to end up with one DLL (OpenDentBusiness) that only contains the data logic (eg no references to System.Windows.Forms, Topaz, or whatever) and another DLL that only contains the UI logic (eg no references to System.Data.*).

The first thing that comes to mind is moving OpenDental/Bridges and OpenDental/Data Interface to OpenDentBusiness.

The second is that OpenDental as it is currently written, does a great job of separating the Data and the UI, but doesn't really separate the "business rules" and the UI. I'd like to try to move these business rules into the OpenDentBusiness tier.
Basically, the UI should just be a thin wrapper around the business tier.

Now, what's the use for this? By putting all business rules into a sperate DLL, the "core" of Open Dental would be Windows Forms independent. That is, it would be rather easy to write any kind of front-end to Open Dental. Think of a GTK-application, but you could as well think of a small web interface (whatever the use may be).

As you know, this is not a "minor" modification. I'm experimenting with this on my own SVN server right now (obviously this can't be done on the trunk). I have a lot to learn about Open Dental to pull this of. On the other hand, I don't necessarily want to this "in the dark", so if you want to keep track of my experimental work, you can give me a svn branch and I'll work from there.

What do you think? Do you see any benifit in this separation of Data/Business rules/UI Logic?

Frederik
That's been the whole idea behind having OpenDentBusiness.dll. We are working constantantly in that direction. Please understand that I consider discussions of general architecture to be of very high importance. So, yes, I am certainly interested. Now about your specific ideas:

OpenDentBusiness certainly should have no references to System.Windows.Forms. It should work equally well for any chosen UI. But I have been trying to use C# DataSets as the UI information storage container. So references to System.Data will certainly be required in the UI because all data coming from the business layer will be in the form of System.Data.DataSets. What could possibly be wrong with this? It is a very logical and reasonable choice of temporary UI data storage. Of course, something else could be used by another UI without any problem.

I've tried a number of times to put all business logic in the business layer, but it slows me down. So I've only done it for situations where the payoff was worth it, like the main modules. You'll notice that significant effor was recently put into moving most Appointment module business logic as relates to queries and data retrieval into the business layer. We are setting the stage for building something like an ASP UI (or some other UI if it makes more sense).

But for smaller forms, it's faster just to crank out the functionality than it is to tediously create the middle tier. It's a matter of being pragmatic. If it just takes one simple query to get the data for a form, then it really doesn't matter if it's in the business layer or the UI. So I consider the issue of data retrieval to be largly solved (I think). The most recent incarnation of this strategy can be seen at OpenDentBusiness.Business.GeneralB.GetDS(), replacing the previous generation at OpenDentServer.BusinessLayer.cs. The difference between the two is that the older generation used a different DTO (data transfer object) for each different command, while the newest generation uses one DTO for all commands.

The issue that I continue to struggle with is data alteration. We need one command for each user action that would alter data in the database. But it's hard. That's a lot of commands. And we don't want to waste very much time converting the current command structure to the new one. Keep in mind that this sort of command requires passing a lot of data to the business layer. Over 60 fields if inserting a patient. It would be unwise to have a command with 60 parameters, so a Patient object needs to be passed. But it can't be a real patient object, because other UIs might not know how to create a C# patient object. So it needs a layer of abstraction, probably in the form of named fields representing an object. And there should be one DTO which passes all such objects so as to avoid writing a lot of framework code. I don't want to have to write the code for a new DTO object for every new command.

One last detail which is needed is that we need to be using a true web service rather than the current raw socket. I consider that a totally separate issue from all the above discussion regarding what the XML structures should look like.

fcarlier
Posts: 75
Joined: Tue Jun 19, 2007 3:12 am
Location: Ghent, Belgium

Why use DataSets when you have Strongly Typed objects?

Post by fcarlier » Tue Jun 19, 2007 3:23 am

There is something that I don't understand, though: why use DataSets when you have strongly typed objects?

OpenDentalBusiness contains a class for each and every table. That means that you can have strongly typed objects in the entire Open Dental application. That's great. The User Interface can then consume these objects, but it doesn't need to know about the database itself.

Why do you, later on, try to pass DataSets to the user interface? If you just pass, for example, a Patient object to the UI, the UI can later on pass that very same Patient object back to OpenDentBusiness which can store the object.

So, why are you not using these objects as your DTO?

User avatar
jordansparks
Site Admin
Posts: 5744
Joined: Sun Jun 17, 2007 3:59 pm
Location: Salem, Oregon
Contact:

Post by jordansparks » Tue Jun 19, 2007 8:34 am

Yes, what you suggest works fine for almost all of the simpler smaller forms in the entire program. But it does not work well for the main pages of the main modules. It is much better in those complex windows to get back from the business layer one or a few simple tables which can just be tossed onto the screen. All of the business logic has already been performed. All the colors, translations, currency, and date issues have already been taken care of. Data from dozens of database tables is already elegantly layed out in a meaningful way. The UI can just lazily plop the grid onto the screen. It is a very powerful technique which will make moving to a web interface very painless. At least for the main modules. I also did it in the Appointment Edit window because of the complexity.

But for all other forms, I entirely agree that strongly typed objects are the way to go. For example, the Patient Edit window.

Now, let's talk about making changes to the database. In the Appointments module, for example, if a change needs to be made to an appointment, one way would be to use the AptNum to grab the appointment, make the change, and pass it back to the business layer. Another way would be to create a specific method to handle specific field changes, such as changing the length of the appointment. In that specific method, all validation logic would be performed. That method would be responsible for ensuring that appointments didn't overlap, for example. So it seems more rigorous and tight in some situations to create the specific methods we need rather than just allowing the UI to just make any changes it wishes to the objects and expecting the business layer to pass all those changes on to the database.

As for the choice of DTOs other than the datasets for the main modules, yes I agree that a Patient object, for example, would be a fine DTO. But I'm not sure how to implement that in a generic way.
Jordan Sparks, DMD
http://www.opendental.com

Post Reply