Exposing OAC functionality externally

Topics: Mobile Client Software Factory
Dec 29, 2006 at 6:51 AM
originally posted by: dcazzulino

Larry asked the question of how to expose inner controls/behavior of an OAC to its containing form or caller. (See thread at http://www.gotdotnet.com/codegallery/messageboard/thread.aspx?id=5bef2b5f-476a-488c-8d55-9d41666a36f3&mbid=36c8b5e8-2f1d-4955-81d1-a4fd351de974&threadid=b64b609b-a360-4fef-bd82-51489148865d)

One option that is missing in the proposed alternatives to dealing with the issue, and which I believe is the best, architecturally speaking, is that views should not be directly manipulated by anyone other than their presenters. Presenters could talk to other presenters, of course, and they would in turn talk to their view.

In the case he mentions, I imagine something along these lines:

1 - Form is the view of a (say) FormPresenter. After construction (using WorkItem.AddNew<FormPresenter>() maybe), the presenter will receive its view (IForm ?), which implements the interface that the presenter will use to talk to the view.
2 - The controller code (a custom work item probably, or a workitem controller) would then instantiate the second presenter for the OAC view.
3 - The OAC view implements an interface that its presenter uses to talk to its listview (say ICustomerDisplay.SetOrders(IList<Order>) or something like that). The interface between the presenter and the view (ICustomerDisplay, for example) should not expose any windows forms specific types. This makes your presenters reusable when/if it comes time to migrate to WPF. The view, in turn, may expose events for the presenter to listen to, such as selection changed events (ICustomerDisplay.SelectedOrderChanged), but again, only passing UI agnostic event args.

The form presenter may need to talk to the OAC presenter, and that's fine. Maybe it will receive the presenter in the constructor.


Making the views as dummy as possible, and abstracting the interaction with the view through a UI-agnostic interface and a presenter, yields the most benefits in making your application easy to test, therefore making it much more robust and maintainable in the long run.

It may be a bit overkill when you start with just a couple forms, but as things grow, you will find value in the added testability. Your unit tests can make sure the appropriate behavior is implemented by using mock views. And you can have your designers/UEx guys working on the UI independently, while being assured that the behavior backing the UI is well done.
Dec 29, 2006 at 8:43 AM
originally posted by: LarryBB

Whew! That's a pretty complicated answer to what I thought was a relatively simple question!

You are talking about a much higher level of abstraction than anything I've been contemplating. This is also a much higher level of abstraction than I've ever seen recommended for compact framework programming. Can a Pocket PC really process the kind of code you're describing without completely bogging down? Especially if the program in question accesses a relatively large database, meaning that I'm already straining the available memory?

I'm assuming that your answers to the above questions will be "Yes!" Then my next question would be, can you point me to a tutorial or hands-on lab that would demonstrate implementation of the OAC with the architecture you're recommending?
Dec 29, 2006 at 9:28 AM
originally posted by: dcazzulino

Yup, I know how it sounds ;).
However, after you read a couple tutorials on the Model-View-Presenter pattern (or MVP, there are plenty on the web), it will start making more sense.
Of course the impact on the PocketPC is not too high. Accessing any resource is more expensive than a couple lightweight (much more so than any control) classes that are basically a split of the same IL you would have intermixed with UI code in the control anyway.

The smart client factory uses the MVP extensively, but probably the online tutorials will be more abstract/simple to understand.

The RI that comes with the MCSF also uses the MVP pattern, so you can also take a look at that.

You will not regret the move if you do it, believe me ;)
Dec 30, 2006 at 1:16 AM
originally posted by: donelodes

Hi,

I had the same questions and opted to make all the OAC controls public for a simple reason:

I would rather have a Orientation Aware Form, not a Control. As that is not possible, my Form accesses the OAC controls has if they were in the form. This way, all the UI logic is in the Form, and the OAC is just a dumb container for all the Form controls.

Do you really think more abstraction is necessary/worthier?
Dec 30, 2006 at 5:40 AM
originally posted by: dcazzulino

Having all the logic in the form has several disadvantages:

1 - How do you test the functionality?
2 - What happpens when it comes time to port the application to WPF?


Separating the UI logic into a presenter is the best way to tackle both problems. Moreover, the UI can be built by a guy specializing in building UIs, while the logic can be developed independently by a developer knowing about the application logic.

You can avoid having multiple forms pretty easily, creating a ContainerForm<TChildControl>, which upon construction can create a new instance of the TChildControl, and add it to its Controls collection, with Dock.Fill. That's precisely what we did in Clarius OAC (which will ship its first CTP later today)
Dec 30, 2006 at 5:58 AM
originally posted by: donelodes

