Nesting classes

Nesting classes

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


Vertigo1 posted on Saturday, August 19, 2006

Hi again, apologies for my elementary questions but I'm a bit new to CSLA and this object-orientation lark :)

Have been thinking about nested classes and when and how they should be implemented, specifically with regards to the CSLA framework.

As a simple example, take an address.  An address consists of several fields and potentially has business logic to validate the contents or perhaps perform postcode lookups and so forth.  As such an address could be used in many places, presumably an Address class would be the way to go to encapsulate this "complex type" and its behaviour?

If so, then you may also have a Contact class which, amongst other fields, contains a nested Address class.  What I'm not sure about is how this would work within the CSLA framework.  Firstly, with regards to validation, I presume the parent Contact class would simply have a rule which checks the validity of the nested Address class, thus delegating responsibility for validation of the Address to that class.

Of more concern is how you'd bind such an object to an interface.  If the interface was required to "flatten" the hierarchy and show the properties of the nested Address class alongside those of the parent Contact class, presumably you'd need two binding sources, one for the Contact object and one for the nested Address and then possibly two error providers, one for each class and so forth.  This all seems rather messy tbh.

What's the best way to design such a system?

Toby.

david.wendelken replied on Saturday, August 19, 2006

Take a close look at the sample ProjectTracker application that comes with CSLA.

Change the name from Resource, Assignment and Role to Contact, Address and Address Type respectively and you've got the makings of a solution.

Take a VERY close look at how the CSLADataSources are configured in the sample pages - it's very obvious once you "get" it, but not so obvious as to be intuitive. :)

Vertigo1 replied on Monday, August 21, 2006

Hi David,

Thanks for that.  I've had a look at how the sample classes are organised and I think I follow you.  If I understand correctly, in my example scenario, the fields constituting the address for the contact would be placed directly in the Contact class but the responsibility for "managing" these fields would be delegated to a separate, static Address class which would contain all the business logic (i.e. rules) for these fields.  I'd implement an interface, such as IHoldAddress, defining the properties for the address fields, which would be implemented by the Contact class and any other class which needed to hold an address.  The AddBusinessRules method on each of these classes would use the rules defined in the static Address class, each of which would accept an object reference and use the IHoldAddress interface to access the properties.  Does this sound right to you?

With regards to data access, if I follow the same pattern implemented by the ProjectResource/Assignment classes then I'd have a dedicated Address table in the database which would hold all addresses and the Contact table would only contain a foreign key reference to this table.  This effectively normalises the data in the database whilst normalising behaviour in the business objects.

The only part of this arrangement which feels slightly odd to me is having the actual address fields replicated in each class which requires an address (an Invoice needs a billing adddress, a Delivery needs a shipping address etc).  Although the business logic relating to these fields is encapsulated by the Address class, my original thought was that this class should actually store the field data itself and then an instance of the Address class would be nested within the Contact, Invoice and Delivery classes, if you follow my drift.  Is this the wrong way to go about things then?  I can see how this complicates matters when it comes to data binding with the UI but replicating these same address fields in multiple classes feels a bit wrong to me as I'm duplicating effort, or am I falling into the "normalising data rather than behaviour" trap that Rockford talks about so much in the book?

Cheers,

Toby.

malloc1024 replied on Monday, August 21, 2006

Your concept of nested classes is incorrect.  A nested class is a class that is defined inside another class. 

Properties are not behavior.  It is acceptable to repeat properties as long as you are not repeating behavior.  I really wish there was a sticky that would explain this in detail.  It seems that many people fall into this same trap. 

Vertigo1 replied on Monday, August 21, 2006

Ok maybe nested is the wrong word but I'm sure you know what I'm on about.

So is my proposed object design the way to go then?  Duplicating the actual fields in each class that utilises an address but factoring out the rules and other behaviour to a static Address class?

malloc1024 replied on Monday, August 21, 2006

Yes, I understood what you were talking about.  However, it is important to use the correct terminology.  It makes it easier to understand the question.

Yes, I believe your suggestion is the CSLA way to do it.  Duplicating properties is acceptable as long as you don’t duplicate the behavior.  Objects are defined by behavior not data.  When using CSLA it is best to use a use-case driven design.  Think of the Customer class as a CustomerEdit class instead.  If you take this approach, it makes more sense to place the address properties in that class.  I believe a use-case driven design is different from a standard OOP design.  I think this is why most people get confused when they start using CSLA.  I would personally leave the address properties in the address class and create an adapter class that encapsulates a customer and address object.

