CAB Best Practice Questions

Topics: CAB & Smart Client Software Factory
Apr 19, 2006 at 9:31 AM
originally posted by: rmtuckerphx

In an effort to better understand the CAB guidance as contained in SC-BAT, I have summarized my understanding in the form of a quiz with the answers that I think are correct. I am interested in what others think the correct answers are and why.

1. The View should only know about the Presenter. True
2. The Presenter knows about the View interface, Services needed, any ServiceAgents, and the WorkItem. True
3. To make the Presenter testable, the Services, ServiceAgents, and WorkItem should be passed in the constructor attributed as a ServiceDependency. True
4. The WorkItem knows about any Services and Views. True
5. If you want to be able to use multiple Presenters with a given view, define an interface for the Presenter. True
6. If the WorkItem is acting as an Application Controller and the Presenter has an interface, the WorkItem would assign the Presenter to the View and the View to the Presenter. True
7. Data passed back and forth between the View and the Presenter should be primitive .NET types or Business Entities. This constitutes the Model. True
8. The Presenter knows nothing about controls used on the View. True
9. EventPublications and EventSubscriptions should be found only in a Presenter or the Shell Form. True
10. A CommandHandler should be found only in a Presenter or the Shell Form. True
11. A Service does not need to be attributed with the Service attribute, but if it is then it will loaded into the WorkItem at Module load time. True
12. A Module can contain multiple WorkItems. If that is the case, then create a new WorkItem that inherits from WorkItemController, add it to an existing WorkItem and call its Run method. The ModuleController can be kept if there are Services or UIExtensions that you want to add when the Module is loaded. True
13. The only communication between a Presenter/Controller and the Shell should be done through UIExtensions and Commands on a WorkItem or using EventPublication/Subscription. True
14. A class attributed with the Service attribute should never communicate with the database or a SOA service. True
Apr 19, 2006 at 10:38 AM
originally posted by: austinlamb

I'm not sure why you have #14? I'd think a CAB Service would be free to do whatever it does - if that happens to be database work, or something on the file system, calling a web service...that's realy irrelevant.

The CAB Service performs some function, other things depend on it via ServiceDependency but the workings of that service aren't important to anyone but the service itself.

That'd be how I'd see it - perhaps you can elaborate more on why you think it should avoid databases and SOA services?
Apr 19, 2006 at 11:01 AM
originally posted by: rmtuckerphx

From the CAB documentation under "Getting References to Services"

<quote>
Note:
In the Composite UI Application Block, the term service describes a component that implements some infrastructure-related functionality that other components in the application may need to use; for example, services providing authorization, logging, or hardware communication functionality. It does not mean a Web service.

Composite UI Application Block applications can use Web services, but the service patterns are not suited for use as business services implemented as Web services or Web service proxies. You can create your Web service proxies within your WorkItem and use them just as you would in any other application.

</quote>

It is my understanding that the ServiceAgent pattern should be used for Web/SOA Services.
Apr 19, 2006 at 11:09 AM
originally posted by: austinlamb

