Who's responsible for creating an object?

Who's responsible for creating an object?

Old forum URL: forums.lhotka.net/forums/t/1270.aspx


Michael Hildner posted on Tuesday, September 19, 2006

Hi,

I've heard from a couple sources, including one of Rocky's DNR TV clips, that a form shouldn't be responsible for creating the object it's interacting with. I guess that makes sense to me, but then who should create the new object?

In my Windows Forms app, the user needs to click a button in the MainForm, which then brings up the AddSlotMachineForm. This is for creating a new SlotMachineEditableRoot. If the AddSlotMachineForm shouldn't create the new object, should the MainForm create it? Or some other object?

Thanks,

Mike

 

ajj3085 replied on Tuesday, September 19, 2006

The code which is opening the form should create it.  That way, the editing form is greatly simplified and can be more easily reused.

Michael Hildner replied on Tuesday, September 19, 2006

Thanks Andy, makes perfect sense.

This is somewhat related. I know the business object should be responsible for setting default values if need be. Does this also apply for other values, such as CreatedBy or ModifiedBy?

My CreatedBy and ModifiedBy are Guids or ints in my Identity class (ReadOnlyBase, IIdentity), which of course is part of the business object assembly. I'm not sure if these should be set in the business object layer or the UI.

Any thoughts?

Thanks,

Mike

malloc1024 replied on Tuesday, September 19, 2006

The form class should know as little about the outside world as possible.  Ideally, you should only pass it the minimum amount it needs to know to do its job.  If the form class is responsible for creating an object it becomes dependent on that objects creation.  However, creating the object in another form and passing it just pushes the creation onto another form.  If you truly want to decouple object creation from your forms you would use a factory.  Unless you know you are going to reuses your forms, this may be overkill.  When using CSLA, you may need to pass the root object to a form to save it.  This form becomes dependent on the root object, reducing the forms usability.  Therefore, the amount of work you put into making your form reusable might be for not.  There are ways to deal with this but it ends up costing more time.  You will need to weight the benefits of reusability vs. time.  The more you try to decouple your classes, the more time you will spend on design.  If you go overboard, you will waste your time.

Michael Hildner replied on Tuesday, September 19, 2006

malloc1024:
However, creating the object in another form and passing it just pushes the creation onto another form. 

That's exactly what I was thinking. Although it seems to make sense, or more sense, to have a form that contains a menu create or retrieve the object, and pass that object to the edit form, rather than have the edit form decide if it needs to create or retrieve an object to edit.

Maybe I don't quite get what you're saying with the form being dependant on the root object, but that seems just fine to me. I mean the form is designed around the object to edit, not to edit different types of objects - at least my forms are. I'm pretty happy reusing my form for both creating and modifying, and just not have the edit form have to decide if the object is new or existing.

Thanks,

Mike

ajj3085 replied on Wednesday, September 20, 2006

You can only decouple to a certain point.  At some point, something somewhere needs to create something.... unless you want to introduce Spring.Net into your architechture... but that's more trouble that its worth IMO.  Where to create the object isn't decoupling anyway.  The edit form is still heavily dependant on the BO, which it necessarly must be.

At any rate putting the object creation in the calling form is a better idea because it should be the one responsible for maintaning the life time of the BO object.  Just because the editing form is closed doesn't mean you are necessarly done with the BO.  Having the edit form creating the object means that the form must destroy the object when the form is closing (well, you can get around that, but then you have a weird situration were the edit form creates the object, the user closes the form, and then the BO continues being managed by the opening form anyway...


malloc1024 replied on Wednesday, September 20, 2006

The point I was trying to make is that the edit form is so dependent on the object that creating the object elsewhere to improve the forms reusability doesn’t make much sense.


Yes, when you create an object, you are coupling the implementation of that object to the class that created it.  Factories are used to decouple object creation.  Some believe that all object creation should be done through factories; however, I am not one of those. 


I agree with you that it is better to create the object somewhere other than the form that uses it.  That is what I typically do.  It just makes more sense for me to do it that way.  However, I never really thought about why this is preferred.  Your last answer makes it more clear on why this is preferred; however, if you create an object inside a form and close the form, the garbage collection doesn’t destroy the object until all references of it are gone.  I believe this is how it works; however I may be wrong.

ajj3085 replied on Wednesday, September 20, 2006

Maybe reusablity wasn't the word to use... it makes the edit for simpler because you just need one contstructor which takes the object to edit. 

