I know it's important to keep user interface code separated from domain code--the application is easier to understand, maintain, change, and (sometimes) isolate bugs. But here's my mental block ...
Delphi comes with components with methods that do what I want, e.g., a RichText Memo component lets me work with rich text. Other components, like TMS's string grid not only do what I want, but I paid extra for the functionality. These features put the R in RAD.
It seems illogical to write my own classes to do things somebody else has already done for me. It's reinventing the wheel [ever tried working directly with rich text? :-) ] But if I use the functionality built into components like these, then I will end up with lots of intermingled UI and domain code--I'll have a form with most of my code built into its event handlers.
How do you deal with this issue? ... Or, if I want to continue using the code others have already written for me, how would you suggest I deal with the issue?
Separating the UI from Business Logic The concept is simple: divide a computer program into sections that each address a separate and distinct concern of the application. This so-called "concern" can be something as simple as naming a class that is instantiated or as broad as platform specific details (Figure 1).
UI components are sometimes messy. If the business logic is tightly coupled with the UI it is often very hard to write proper tests. The only way to make those components testable is by decoupling UI elements from the business logic.
When separating the business and presentation logic, you need to consider the following: Avoid affinities between the two parts of the application. Be aware of the DPL-restricted API; see Exception conditions for LINK command for details. Be aware of hidden presentation dependencies, such as EIBTRMID usage.
UI logic is how the content is been showing on the screen,(build method), business logic is you provide input to the code returning the output you require. (Methods/classes etc.).
First off, remember that "dealing with rich text" isn't what your app is supposed to do. Your app is supposed to enable the user to perform a certain task, and the code to take care of that task is your domain logic. If part of the task that your program needs to accomplish involves working with rich text, then you can delegate that part of it to a rich text component. The complexity comes, as you mentioned, at the interface between these libraries and domain logic.
The way Delphi domain logic and Delphi UI controls interact with each other is mostly through event handlers. But that doesn't mean that you need to put your domain logic in the event handlers themselves. Instead, try writing units that contain the code for the domain-specific tasks you need to accomplish, and have the event handlers call those units.
In other words, don't write classes to reinvent the wheel and do things others have already done for you. You're right, that would be illogical. But write the application-specific parts that the controls and libraries you use haven't provided as their own separate classes in their own separate units, and connect them through event handlers and public methods or properties on your forms, and you'll end up with decent separation of concerns.
You can create a rather clean separation by using datamodules with clientDataSets to contain your business logic and data objects. You could even take it step further and break the business logic away from the data. Obviously the form contains the UI. Almost every component you use can be data bound which makes it easy to bind them to your clientDataSets.
Just remember Delphi has a way of doing things that don't always fit the best practices that Java or .Net have. Your goal should be to do something that feels right and works for Delphi.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With