hurcane replied on Monday, August 21, 2006

Here's a response from a Windows Forms perspective...

I've gone the route of exposing the Address as an object and using a different data source for binding in my UI. However, that decision was made because of our UI design. My primary object (an order), has multiple addresses (e.g. bill-to, ship-to, ackowledge-to). In my case, the user sees a display-only summary of the address in the order entry UI , but they can access a dialog to edit complete address information. In addition, the users required the ability to configure the display-only version of the address information.

We have made a smart control that handles the read-only address customization requirements. We bind this smart control to the appropriate address property. The dialog form is also bound to an Address object.

We could have flattened this object structure, as others have suggested, but that didn't seem to fit our needs for the UI. Both solutions will work. You have to decide which one best fits your needs. Sometimes it comes down to flipping a coin. Big Smile [:D]

Vertigo1 replied on Tuesday, August 22, 2006

Hurcane, that's very similar to my original idea.  I too would have certain classes which contain multiple addresses and it just strikes me that having all the address fields (seven in total) repeated over and over isn't very good design.  Apart from the issue of duplicating the fields in separate classes, in cases where a single class needs to hold several addresses, you're looking a load of fields, many of which are effectively identical.  Whilst the business logic for these fields would be delegated to a dedicated, static class, you'd still be "clogging up" the main classes with these fields.

It is for this reason that I thought factoring out the actual field data to a separate class and embedding (is that the right word?) an instance (or several instances) of this class where needed would be a much cleaner design.  Yes it's normalising data, but is this always a bad thing?  The behaviour would still be normalised so it's not a case of normalising data instead of behaviour, just aswell as.

As for the interface, I can see what you're on about with delegating editing of address details to a separate control or dialog and although I might want to do this in some places, in many I would not.  In cases where I wish to view the address fields in a "flat" list alongside the other class fields, it would complicate matters slightly in that I'd need a second binding source for the embedded address object.  What I'm trying to work out is (a) whether the advantage of factoring out the field data to a separate class outweighs the disadvantage of the interface binding complication and (b) whether there are any other issues with this design that I've not yet thought of.

ajj3085 replied on Tuesday, August 22, 2006

Vertigo,

I think creating an Address class (or classes) embeding the Address class as a property is fine.     Each address may have its own rules and behaviors, which the customer object doesn't really care about nor should be responsible for.  If the rules for the Address changes, it should not affect your customer object.

I do this typically:
public Address ShipToAddress {
    get { return shipToAddress; }
    private set { shipToAddress = value; } // We dont want customer clients to push in their own object, just modify the existing one
}

You could also do this, if your ship to address has different behavior than your billing address:
public ShipToAddress ShipToAddress { /* code here */ }

If any address types share identical behvaior, you can encapsulate that within an internal only class, which the public addresses use.

HTH
Andy

Vertigo1 replied on Tuesday, August 22, 2006

Hi Andy,

Cheers for that, nice to know I'm not going totally potty and others are doing things this way :)

Of course, even if the fields themselves weren't stored in a separate Address class, the behaviour could still be normalised out by placing the rules in there, as per the Assignment class in the Project Tracker application but I personally think it will make things much clearer to have all the data stored in the Address class to and reduce each address instance in other classes to a single field/property.

You said you typically do it this way, can I ask how much it complicates the interface and whether it causes any other issues elsewhere?  In many places I will need a flat list of controls bound to properties of the main object, so in the case of a Customer object I might have a flat list of controls for Forename, Surname, Salutation, Telephone, Address1, Address2, Address3...

In this situation I'm going to need two binding sources, one for the main object to which the Forename, Surname, Salutation and Telephone would be bound and another for the embedded Address object, to which the Address1,2,3... fields would be bound.  I presume this is how you do it?  Does it work ok?

Cheers,

Toby.

ajj3085 replied on Tuesday, August 22, 2006

Toby,

Part of the reason I believe in seperating it is because Address is one of those things were the rules likely are shared among use cases, although not always.  It also reduces the number of properties on the parent object, which I think is important.  Ever had to learn an object which has over 500 properties?  Not an easy task..

The situation where it complicates things is when you're displaying address data in some kind of grid.  Typically these are reaonly objects though, and may not necessarly have all the detail your editing object would expose.  Here, I simplify the object model a bit.

You will need two binding sources; your main binding source, and then a second one (and third, forth depending how many complex objects you have).  The secondary binding sources will have their DataSource as the first binding source, and the data member as the comlex property.  You'll have to type that in manually as the designer won't show the property in the dropdown, but it the binding sources work together just fine.