malloc1024:
Yes, when you create an object, you are coupling the implementation of that object to the class that created it.  Factories are used to decouple object creation.  Some believe that all object creation should be done through factories; however, I am not one of those.


Isn't class-in-charge a factory pattern? Wink [;)]

malloc1024:
Your last answer makes it more clear on why this is preferred; however, if you create an object inside a form and close the form, the garbage collection doesn’t destroy the object until all references of it are gone.  I believe this is how it works; however I may be wrong.


Sorry, I wasn't clear.. Yes, the GC won't collect the object.  I meant something like this would be 'odd,' at least to me..

private void Button_Click( object sender, EventArgs e ) {
    EditFrm frm;
    MyBO bo;

    frm = new EditFrm();

   frm.ShowDialog();

   bo = frm.TheBO;

   // Do stuff with BO
}

SonOfPirate replied on Wednesday, September 20, 2006

A couple of quick points, if I may...

If you look at most of the components in the FCL, web and win, you'll see the DataSource property is prevalent.  This is a great example of what Andy has been describing in that all of these controls and components are designed to perform a function and really don't care what the underlying object is.  As long as the object you set as the DataSource has the requisite interface or is of the requisite type, than the form/control can do its thing.  This would be the goal of a solid multi-tiered design where UI and BO are clearly delineated.

The other point I wanted to make was to take a look at the Automation Model for another example of how the UI can be separated from the business logic and how the BO layer drives the interface instead of the other way around.