Sorry, I didn't explained myself correctly.
I'm using the MVP approach so I have a presenter controlling the form. What I mean is that the OAC is only known inside the Form, and it has it's controls public so it's like there just exists the form and I only need one presenter.

The communication between the form and the presenter is done without any reference of UI controls, the presenter updates the view directly (sometimes sending Business Objects that the view knows how to show) and the view sends events to the presenter.
Dec 30, 2006 at 10:02 AM
originally posted by: dcazzulino

I see.
I prefer having the OAC implement the IView interface, and have the controller create a dummy ContainerForm<T>.

But it's a matter of taste, actually ;)
Dec 30, 2006 at 11:12 AM
originally posted by: LarryBB

It's great to get this kind of discussion going -- very helpful to those of us who are new to this.

I'm presently working my way through the discussion and examples at http://www.codeproject.com/useritems/ModelViewPresenter.asp. This seems to be a pretty good discussion of how to use MVP along with user controls. I hope to work up a relatively simple "Hello World" kind of project demonstrating how to use the MVP approach with the OAC. (Sadly, the discussion and examples at the web site quoted above are for asp.net, not for mobile devices, but I think most of the discussion there is applicable to what we're trying to do here.)

I take it that the OrientationAware Demo included with the MCSF does not follow the MVP approach. Correct?
Dec 30, 2006 at 11:19 AM
originally posted by: dcazzulino

Yup, the Demo does not use MVP because there's no logic at all, just controls dragged here and there ;)
Dec 30, 2006 at 10:54 PM
originally posted by: LarryBB

OK, I've built my test MVP project with OAC. I see your point, this is pretty cool. I think my approach is similar to yours, as my OAC implements my IView. I only have a single presenter, though. Not sure yet why I'd use more than one.

I'm not sure how to organize all of this code within a single solution. You've recommended that OACs be included in their own project. If I do that, then it seems that the IView must be included in the project with the OAC (since the OAC must implement the IView), and that the presenter must be included in this same project. The form containing the OAC can be in the main project. This seems to be required by the MCSF, which sets up the main project as dependent on the OAC project. I think this is why Visual Studio won't allow me to include a reference to the main project in the OAC project.

If I'm correct in my assumptions here, then I've got a question how to set up the presenter in a data-driven application. If I understand MVP correctly, then the presenter is the piece that's going to address the data layer of my application. I typically build my own data access classes, which I include in a Data folder in my (single) application project. Now that I have two projects, I would think that the data access classes belong with the main project and not the OAC project. However, if the data classes are in the main project, I think that the presenter will not be able to call them. If I place the data classes in the OAC project, then nearly all of my code will be in the OAC project, which I think would defeat the purpose of having a separate OAC project in the first place (which is to isolate the OACs, making them easier to build?). I guess I could place the data access classes into a THIRD project ...

... or does it make more sense to do this in a single project?

The samples in the MCSF are organized into multiple projects, but along different lines than what I'm describing, so I have not been able to derive any answers from reviewing these samples.

Any thoughts here? Thanks in advance.
Dec 31, 2006 at 3:15 AM
originally posted by: donelodes

dcazzulino:

Just one question, if you have only one dummy Form, how do you manage main menus? Do you always add them at run time and never in design time?
Jan 1, 2007 at 9:30 AM
originally posted by: dcazzulino

My take on this:

1 - Use one project for the DAL
2 - Use one project for each module that contains: views, view interfaces, presenters, and other assets to fullfill the use case.
3 - Use binary references to anything in MCSF

The projects 2) should not have any dependencies on the Shell or main project. Ditto the other way around. If there's any kind of common communication that needs to happen between them, use a third project "Common" where you place service interfaces, constants for UI elements and extensions, etc.

3) is tricky. In the guidance package, I copied all MCSF projects (except for the OAC, so that the output assembly/designer does not have to be recompiled, which would fail as it would already be locket by VS) mainly because there's a common scenario where customers modify p&p blocks.

On second thought, though, I think that typically happens once per company, and the modified source is kept in a central, not per-project location, and basically all projects reference the output of these sources from some Lib folder. It was not clear to me how to implement such a real-world scenario just using GAX, so I opted for bringing in the sources. Not sure if it was the best idea, though.
Jan 1, 2007 at 9:33 AM
originally posted by: dcazzulino

Don, very good question!

I'd say you should typically rely on CAB extensibility for UI elements including menus. Hence, you only have one main menu that changes over time. Don't know if a new form hides the main menu of its parent. In that case, I guess you could assign the parent form main menu as the new one's. Would that work?

Building the menus at run time is the way the current CAB favors, yes.