Page 17 - MSDN Magazine, June 2019
P. 17

Once again, NOF uses naming conventions to provide this kind of functionality. By providing a method that begins with the name “Disable” and continues with the name of the action you want to disable (in this case “Delete”), you can do that check long before the user ever selects it:
public string DisableDelete() {
if (Talks.Count > 0) {
return "Speakers cannot be deleted until their Talks are removed."; }
“ContributedAction” attribute on it, the NOF UI takes that to mean that this action should appear on the domain object’s menu. Imagine for a moment that you want the code to notify Speakers that their talk was accepted at the conference to be outside the Speaker object. (This makes sense, actually, from a domain model- ing perspective, because notifying a Speaker has really nothing to do with being a Speaker.) You create a service, then, that looks some- thing like this (taking care to make sure it’s registered with NOF in the Services property of the NakedObjectsRunSettings class, as well):
return null; }{
Notice that DisableDelete returns a string, which will either be null if the action is fine to execute, or will be displayed to the user. (By default, the menu item for the action will be disabled, so it won’t be selectable by the user, but remember that actions can be invoked in other ways.)
What if you want to hide the action from the user entirely? That’s a different question, but NOF uses the same approach—a HideDelete method—to indicate whether the action should be displayed. The choice between hidden and disabled is obviously a subtle one, and probably a UX debate that others are more qual- ified to have than I; suffice it to say, choose as your UX designer or your heart takes you.
NOF is committed to the principle that the UI should be built from the structure of the code itself.
Action Parameters
Keep in mind that, in many cases, the action will require additional data before it can be carried out. An action may want to find all Speakers who have Talks that contain a particular search term, such as “Blockchain” or “IoT” (hopefully to remove them entirely from the system), which means the user has to have an oppor- tunity to type in that search term. Again, NOF is committed to the principle that the UI should be built from the structure of the code itself, which means in this case that the UI will examine the parameters of the method and present a UI element that provides the user the chance to put the necessary input in place. You’ve seen this mechanism at work already, in that the FindSpeakerByLast- Name method of the SpeakerRepository does the same thing: accepts a string parameter for the last name for which to search, which NOF interprets to mean it needs to display a textbox after that action is invoked.
Naked Contributions
Recall from the earlier article I mentioned that the Naked Objects world consists of both domain objects and services, where ser- vices are collections of behavior that don’t necessarily belong on the domain object. Essentially, if a method on a service takes a domain object as one of its parameters, and that parameter has a msdnmagazine.com
public class NotificationService
public IDomainObjectContainer Container { set; protected get; }
public void AcceptTalk([ContributedAction] Talk talk) {
Container.InformUser("Great! The Speaker will be emailed right now");
}
The implementation of the notification, of course, will take more than just showing a message to the user, but that’s not the important part—the key here is the ContributedAction attribute on the Talk parameter, which will cause this action to appear in the Talk list of actions. This provides a great deal of flexibility regarding where code appears in the system, compared to where it appears in the UI.
Note that it’s possible to contribute actions to groups of domain objects, as well, using the same kind of convention, only applying it to a parameter that’s a collection of domain objects rather than a single one. For example, if I want to send notifications to a col- lection of Speakers, I can do so from a given method, like this:
public void NotifySpeakers([ContributedAction] IQueryable<Speaker> speakers)
{
foreach (Speaker s in speakers) {
// Send SMS or email or whatever }
}
From a UI perspective, any collection of Speakers will now have a checkbox appear in front of each one (allowing the user to select which of the Speakers will appear in the collection), and the “Actions” menu presented in the table will have the “Notify Speakers” action displayed. As with all actions, if additional input from the user is required (such as the message to send each Speaker), this will appear as part of the UI before the method is executed.
Wrapping Up
Actions represent an important aspect of the Naked Objects Framework experience, in that they’re where the vast majority of the “business rules” of any application will sit. Services can pro- vide opportunities to host business logic, to be sure, but it’s inside actions on a domain object that domain-driven developers will find the best opportunities to provide the code to “do the work.”
Happy coding! n
Ted Neward is a Seattle-based polytechnology consultant, speaker and mentor. He’s written a ton of articles, authored and co-authored a dozen books, and speaks all over the world. Reach him at ted@tedneward.com or read his blog at blogs.tedneward.com.
ThaNks to the following technical expert for reviewing this article: Richard Pawson
June 2019 13
}


































































































   15   16   17   18   19