I think the common misperception, or the common thought process, that we all have had to overcome or are working on stems from the fact that in the days of yore, in event-driven applications, the user-interface was perceived as being the driving force behind the application.  Linking forms together via button clicks, etc. was how the application was glued together.  In fact, I can remember working with some development tools that actually had buttons with OpenForm('x') as the default action (MS-Access comes to mind as one of 'em).  Because it is what we see and our minds naturally gravitate to the thought that "if I click this, then a form will open", we seem to want to continue the UI-centric approach.

However, if you can switch gears and think from a service point-of-view - you know, those UI-less apps running on your system that you can see when you open the Task Manager?  Without a UI, what's driving those?

See the segue coming to SOA?

If you look at your application as an in-memory process (service) that is performing functions and may be presenting an interface to your user, it starts becoming easier to create this separation.  That's why I bring up the Automation Model because the UI that you see is generated by the application's code based on whatever logic and data and rules you have programmed.  The UI events simply provide hooks into the underlying functionality with event-handlers to respond to changes from the business objects.  The result is very lean UI code concerned only with displaying the information and routing the user's actions back to the underlying service layer (business objects).

I believe this is what Andy was describing, as well as Rocky et al.  The power of this approach is tremendous as you venture into multiple interface apps such as web, win and mobile.  All you are doing is putting a different face on the same application.

Hope that helps.

DansDreams replied on Wednesday, September 20, 2006

Son (can I call you son? - LOL),

I don't think I agree with your thought-provoking perspective if I'm understanding you correctly.  That's because I perceive some contradictory thoughts in there.  It's probably my misunderstanding, so if you clarify...

I agree with your first couple of paragraphs, but I part company when you start talking about the business layer driving the UI.

The point of n-tier, and even moreso SOA, is that the business layer will know absolutely nothing about what the UI is. I think it's a mistake right out of the gate to think in terms of  how the BO will "drive" the UI except for what's absolutely required to support things like DataBinding.

Maybe you really meant the same thing as what I will describe, but I would suggest it's better to think of the business layer (BL) independent of anything else.  Its essence is a set of behaviors and supporting data to fulfill and implement the business rules, nothing more.  That's why n-tier is such a powerful design - you can swap out UI without really changing the essence of the application from the perspective of the business.

A particular UI that you've wrapped over that BL is what it is.  The notion that one form is related to another form is a UI concept.  You may indeed represent in the BOs or in BL metadata that objects are related to each other and that may be beneficial, but it shouldn't be done with any particular UI implications in mind.

What I mean is that IMO of course the determination that a button opens such-and-such a form will be coded at the UI level... the idea that a form should contain a button because the BO says so and then ask the BO what should happen when it's clicked is a dangerous path.  There is some power there if implemented very cautiously, but be careful going down that road.  For example, it may provide some interesting context-sensitive UI features to know that the Customer BO is related to the OrderList BO by passing the CustomerID to the GetOrderList(int customerID) method, but that should be represented in a way as decoupled as possible from any specific UI implications.

SonOfPirate replied on Friday, September 22, 2006

Yea, I guess I did mis-speak a little and give the wrong impression of what I was trying to describe.  It was along day...

Anyway, what I was describing was not to empower the BO's with UI information.  Instead, you would actually have another layer in between.  And, I agree with your logic that this would be a part of the Presentation Layer albeit not responsible for the UI directly.  I was referring mostly to the Model-View-Controller design pattern.  Here's a link to a pretty good article about how this can be used in your apps: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/automationmodel.asp  You'll see in the sample code that you really end up with two assemblies for your Presentation Layer, one for the UI (View) and the other for the automation (Controller) - your BO's are the model.

When the app is started, an instance of the (controller) Application class is created which spawns the creation of the (controller) MenuCollection object.  But population of the collection is handled by the ctlTop UI element and, in this case is hard coded but could be the result of data-binding to a BO.

However, that doesn't exactly address your question.  And, I don't know if the example will help you or confuse matters.  But...

As you said, it is key that your BO's remain unaware of anything to do with the UI.  At the same time, it would be nice to have a unified way of creating a UI independant of what technology is used (this is what I was getting at before).  If you look at the example, there is a disconnect between the UI elements (View) and the automation-model (Controller) that would allow you to just as easily put a web interface on the application.  All you would have to do is replace the Windows Forms controls with Web Form controls.  The same collection of menu items, etc. could be generated, then your UI would simply use the appropriate control for rendering the items in the interface.

Of course to do this efficiently, I would suggest one change from the way the sample does things.  I don't like the fact that the UI components, such as ctlTop, populate the Controller collections.  This is done because these are hard-coded into the UI probably through a designer.  And this is fine and dandy if your content is not to be dynamic.

So, let's say you have a tree-view with the root node "Projects" and you want to populate it with child nodes corresponding to a collection of business objects.  Your UI component, let's call it MyApp.Windows.Controls.ProjectExplorer would be created by your main form and would call the MyApp.Application.Projects static property to obtain the current MyApp.ProjectCollection object then iterates over the collection, creating a new node for each.

At this point, your UI component, ProjectExplorer, is independant of the collection used to create it's items.  And, the component could be a Windows Forms control, Web Forms control, Mobile control, etc.

Unlike the sample app, I believe that the MyApp.ProjectCollection class should be responsible to "connecting" to the business layer.  So, internal to that class, you would instantiate your BO, MyApp.Data.ProjectCollection, which contains your MyApp.Data.Project BO's.  The MyApp.ProjectCollection wraps your BO's for use by the UI.  Now, how you instantiate the BO is up to you whether it is direct using new (New in VB), a static NewProjectCollection method or a data factory - it's up to you.

The argument could be made that you don't really need the MyApp.ProjectCollection and MyApp.Project classes sitting in between the UI and BO's, that it just clutters everything up.  But remember, these classes add UI "hooks" to the underlying BO that the BO isn't supposed to have (because we don't want it to know anything about the UI).  So, for instance, your MyApp.Project class may expose an OnShow event that is handled by the MyApp.ProjectCollection which, in turn, raises an OnItemShow event that is then handled by the UI elements to refresh the interface based on the command.  From the ProjectExplorer UI element, when a tree-view node is double-clicked, the control handles the event and calls Project.Show() which raises the OnShow event...

I hope that gives you a better understanding of what I was trying to explain.  I know it may sound like overkill and I will take no offense to you ripping it to shreds, but I like this approach because of the flexibility it gives you by adding that middle layer of abstraction between your UI elements and BO's which allows you to switch 'faces' on your app quickly and easily.  Plus, you have the added benefits as explained in the article by having an automation-model should that be of interest (which it is to us).

One thing not mentioned in the article that is available with this approach comes when developing Smart Client applications.  Imagine if your BO's were only available to your app via a web service interface.  Your automation-model classes (controllers) would be able to isolate this from your UI as it is their responsibility to interface with the business layer whether it is direct or through a service interface.  Nice flexibility.

Hope that helps.

Patrick replied on Tuesday, December 12, 2006

Hi SonOfPirate,

what you are describing sounds very interesting and I would like to use it for a new application I am building (including the automation part).
If you have any more tips on using Omar's automation model in a CSLA.NET application or even a prototype you might have built I would be very grateful.

Thanks a lot
Patrick

Copyright (c) Marimer LLC