HTH
Andy

malloc1024 replied on Tuesday, August 22, 2006

As I stated in my previous response, I prefer keeping the address properties in the address class.  I share your concerns as well.  I also stated that you could use a wrapper class to bind to these classes.  Couldn’t you create another class that implements a customer and address interface?  You would pass a customer and address object to this object and use it in the form.  I haven’t tried it, but you should be able to bind to it.  This would allow you to keep your hierarchy the way you want it and also allow you to flatten it for data binding.

Vertigo1 replied on Tuesday, August 22, 2006

malloc1024:

As I stated in my previous response, I prefer keeping the address properties in the address class.  I share your concerns as well.  I also stated that you could use a wrapper class to bind to these classes.  Couldn’t you create another class that implements a customer and address interface?  You would pass a customer and address object to this object and use it in the form.  I haven’t tried it, but you should be able to bind to it.  This would allow you to keep your hierarchy the way you want it and also allow you to flatten it for data binding.

Hmm, I see what you're driving at but wouldn't this cause even more grief, as the wrapper class would need to duplicate each property of the main (eg. Customer) class and each property of the Address class, just to pass everything between the original objects and the UI?  I can see how it could be used to "flatten" the hierarchy but I don't wonder if it's causing more problems than it solves.

ajj3085:

The situation where it complicates things is when you're displaying address data in some kind of grid.  Typically these are reaonly objects though, and may not necessarly have all the detail your editing object would expose.  Here, I simplify the object model a bit.

I'd not thought about grids, that's a very good point as the individual address fields would need to be displayed in a grid.  How exactly are you handling this?  My first thought was that the main class could expose a single, read-only string property which returned a single-line representation of the address, delegating the work to the Address class.  This would then allow this single property to be bound to a column of the grid removing the dual-level binding problem.  Of course, if the grid's own search logic was to be used then it would only be possible to search on the single string representation as a whole rather than on a specific address field.  Whilst part of me thinks I could get away with that, the devil on my shoulder is pointing out that some awkward user will ask for it at some point :)

ajj3085 replied on Tuesday, August 22, 2006

Vertigo1:
I'd not thought about grids, that's a very good point as the individual address fields would need to be displayed in a grid.  How exactly are you handling this?  My first thought was that the main class could expose a single, read-only string property which returned a single-line representation of the address, delegating the work to the Address class.  This would then allow this single property to be bound to a column of the grid removing the dual-level binding problem.  Of course, if the grid's own search logic was to be used then it would only be possible to search on the single string representation as a whole rather than on a specific address field.  Whilst part of me thinks I could get away with that, the devil on my shoulder is pointing out that some awkward user will ask for it at some point :)


Well the read only object doesn't have nearly as many properties (because most of them are not relevent in a grid listing) so I just have an AddressLine1, Addressline2, etc. properties.  Its a different use case, so there are different expectations and design to handle this case.

DansDreams replied on Tuesday, August 22, 2006

Looking at the complete picture, there seems to me to be a lot of value of having a separate Address class AND a user control for editing it in the typical contexts of an aggregating class or address list container.

Vertigo1 replied on Tuesday, August 22, 2006

ajj3085:

Well the read only object doesn't have nearly as many properties (because most of them are not relevent in a grid listing) so I just have an AddressLine1, Addressline2, etc. properties.  Its a different use case, so there are different expectations and design to handle this case.

Yeah I had the same thought shortly after posting, why not have the main editable class contain an embedded instance of the Address class, possibly with the aforementioned single address field for convenience, yet use individual fields in the read-only version used for searches and so forth.  Definitely think that's the way forward with this.

I also thought a bit more about the single string field I mentioned.  My original idea was that this would be a read-only property to display the address for info and if the user wanted to edit it they'd pop up a separate dialog which would bind each property in the embedded object.  Why not, however, have this single string property read/write, with some business logic in the Address class to parse the address out into the relevant fields, thus enabling users to just type a load of text in and have the software make sense of it for them.  They could still pop up the full editing dialog if they so desired.  I think I like that solution :)

malloc1024 replied on Tuesday, August 22, 2006

When you are designing your business objects, you should not even think about the presentation layer.  You should develop your business layer without giving thought to the presentation layer or data binding.  If the presentation layer wants something different that the business layer provides, you add an extra layer between the presentation and business layer to bridge the gap.  This is typically how it is done.  Designing the business layer with the presentation layer in mind will only result in poor design.