I see your point, but it seems to make sense to me that a ServiceAgent could just as easily be a CAB Service (I'm just using the [] to denote CAB-usage of the term Service to avoid ambiguity).

That way the ServiceAgent can be injected into the WorkItem or Presenter or whatever needs it - the fact that it's using a Web Service seems irrelevant, though obviously the Agent should be designed Asynchronously if possible to keep the UI responsive.

Is there some downside you can see to treating a ServiceAgent just like any other CAB Service?
Apr 19, 2006 at 11:34 AM
originally posted by: rmtuckerphx

I think that using a ServiceDependency with a ServiceAgent is OK. I don't think using a ServiceDependency with a Web Service Proxy is OK.

The AppraisalWorkbench indicates that as an acceptable pattern:

MyAppraisalsViewPresenter:

private IAppraisalManagementServiceAgent _appraisalService;
private WorkItem _workItem;

InjectionConstructor
public MyAppraisalsViewPresenter
(
ServiceDependency WorkItem workItem,
ServiceDependency IAppraisalManagementServiceAgent appraisalService
)
{
_workItem = workItem;
_appraisalService = appraisalService;
}

And in the ModuleController;

AppraisalManagementServiceAgent agent = WorkItem.Services.AddNew&ltAppraisalManagementServiceAgent, IAppraisalManagementServiceAgent&gt();

The AppraisalManagementServiceAgent class could have been decorated with the Service attribute instead in which case the ServiceAgent would have been added to the root WorkItem as part of the Module processing.

From an answer to another post;

"Service" in the CAB context doesn't mean "web service". It means a class which is meant to be found by type to be used to provide some functionality for other code.
Apr 19, 2006 at 12:20 PM
originally posted by: austinlamb

I agree - having ServiceDependency on a ServiceAgent (or its interface, if you go the interface route, which I would for testability) makes good sense, and is backed up by the AppraisalWorkbench reference implementation.

Likewise, I agre that having a ServiceDependency on a Service Proxy probably is a bad thing - the ServiceAgent serves a purpose after all, and bypassing it to the proxy like that from a CAB Presenter (or whatever is having the dependency injected) doesn't make sense.

So, perhaps I was just misreading your point #14 above? When you say it should never communicate with a web service, do you mean it should never directly communicate with a web service, but indirect communication (via Service Proxy) is ok? Because I can agree with that, otherwise I still don't understand your point #14 above.
Apr 21, 2006 at 7:10 PM
originally posted by: JohnAskew

#12 seems like a two part FAQ item:

12a. A Module can contain multiple WorkItems. If that is the case, then create a new WorkItem that inherits from WorkItemController, add it to an existing WorkItem and call its Run method. True

12b. The ModuleController can be kept if there are Services or UIExtensions that you want to add when the Module is loaded. True

I don't understand why these two parts are both on item 12. What am I missing?

*Is it just that the new WorkItem would be a peer to the ModuleController and, perhaps, marginalize reason to have a ModuleController? I think I understand.
Apr 22, 2006 at 6:49 AM
originally posted by: rmtuckerphx

Keep the comments coming!

Here is an update that incorporates the comments to date:

1. The View should only know about the Presenter. True
2. The Presenter knows about the View interface, Services needed, any ServiceAgents, and the WorkItem. True
3. To make the Presenter testable, the Services, ServiceAgents, and WorkItem should be passed in the constructor attributed as a ServiceDependency. True
4. The WorkItem knows about any Services and Views. True
5. If you want to be able to use multiple Presenters with a given view, define an interface for the Presenter. True
6. If the WorkItem is acting as an Application Controller and the Presenter has an interface, the WorkItem would assign the Presenter to the View and the View to the Presenter. True
7. Data passed back and forth between the View and the Presenter should be primitive .NET types or Business Entities. This constitutes the Model. True
8. The Presenter knows nothing about controls used on the View. True
9. EventPublications and EventSubscriptions should be found only in a Presenter, WorkItemController or the Shell Form. True
10. A CommandHandler should be found only in a Presenter, WorkItemController or the Shell Form. True
11. A Service does not need to be attributed with the Service attribute, but if it is then it will loaded into the root WorkItem at Module load time. True
12a. A Module can contain multiple WorkItems. If that is the case, then create a new WorkItem that inherits from WorkItemController, add it to an existing WorkItem and call its Run method. True
12b. The ModuleController can be kept if there are Services or UIExtensions that you want to add when the Module is loaded. True
13. The only communication between a Presenter/Controller and the Shell should be done through UIExtensions and Commands on a WorkItem or using EventPublication/Subscription. True
14a. A class attributed with the Service attribute should never communicate directly with a web service. True
14b. A class attributed with the Service attribute can communicate with a Service Proxy. True
14c. A class attributed with the Service attribute can communicate directly with a database, but be careful that your Smart Client doesn't turn into client/server. True
15. The Smart Client Software Factory is pushing WorkItem more as a container than an Application Controller. It is preferred to use a class that inherits from WorkItemController than to extend the WorkItem class. True
May 4, 2006 at 10:08 AM
originally posted by: sklett

"9. EventPublications and EventSubscriptions should be found only in a Presenter, WorkItemController or the Shell Form. True
10. A CommandHandler should be found only in a Presenter, WorkItemController or the Shell Form. True "

I'm sure this is obvious to many of you, but why is it that #9 & #10 are true?
Would it be wrong to have my service publish events? If my service get's fresh data from a WS or DB directly, why would I not want to publish that event?

I'm not saying they SHOULDN'T be true, I just don't understand why they are.
May 4, 2006 at 10:22 AM
originally posted by: austinlamb

Actually, I agree with sklett to some extent - Event publications, at the very least (maybe subscriptions too - I'd have to think more) could just as easily be valid from a service. I'm not sure about commands - those feel more UI-ish to me, with events being more generic and about "things going on" - which happens in services too. But perhaps someone can make the case for Commands going into services - I just don't see it now.

For example, I currently have my ServiceAgent hold a cache of some things, but when that cache gets dirty, it fires an event indicating it is dirty, so anyone that was using the values from the cache can re-query the service for newer data. It's working wonderfully, and doesn't seem to have any architectural incompatability with CAB or SCSF.
May 8, 2006 at 8:30 PM
originally posted by: askew

Should it read the corollary?
9. EventPublications and EventSubscriptions should not be found in a View. True.
10. A CommandHandler should not be found in a View. True.

Basically stating that Views are aggregate ui components for the Presenters, et al?

Or would the service be considered embedded within it's consumers (Controllers/Presenters/Shell), and 9 & 10 remain unchanged?