In the new e-book, I see the ProjectDisplay view uses as its VM the ProjectGetter object, which provides read-only access to the ProjectEdit and RoleList objects. Stated in this section is the following:
Because this viewmodel is used by a read-only view, there is no reason to support the Cancel operation, so the ManageObjectLifetime property is set to false. This prevents the CSLA 4 ViewModelBase class from calling the BeginEdit, CancelEdit, and ApplyEdit
methods on the business object.
Given this, how do you decide when to create a separate ReadOnly object vs just creating an Editable object and using the ManageObjectLifetime property when you need a read-only view? Thanks.
I would create a separate ReadOnly if the usage differs.
In my opinion, indicators are if the properties differ: either the number (i.e join or sql view to add more, or reduce significantly); or if non-scalar properties can change from immediate load/child to a lazy loaded ReadOnly variant of the child.
Because we use code generation, adding ReadOnly objects wouldn't be much work, on the other hand I would not have to many entities. My design approach is to identifiy "patterns of how objects are used", i.e. as a tree node, main editable of a form (the 80% entry forms), overview lists, etc. The patterns are basically given by the concept of the UI experience, special cases, or real performace issues (UOW).
I would made the decision of adding a separate ReadOnly not to the fact that it's read only, but that its properties or loading is different.
Interesting question for which you will get far more intelligent answers than mine on here but I thought I’d chip in because it’s been a pet topic of mine for many years.
I have never much bought into the read-only business object approach where a separate instance of a class is created to encapsulate the read-only-ness behaviour. If I have an Order, for example, that can behave in a read-only fashion I still see it an order sharing the properties, data access, and many (not all and this is where the debate kicks off) the behaviours of its non-read-only counterpart. I could even argue that the business rules should still be applied so that any read-only instance can be clearly seen as broken if that be the case.
So when I started out on my Csla journey many years ago I choose implement more than a single behaviour in every significant business class. Read-only-ness is one if these. But so too is child/root, etc., etc. The key thing for me is operating environment and I view the types of workplaces I operate in as unlikely to be disciplined enough to keep instances of classes in sync over time. I make these compromises to ensure a developer doesn’t have to search out all Order related code to add/change/delete a property because in my experience a change to the core editable business object inevitably leads to changes to all the related classes too.
Now, all that said, I understand the need to have what I’d call lookup classes where you model select-first-manage/edit-later type approach. If the selection part only requires a couple of properties like Name & Description I will likely choose a Lookup<T> class but if more/many/all the properties are required I will choose a collection of the core objects created with read-only behaviour.
So perhaps this ManageObjectLifetime used in this manner is a step toward my thinking and, perhaps, with the prevalence of presentation layers (or ModelViews) beneath/supporting the UI allowing the business object creator dictate some behaviour isn’t seen as a totally undesirable compromise!?!
Please don’t flame me with behaviour versus data, properties, etc. and how I have totally misunderstood OO principles because I really do understand those arguments already and understand totally the compromises of my thinking.
Currently, I'm using ReadOnly BOs in only two scenarios:
- I think what you call Lookup: a read only root list with its read only children to display in a tree, drop down or multi column chooser, search results etc.
- Mapped to a view or joined tables to provide an overview list. This is not a BO but a broader view of associated information, and performance is the driving factor.
I would agree with both of these. The only thing I would suggest ( keeping head down) is that these really aren't business objects. They'd be more presentation oriented. But I'd have no probem with your choice of structures to hold this data in.
You're absolutly right.
I'm using CSLA read only objects for its mobile behaviour and because they're easily generated.
They might be "presentation oriented".
But I suggest that any object model that is properly designed to meet a use case or user story will, almost by definition, fit smoothly into the presentation.
This is because the presentation is also designed to meet the same use case, or story. It is hard to imagine how good object-oriented design for a use case would end up with an object that didn't match the presentation requirements - given that the presentationa and business model must meet the same requirements.
Yes, I think your term ("presentation oriented") is more appropriate. And for navigation tree, overview list or data for creating a report, this is perfect (they are ready only).
But, if there exist multiple screens for really different user scenarios, where you can modify the same data or even create new associated parts? According to your statement, you would create different business object classes, wouldn't you?. Then, where to put validation and calculation logic that are true for both (true for the domain). Is this an indicator for an UoW and delegation?
CSLA helps really to share business logic (i.e. rules) across client/server tiers.
But what about sharing across different use cases?
(disclaimer: I'm on heavy-duty pain killers due to having hernia surgery yesterday - so this could be rambling and might use metaphors that are overly florid)
One area where my view has changed over my career is "reuse of code".
Like most people, I used to think that reuse was a primary goal. This has been a driver behind procedural, modular, component-based, and even object-oriented designs over the past 24+ years of my career and our industry.
Over the past decade however, there's been an increasing realization that the ultimate evil in software is coupling. This has been a driver behind services and serivce-oriented architecture/design. The whole point of SOA is to reduce or eliminate coupling. (sadly, not everyone gets that this is the whole point, but it really is the one big reason to accept the costs of SOA).
I'm a Batman fan. Always have been. If you recall, one of Batman's primary foes is Two Face. And Two Face has a coin that is pristine on one side, and blackened on the other side. He flips this coin to decide the fate of his victims - shiny side is good, blackened side is bad.
This coin represents reuse and coupling. Reuse is the shiny side, coupling is the blackened side. You can not have one without the other. So to get reuse, you must accept the ultimate evil of coupling.
Because of this, you must understand that reuse is not a goal. It is a desirable side-effect, and if you can get it without undo coupling that's good. But reuse always comes with coupling, and so all reuse brings with it some element of darkness and doom.
I always thought reuse was a goal. Something worth pursuing to the point that it altered software design, etc.
But over the decades I've learned that most reuse incurs enough coupling that the end result is negative, not positive.
So I do reuse code, but only when I don't incur so much coupling that the end result is worse than if I'd skipped reuse/coupling.
In practical terms, I recommend "normalization of logic". And I don't count property declarations as logic - they are code snippets that are stamped out in .5 seconds each, so they are meaningless in terms of cost.
But business rules, validation rules, authorization rules - these are logic. These are worthy of reuse when possible.
So I'll happily create multiple classes that have overlapping properties, as long as I can attach the same rules to those properties. Normalizing the rules into a rule library allows this to happen. So the rule (the logic) exists once and is reused, and the super-cheap-to-create properties exist where necessary to support various user scenarios.
Also, I will reuse actual business classes (BusinessBase types, etc) as long as I can reuse them without conditional logic. In other words, if two user scenarios need exactly the same business type, then I'll reuse that type. As soon as the two user scenarios start to have different requirements though, I'll break that into two business types.
If you don't follow this approach, you end up writing the same kind of if..then..else code that led to unmaintainable COBOL, FORTRAN, BASIC, Pascal, C, etc.
Thank you very much for your detailed and enjoyable answer.
Yes, you're right. I probably was to deep in details. I now remember what I found most valuable when I got really into OO using Smalltalk: It's not about inheritance but about delegation. And Smalltalk classes remind me of bosses or experts, who pertend that they can do that, but in fact they only know who is responsible and how to delegate ;-)
But yes, you have to decide what's worse / maintainable in a long-term view.
This whole thread has been very helpful. I guess it takes a while to rethink the picture on reuse and what its priority should be, because that was (mistakenly) the main thing me and other devs in my group put forth to management about why we should consider moving to CSLA and investing time in learning it. This was after we had read the 2005 BO book but before we really began to use it. We wanted reuse so much because in our organization, we've got 50 different internal apps developed in many different ways, each often doing lots of the same types of things (like getting a list of customers, products, etc). And further, each of those apps have their own versions of stored procedures that essentially do the same thing but in a slightly different way, pulling from differnet databases/tables that contain the same types of data. It is a mess that made us really desire reuse and standardization.
But I will say that, after completing the first small project with CSLA, I feel great about having a consistent approach to building applications going forward. Not to mention all the features and complexities that are taken care of by the CSLA framework (like making objects mobile, the rich-model paradigm, etc).
On the basis of my experience there are certain other factors, which incluence sucess / failure:
Because there's seldom enough support of the management and all teams for a big thing (50 apps), I would start with small parts, which will likely succeed in a short time period.
good luck ;-)
First, Rocky, sorry to hear of your painful troubles and hope the recovery is speedy. My disclaimer this afternoon is that I am writing from a position of severe and prolonged sleep deprivation so I have no idea where this post will lead me…..
This is definitely a topic with passionate views both on the purist and the practical side of the coin. And thoughts are always evolving and changing. It gets weary but it also important to air views every now and then. I am only answering here because I want to post more questions and feel it would be disingenuous not complete something i may have started here even though I have suspicions it'll put me in the firing line
I fought hard in an upgrade from csla 1 to 2 to keep my deep inheritance capabilities because in a well defined domain that type of coupling isn’t necessarily a bad thing. In fact, I viewed it as a positive thing in the right circumstances, in the right hands. I certainly did not want to exclude its possibility. Csla uses inheritance to good effect but people shouldn’t be blinded by its brilliance either and not question - this is probably my single most disappointment with professionals in our field these days: that if an expert says or does something then that is correct. No need to think about it or question. Just follow. You have far more power than you probably already even know Rocky. But, as you point out, the experts too are evolving their opinions an approaches constantly (or regularly might be a better word. Hopefully!). But they/you have no power over who keeps up with your current thinking and who stays with your 2001/5/8 thinking.
So inheritance and coupling in Csla? A good or a bad thing?? I don’t use Undobable capabilities – never have because I still live in fear of disappearing data (or information) in our world so I persist ASAP - yet I am forced to have those capabilities if I inherit from BusinessBase. I like BusinessBase. A lot. But I especially like BindableBase .So I weigh up the costs of recreating those capabilities without undoableness. Or I refactor out Undoable. But what if I need undoable in the next app or just in the next screen which uses the same business object. Should have I have 2 instances of the framework? It seems pure use case driven this is the recommendation. But at what cost? Very little in terms of pure day 1 development but potentially lots as the system evolves through its lifecycle – remembering that the initial build part of the lifecycle, in big evolving (someone mentioned budgets, etc.) systems, becomes a smaller and smaller part of the overall time and cost. But that also constitutes some level of if/then/else decision in code and likely supporting documentation/reasoning/etc. on why one screen approach differs from another – so no bad coupling but still conditional logic somewhere guaranteed to cause head-scratching and sweeping “this is bad code, csla is terrible” statements in the future as new developers and managers come along.
I wanted to introduce an IsSavable property across many (perhaps not all) of my business objects and provide some default logic. Must I introduce this logic on all classes separately or do I create a base class with this capability. Or do I decide that an object itself shouldn’t know whether it is savable but that should be the responsibility of some other object (isSavable = StateManagement.IsSavable(myObject)). After all you’ll never hear business talk about savability. But what about encapsulation – I really like encapsulation. Doing all this the pure, correct way will be unlikely to lead to rapid development and ease of maintenance over time unless all developers are Lhotkas or Guthries or the like. So we compromise to ensure software doesn’t get overly complex for purity sake. I like developers to have to deal with a minimum set of classes to achieve their goals. I like public factory methods on business classes (in fact, I like mine all to be named the same: Customer.Load / Order.Load / Car.Load) rather than separate factory classes (myCustomer = Factory.Load(typeof(Customer)….); I like capabilities like myCustomer.Save() rather than SateManagement.Save(myCustomer); etc., etc. because once a developer has to coordinate a lot of elements he really isn’t all that interested in (he cares only about Customer) the possibilities of error and pattern deviation (usually resulting in error at some inconvenient time in the future) grows.
What about Batman himself. Is he a man displaying all the normal behaviours of or a man? Well obviously not. When he’s got his tights on he’s behaving quite abnormally. Bat-like I suppose! Yet he still walks and talks, etc. and most of the time behaves very much like any normal fellow. Should he inherit the behaviour of man or of a bat or of anything? How many instances of Batman should we have – when he’s behaving like a man, a bat, and a bat with man features, a bat without core bat features (does he consume large volumes of insects I wonder?), just a man with tights etc. – he appears a complicated fellow to pin down. There’d likely be duplication of common complex aspects of his personality across all of these. Of course you want to define your Batman based on use cases rather than on his overall behaviour so it’s more of a “what is Batman up to now” thought process.
This, I suppose, is where my thinking wavers from one side to the other (I can argue myself each way on a lot of these topics which isn’t really a comfortable position to be in) – in this instance I am probably more likely to capture all of his behaviour into a set of Batman related classes right from the start and expose this to clients. This rather than risk another man dressed in tights who sleeps in a cave suspended upside-down appearing in my business layer at some point who looks a lot like my Batman but inherits from Bat and has some inconsistent or odd behaviour – he eats insects by the truck load because nobody bothered to remove that behaviour.
How I want to view Batman is entirely at the whim of the presentation use case – flying, sitting, sleeping. The fact that he can do all three may be irrelevant to one view but it is intrinsic to the Batman. If I assume he’s sitting when he’s actually flying I might be in trouble.
Ok, these examples might be odd and maybe don’t even illustrate my concerns very well.
I do think design is key and is something that perhaps with all of our RAD capabilities doesn’t happen to a great degree anymore – at least not at the level of actual code. The trouble with bad design is that you will eventually (or sooner) end up with that erroneous property at a base level or a behaviour that really isn’t as common as you imagined on day 1. I think that is why it’s easier to decide against inheritance and reuse to any great degree – you suffer duplication to avoid refactoring and the implications that involves.
I do believe, and maybe I am just too stuck in my thinking, that designing a business object purely to fit a single use case is slightly weird. I rarely see and class of significance to an application (those 10/20% complex areas) used in a single manner. And, in pure practical terms, this means following the use case approach duplication is inevitable and the level of duplication can be significant. Duplication to me, with the best will in the world and the best tools in the world (even the best people in the world), will always be a high risk approach. Time has proven (to me) that recreating or altering a behaviour, a rule, a calculation, a condition in multiple places within a single system or across multiple systems will result in failure on some level.
I suppose I should clarify what that reuse word means to me. Whenever I say I’d like to have a single object display several behaviours it looks as though I am talking purely about code reuse. Of course I am to a large degree but that’s not the whole story. I am mostly talking about behaviour and logic reuse. Now, of course, we can achieve behaviour reuse in a many ways (all with their own problems) but they all involve some written code somewhere. Writing/generating/etc. it n time to me means n possibilities of getting it wrong. But it’s probably the n+1 problem that is the greatest risk – that 1 place your developer didn’t look at, didn’t refactor, etc.
In summary (and probably not really as I deleted large chunks of this because it got far too long), I personally think of business objects as distinct from presentation objects. Presentations change all the time. Core business elements do too but less often – they are usually fundamental to a business and its process and are key to its success. VMs to me are today’s purity of presentation objects. I see these as windows on a relevant slice of the business layer at a point in time. I may only want to see a small part of it right now but I must not be allowed to compromise its integrity. And, I actually feel that presentations are changing in business applications – I honestly think the days of static views are numbered. So use cases in any given scenario are getting more and more elusive. I might be managing Batman’s wardrobe in this screen but, you know what, I feel like calling him to arrange a fitting, is he in-flight, can he use his hands, or has he an earpiece, is it in, etc. – a bunch of dig deeper type pieces of information that I’d have had difficulty thinking through at requirements gathering time when those nice IT people called around. I also feel that as the issues of performance and footprint pale into insignificance business layers will become more complete to be navigated deep and wide and encapsulate every aspect of a business.
There you go – even the summary was long winded. I hope all this somehow coherent. Perhaps some more drugs will help!
Csla uses inheritance to good effect but people shouldn’t be blinded by its brilliance either and not question - this is probably my single most disappointment with professionals in our field these days: that if an expert says or does something then that is correct. No need to think about it or question. Just follow.
I would agree with this - there is a danger. At the same time, there is too much to learn for most (or at least me) to be an expert on everything let alone one thing, and rightly or wrongly I have identified a few people over the years whose opinions I hold in higher regard due to their displayed experience and understanding of topics. In many cases they are speaking from years of experience wrestling with issues with which I have little experience. So thinking about it and questioning it is a must, but it is sometimes difficult to go a different route when lacking in understanding. But that is the great thing about forums like this - we get to hear different viewpoints and often I find they give me a blended perspective on an issue.
In the relatively short time using CSLA I found that the individual business objects can be designed clear, stable, and almost identical across the different user stories. What really differs is the object graph. They are smaller or broader, from A to D or from C to F.
With a user story specific graph, I can benefit from all loading and saving features of children.
Without I'll have mutliple root, which I can load using a UoW and save with an "update command", and the view model (sub view models) have to coordinate the status of all roots.
So, I have to decide what probably fits better, especially low-maintenanc. The domain expert can tell if the user stories more likely to drift apart or to converge.
Copyright (c) Marimer LLC