Vertigo1 replied on Wednesday, August 23, 2006

Hmm, not sure I agree with that to be honest.  Whilst I appreciate that the layers should be separated and the business logic layer should have no knowledge nor dependence on the UI or presentation layers, the interface requirements in terms of presentation and editing of data do have a bearing on what properties and functions are exposed by the business logic.  Surely this is what use cases are all about, defining the needs of the user, and thus the interface, in order to extrapolate what facilities the business logic layer needs to provide?

malloc1024 replied on Wednesday, August 23, 2006

I should clarify what I said earlier.  I meant that you should not think about a specific UI when you are developing your business objects.  Not all UI’s use binding, therefore it’s not a good idea to change your business objects to make binding easier.  IMO, it seems like a bad idea to change your business objects to fit your UI.  Your solution looks good.  However, making a habit of changing your business object to fit your UI will lead to design issues.

Vertigo1 replied on Wednesday, August 23, 2006

Ah right, I'm with you now and agree with what you're saying :)

Whilst I don't want to tailor the business logic to suit a specific UI, I obviously want to make it as flexible as possible which is why I'm trying to think of the different ways users might want to interact with the objects and their properties, such as the ability to either view/edit the address as a single block of text or discrete properties as mentioned earlier.

I don't know about others here, but one of my biggest hates with development is when the boss comes in with some user requirement which I can't implement in the UI without modifying the business logic to expose extra detail/properties/objects etc.  Obviously in many cases this is unavoidable but I like to do my best to anticipate every "petty" user whim :)

ajj3085 replied on Wednesday, August 23, 2006

Well to be fair that 'petty' change is a change in the use case I would think, which would dictate a change in the design.  Of course it doesn't seem like your manager should just be able to willy nilly change use cases like that on you either.

RockfordLhotka replied on Wednesday, August 23, 2006

malloc1024:

I should clarify what I said earlier.  I meant that you should not think about a specific UI when you are developing your business objects.  Not all UI’s use binding, therefore it’s not a good idea to change your business objects to make binding easier.  IMO, it seems like a bad idea to change your business objects to fit your UI.  Your solution looks good.  However, making a habit of changing your business object to fit your UI will lead to design issues.



I agree in general. The one exception to this however, is that you may need to consider whether your UI will run in a stateful or stateless setting. Unfortunately, this can require substantial changes to the way you build your object model. Not so much because of the specific UI, but because of the stateless/stateful choice.

If you are able to be stateful, then you can employ the full range of OO design possibilities - allowing your object model to naturally reflect the relationships between various objects within a broad use case.

If you are required to be stateless, then each request must be viewed as an independent use case. This level of atomicity means that you are rarely able to allow object relationships to assist you in providing natural business behaviors, and you have to write them by hand in a more explicit manner. A pure stateless model should, therefore, be avoided unless it is really required to enable high levels of scalability.

For example, are duplicate line items allowed on a sales order? In a stateful model, your Order object will have a LineItems collection which can easily implement such a restriction. But in a stateless model, each line item is added on a seperate page (request) and so the adding of a line item becomes its own use case. There IS NO LineItems collection - each line item saves itself directly to the database. Thus each line item must implement its own logic, PLUS the logic that should have been in the LineItems collection.

Alternately, you could allow the user to enter duplicate line items, and have a final use case like CommitOrder where you tell them that they messed up 10 steps earlier and need to fix their order (which is probably not a great approach).

Ultimately, stateless models should be minimized, as they are more expensive in terms of coding and maintenance - but they are sometimes necessary.

Beyond the stateful/stateless question, I agree that the object model should reflect the business use cases, not the UI "user experience" - any more than absolutely necessary anyway.

ajj3085 replied on Wednesday, August 23, 2006

I agree, but you can't totaly ignore it either.  In the case of the readonly object, should you make the address a 'complex' property or just include al the address properties as direct properties of the main readonly object? 

In this case, it doesn't really matter either way, until you want to display the read only objects in a grid.  One way will be more complex; you'll have to figure out how to use the Format event get the proper values in the grid, or write a UI wrapper object which exposes the data as a single 'flat' object. 
The other way requires less code in the UI layer.

Yes, while you're right you shouldn't design your BOs according to the presentation, I think this is one of those cases were its ok, because the end design doesn't really 'matter' too much one way or the other... so why not pick the way that makes coding the UI easier (in this particular case).

Copyright (c) Marimer LLC