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.
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. :)
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.
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.
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?
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, 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.
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.
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.
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 :)
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 :)
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 :)
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.
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 :)
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.
Copyright (c) Marimer LLC