Situation:
VB.NET WinForms application, using the WinForms as a presentation layer project. Another class library project containing the business layer, in the form of CQS and Service classes, plus a data access layer.
Summary:
I'm attempting to follow CQS for new features being added to the legacy application. Consider a product return log... I have a class for the Update Command, a class for the Create Command, and a class with two Query functions. The ProductReturnsService
class contains the Public functions for the Windows Form to call Create, Update, ReadX, ReadY, etc. This class also contains private functions to validate the Update and Create commands.
Dilemma:
When updating an item on the product return log, I need the UI to disable several controls based on the current or changed data for the item being updated. For example, I have a CheckBox
called "Completed", which will "close" that product return record and lock out changes to all the other fields. However, this CheckBox
shouldn't be enabled unless, for example, Date Received has a value. The "Completed" CheckBox
also shouldn't be enabled if the current user isn't a member of a certain security group in the system - even though that current user can enter data.
Question:
In OOP, it is my understanding that things like, "Can't check Completed until Receive Date has a value." and "Can't check Completed if not in the Manager role." are business rules. And it is my understanding that business rules belong in the business layer.
How do I expose those business rules to the UI, so that users aren't frustrated with returned validation error messages from the BL? How can I have the UI enable/disable controls according to the business rules in the BL? I also understand that following DRY, I wouldn't want to recode all the business rules in the Windows Form code page.
I can't wrap my head around how to implement one set of business rules that the BL acts on, as well as the UI. Currently, my BL validation is in the ProductReturnsService
class, with one function to validate a Create Command, and another function to validate an Update Command, which I think makes sense because these validation functions are validating the data before it goes to the database. I would prefer the same kind of validation "in real time", interactively, on the UI.