Rich user interfaces enable and disable controls based on the current form-state. Input fields may also be mandatory for instance. Since this logic is user interface related it should not be in the business logic: it depends on the consumer if this information is usefull.
On the other hand, when the business logic could provide hints about a row of data, like:
- is the row editable
- can the row be deleted
- is a particular cell value editable
the Controller in the MVC-architecture could update the view accordingly. See also this article about a business logic property "Color", http://martinfowler.com/eaaDev/uiArchs.html.
So where do you put this additional information (UI-hints) when you exchange ProDataSets with the UI and when do you provide it? Basically every value in a temp-table can be decorated with at least the following properties:
- CanChange
- IsMandatory
And every row with:
- CanUpdate
- CanDelete
For the latter you can also take the optimistic approach and enable Save/Delete buttons and let the business logic decide your edits where not allowed after all.
Some aspects can be inferred from the temp-table definition or in the case of XML from the schema. Based on the primary key fields you could disable corresponding controls for existing rows. But this might not always be the case.
Note: when you're using DataSets in a .Net UI, you should be carefull with enabling the uniqueness constraint for a DataTable (primary key): when your DataTable has a natural primary key, which can't be assigned at the UI-level, you can't insert two rows at the time. So a batch oriented data entry screen is not applicable without altering the temp-table definition. This is one of the practical issues you have to face...
Theo.
I don't think that information belongs in a data object. It is specific to the particular view and may even be subject to access control specific to the user.
I don't think that information belongs in a data
object. It is specific to the particular view and
may even be subject to access control specific to the
user.
That's my first hunch as well, but now imagine you have a data structure with rows & values on one side and somekind of state structure with access-rights/validation constraints on the other side. How do you synchronize this and it would also require an extra roundtrip to an AppServer:
- first fetch the data
- next fetch the presentation hints
So in the OO-world you would encapsulate the raw data value in somekind of ControlView-class, that encapsulates the other properties as well. At least if you want to "automate" the presentation logic a bit. Take the simpler case of a string value: there is no such thing as a string in your application, it's a Memo-field with 32K size, a Code-field of 2 characters in uppercase, etc. Now these properties apply to the entire entity (database column), but things like "can this value be edited" are row context sensitive.
Theo.
Again, I don't think they belong in a single object. The access control rules can depend on the view and the model and controller should not have to change with a different view. One view might be a read-only inquiry screen, another one that only allows updating certain information based on the rights of the specific user and another a wide open change everything. Also, different views might be presenting different parts of the data so that access control on a datum that is not presented is meaningless.
Again, I don't think they belong in a single object. The access control rules can depend on the view and the model and controller should not have to change with a different view. One view might be a read-only inquiry screen, another one that only allows updating certain information based on the rights of the specific user and another a wide open change everything. Also, different views might be presenting different parts of the data so that access control on a datum that is not presented is meaningless.
Don’t be too hard on me, okay?
Regards,
PSDN.
Again, I don't think they belong in a single object.
The access control rules can depend on the view and
the model and controller should not have to change
with a different view. One view might be a
read-only inquiry screen, another one that only
allows updating certain information based on the
rights of the specific user and another a wide open
change everything. Also, different views might be
presenting different parts of the data so that
access control on a datum that is not presented is
meaningless.
So, maybe the backend should provide some information about what actions are valid with the current business logic. (eg. can update customer name, can't update customer number) Perhaps this could be implemented on a row level (eg. can delete customer number 5, can't delete customer number 7 - perhaps with further information "because orders exist", sending this kind of extra information, even if the order information isn't requested).
That information could then be used in the view component. ie. in the update view, enable the different UI objects - in the inquiry only view, don't enable them.
Is this how you would implement such things today? If not, how would you approach it?
So, maybe the backend should provide some information
about what actions are valid with the current
business logic.
To be more precise: what actions are valid with the current data stream. The issue is that in a SOA environment you're decoupling behavior from data, since your business service provides or digests a ProDataSet (or business document) based on a request. For the "dumb" UI, or automatically rendered UI, this data is meaningless unless it's decorated.
An example is Microsoft InfoPath 2003, which allows you to design a form based on a web service. When the web service provides a schema, it's much easier to design a more precise form, since schema's can contain constraints.
Determining wether or not a customer can be deleted is business logic. You can have two approaches when you present a list of customers in a grid
1) optimistic approach which allows all operations
2) pessimistic approach which disables actions (buttons/menu items) when they're not relavant.
In this case I'm not talking about access control (security). It's easy to expand this to enabling/disabling/hiding controls like you state below:
(eg. can update customer name, can't
update customer number) Perhaps this could be
implemented on a row level (eg. can delete customer
number 5, can't delete customer number 7 - perhaps
with further information "because orders exist",
sending this kind of extra information, even if the
order information isn't requested).
Exactly.
Is this how you would implement such things today?
If not, how would you approach it?
Our traditional client/server application hides/disables actions when you can't execute them, so this is the pessimistic approach. And code is duplicated in the UI to achieve this. Here you might argue the value compared to the resources used. But if we forget the actions, we still have to enable/disble controls somehow else you will end up with a pretty dumb user interface, that's not able to react on the user input.
My design point is: let's say I want to add two "properties"/"aspects" to each value in a data row. How are you going to address this when you only have a ProDataSet that can store simple values like integer, string, etc? A workaround would be the addition of a property table, but that will be:
1) hard to manage
2) size will be big: unless you need somekind of coding schema, you need a property-row in the propery table for every value (for every row in all tables).
Theo.
I guess I need a use case to explain why this type of control is relevant. I don't suppose you have any experience with the Siebel architecture. It is one of the best designed applications I have seen. In it, one can have a Customer applet which allows editing and another appliet which is read only, possibly identical in appearance. The developer puts these applets together into screens and the administrator decides which users get access to which screens. So, there is no difference in business logic underneath, just a different applet that presents a different layout or functionality.
E.g., they have many applets that are arranged as browsers in which the user can change the size and sequence of columns. Any column which is included can be editted (if that was the way it was set up). But, there will also be a form applet that has only one record and more fields arranged in a way that makes it easy to create or edit. In many places, clicking on one button takes one from the browser to the form, which is actually a new screen with a new collection of applets. No business logic has changed.
These view applets can include conditional logic, e.g., a field might be editable when the record is new, but not edittable if it is old or if it is closed. It isn't that the BL is signalling that a record is not editable, it is signalling that it is not new or open/closed, something that one might want to display anyway.
Incidentally, their UI is done entirely in a browser with a sort of per-Ajax set of automatically downloadable code modules that provide a highly interactive screen and minimal network traffic, much as Ajax is supposed to allow.
Can you give me a case where the business logic needs to decide on these things rather than it simply being a case of the state of the record, i.e., something the view component can do based on state?
Can you give me a case where the business logic needs
to decide on these things rather than it simply being
a case of the state of the record, i.e., something
the view component can do based on state?
To stick with the order example:
1) once the order has been approved, it might not be allowed to change the orderline's discount percentage. It might be possible though to change the orderline's delivery date.
2) when you have saved an order with a particular currency ("USD"), it might not be allowed to change that currency ("EUR") when the order is being processed (a particular state-field on the order)
3) when you have price agreements, it might not be allowed to change the defaulted price for a particular customer when entering an orderline.
These are examples of process related restrictions for the use case "order entry". Some of these restrictions can be configurable (based on the deployment schema).
So there can be a business service that handles request "get me order XXX". When you present the order, you can imagine you want to show a tooltip with "This customer has price agreements" on the disabled price field in the order entry form, so the user knows why it can't enter that value. But how will the UI(-controller) know it should display a tooltip and disable the control when it has no more information than the price value?
1) you could duplicate that code in the UI-controller, but that's not what you want if you would like to create a thin UI-tier.
2) you could implement business service calls in the UI-controller to fetch the additional UI-hints, but that will create a chatty interface and you have to manage both pieces of data.
3) you could invent somekind of contract, so the UI-controller knows how to fetch the additional UI-related hints.
4) you could go for the optimistic scenario and enable all controls, since you don't know what the user is going to do (perhaps he only wants to look at the order). But I don't think that's acceptable in all cases...
I think enabling/disabling controls conditionally is pretty common in data entry forms, since it guides users to their goal. So why not generalize this concept, so you can automate it?
Theo.
1) once the order has been approved, it might not be allowed to change the
orderline's discount percentage. It might be possible though to change the
orderline's delivery date.
My customers would shoot me if I did that.
2) when you have saved an order with a particular currency ("USD"), it
might not be allowed to change that currency ("EUR") when the order is
being processed (a particular state-field on the order)
This seems so improbable that I would be perfectly happy handling it with an exception condition in the fashion of an optimistic lock exception ... or, I wouldn't make it a restriction. Why should it be a restriction?
3) when you have price agreements, it might not be allowed to change the > defaulted price for a particular customer when entering an orderline.
3) when you have price agreements, it might not be allowed to change the
defaulted price for a particular customer when entering an orderline.
In my own experience, price is always rule-based, not entered by the operator ... having operators enter prices is enormously risky, both in terms of error and in terms of potential for fraud. But, if it is really necessary, then there can be a flag for it.
Aside from the fact that I can't doing some of these things, I see nothing here that one can't accomplish simply by having the BL provide a flag to indicate the state. Indeed, following the Siebel model, one might well have a view accessible to the normal operator which was controlled by the flag and another view accessible to supervisors or management in which the flag was not observed ... same BL, controller and model underneath both of them. And, one might have another view accessible by customers which did something else.
But how will the UI(-controller) know it should display a tooltip and disable > the control when it has no more information than the price value?
Like I said, the kinds of things that you are talking about are issues of state, so it is reasonable for their to be flags and values which convey that state. Some views might ignore the state, some change colors, some hide fields, and others would access only fields which were unrelated to the state so they would ignore it.
1) you could duplicate that code in the UI-controller, but that's not what
you want if you would like to create a thin UI-tier.
I see no duplication of code. In fact, I see the flags being set as a part of marshalling the object in the data access layer, when it is an existing order, or arising from the business logic if it is a new order ... not even something that happens in the model or controller. The controller is about flow, not business logic at this level. These lower levels set the state and it is up to the view to decide whether and how to respond to it. Even two views which both respond to the state might respond to it in a different way, e.g., a customer facing screen might hide a field while an employee facing screen might display it but allow no change.
2) you could implement business service calls in the UI-controller to fetch
the additional UI-hints, but that will create a chatty interface and you have
to manage both pieces of data.
I see no need for this kind of chat. The controller has no need to micro-manage the view.
3) you could invent somekind of contract, so the UI-controller knows how
to fetch the additional UI-related hints.
Or, the contoller can stay out of the micromanagement biz and simply let the view do what it should do based on state.
I think enabling/disabling controls conditionally is pretty common in data
entry forms, since it guides users to their goal. So why not generalize this
concept, so you can automate it?
Because it is the wrong kind of encapsulation. One of the whole idea of the MVC pattern is that one can keep the same model and controller and use them with multiple views. For that to be true, each view needs to be able to react appropriately without getting view-specific instructions. So, if there is a state difference which enables editing of a field ... and probably another view using the same model and controller in which editing is allowed regardless of state ... then this behavior has to be located in the view and it must be based on state indicators.
This is what bothers me about the published PSC MVC example because the contoller is very specific to the individual view and operates in terms of controlling those components of the view instead of operating in terms of the state of the object. This is not a correct implementation of the pattern and it ought to get changed before it leads people down the wrong path.
My customers would shoot me if I did that.
That's what I could expect when challanged for examples. Don't miss the point: it's an example and it's about a control that somehow needs to be enabled/disabled, showing a tooltip, emphasizing itself when dealing with a mandatory field or whatever you can come up with.
But, if it is
really necessary, then there can be a flag for it.
So there is a flag and there is the price value. This means we have to extend the original temp-table definition with a flag for field "price". When do you stop adding state-fields to the definition? And where are you going to put the translation logic that maps your state-flag value to the actually hiding/disabling of a particular control. This is not a matter of databinding...
So there is a flag and there is the price value. This means we have to
extend the original temp-table definition with a flag for field "price".
No. The flag is not about the field. The flag is about the state. The state may impact one field, a dozen, the whole record, or some complext behavior. The state is a part of the domain definition of the object, not just something thrown in for the UI. If it is a meaningful state, we would expect business logic behaviors to be associated with it as well.
One
of the whole ideas of the MVC pattern is that one can
keep the same model and controller and use them with
multiple views. For that to be true, each view needs
to be able to react appropriately without getting
view-specific instructions. So, if there is a state
difference which enables editing of a field ... and
probably another view using the same model and
controller in which editing is allowed regardless of
state ... then this behavior has to be located in the
view and it must be based on state indicators.
This is certainly true. The Controller should send to the View only instructions that it can validly deduce as being appropriate, without trying to do all the specific View's job for it. Some of these instructions may be universal "rules of the UI" for a particular application design, such as that navigation should be disabled when in an updating state. Others may be derivable from the way the data is packaged, if the data describes some aspects of its state (such as which fields or rows are modifiable or not). A particular View can react to "modifiable" and turn that into a particular UI result, such as enabling fields. But it's a valid part of the description of the data as a business object; other business logic could look at the same flag and reject a field modification regardless of whether it came through a UI or not. Some of these kinds of rules may be fairly constant for a particular business object (such as that you can't change the Customer Name through the Order object, even though it is joined into the dataset for convenience). Others will depend on the state of the object and who is manipulating it. But regardless of what logic sets the flags, they are an appropriate part of the state of the object and one of the useful things that can be done with some of them is to allow the View to automate some aspects of the data display by interpreting them. If different Views represent different access modes or whatever for the same data, then somehow it has to be communicated back to the data access layer who is making the request, so that permissions and other parts of the logic can be applied to the data at that level. Some of these may be useful to a particular View, but findamentally they are a part of the description of the data object.
Theo's question remains, namely, how best to overlay these kinds of flags onto the data as it is passed around. Some built-in flags such as CanModify or whatever have been considered and will continue to be. Suggestions will always be welcomed. Otherwise one can imagine a variety or more or less ugly workarounds in extra fields somewhere.
This is what bothers me about the published PSC MVC
example because the contoller is very specific to the
individual view and operates in terms of controlling
those components of the view instead of operating in
terms of the state of the object. This is not a
correct implementation of the pattern and it ought to
get changed before it leads people down the wrong
path.
I understand that the published MVC example embeds assumptions about the partucular UI platform (ABL GUI client in this case) into the Controller logic, which is a limitation. But it is certainly not intended to apply only to a single View, only to provide for the View interpretations of UI rules that are either universal or that it can deduce from its relationship to the data description in the Model on the one hand and the realization of that in the View on the other. And however broad these general rules can be made, the View will always be in charge of a certain portion of its own logic; the goal is to extract whatever can be generized and put it somewhere where it is implemented only once.
Theo's question remains, namely, how best to overlay these kinds of flags
onto the data as it is passed around. Some built-in flags such as CanModify
or whatever have been considered and will continue to be.
What I am question about his question is the appropriateness of such a limited flag when that flag must relate to some other property such as a record state. Suppose, for example, that one wants to allow the ship-to address of an order to be changeable except when it is too late, i.e., the order has already shipped. Rather than having a can modify flag on each of the address fields, the apppropriate focus for this logic is a field indicating the state of the record, which probably needs to be there anyway.
Perhaps someone can suggest some examples that are not coming to mind for me, but it seems to me that this kind of can see, can modify, can delete behavior stems entirely from one of two sources. One is some aspect of record state, which the UI can react to directly; the other is some aspect of the UI itself, e.g., my mention earlier of seemingly identical Siebel "applets", one of which is read-only and the other of which is not and the applet provided to the user depends on the characteristics of the user and their path through the application.
In the absolute worst case, I suppose that one could end up with a one to one correspondence between columns and state flags to control their behavior, but certainly this will not be the common case. Indeed, for behavior differences which derive from the BL, I would say that the typical case was that many columns were controlled by a single state and that state indicator was probably already a part of the record.
One idea would be to use one or more states for a given set of fields, have a flag for a subset of fields to allow or disallow changes to them, and field-specific flags for exceptions to the field set / state flag.
Ideally, most of the time the state would tell you everything, but when it doesn't, there'd be flexibility to control down to the field level if the need was there.
My point, though, is that one really has no need to be thinking in terms of UI oriented fields within the domain object. There shouldn't be UI oriented flags, there should be states and it is the UI that interprets those states to produce the correct behavior.
The UI behavior derives from the domain. I.e., the reason one wants to create these differences in behavior in the UI is because there is some inherent characteristic or behavior of the domain object which relates to that behavior ... unless it is the difference in UI logic independent of the individual domain object like read only screens.
What I am questioning about (Theo's) question is the
appropriateness of such a limited flag when that flag
must relate to some other property such as a record
state.
I guess I can only make the boring response that I agree with you -- except that I don't see these flags as being particularly 'limited' -- and though I won't speak for him I suspect Theo does too. I am not thinking of any of these kinds of flags as being "UI-specific", but related in one way or another to the business logic that applies to an object. As per my previous example, some settings will be more or less absolute for an object, such as that ttOrder.CustName, if you choose to include such a field in a dataset, is not modifiable through that Order object -- ever. That's a business rule that in this case derives from the structure of the database data the dataset is derived from. Your example is one that is state-dependent: if Order.Shipped THEN OrderDate = read-only, however you set this (and speaking of this, there is a READ-ONLY flag that's available to you for buffer fields, like the MANDATORY flag, though the runtime engine doesn't do anything with it). I would expect the READ-ONLY flag in this case to be set by something like a FILL event handler on the dataset. In either case, the result is a business rule that can be enforced to make sure no update tries to modify those fields. The UI can certainly make use of this information to change whether a field on a screen is enabled, and this can be very handy, but it is not in any way a UI-specific flag. And as you note, there will be other characteristics that can be set only in the View itself, such as that the particular View is itself read-only. That's fine; different things get set in different places.
Theo's question remains, namely, how best to overlay
these kinds of flags onto the data as it is passed
around. Some built-in flags such as CanModify or
whatever have been considered and will continue to
be. Suggestions will always be welcomed. Otherwise
one can imagine a variety or more or less ugly
workarounds in extra fields somewhere.
Thanks for the excellent summary!
Perhaps a more down to earth example: the "date" value type. A date can be encoded so it can be passed as a single integer value, but it could as well have been split into 3 values: month, day and year. Since we expect a date to be an atomic value, somebody decided we should go for the first option. So the View has to know about this deal else it can't show the fancy calendar control.
Now the more fundamental question: why do we allow the date to be encoded like this, but don't we allow another aspect to be added to a simple value type? When the View would know a string value is uneditable, it can do something about it: prevent user input when that field has focus. The View can't do anything with a status flag for an order: how would it know that status "A" means "order delivered, you can't change the address"? That's interpretation of flag "A", which is business logic.
Going on level deeper: you can even question if a Controller/View, alias the UI, should know anything about relationships between entities. Isn't that business logic as well? If that's the case, how can a Controller pass a query string to an AppServer component, something you see in some of the contracts when looking at the OERA model...
I guess I can only make the boring response that I
agree with you -- except that I don't see these
flags as being particularly 'limited' -- and though
I won't speak for him I suspect Theo does too.
Yes I do (and I'm already married
I am
not thinking of any of these kinds of flags as being
"UI-specific", but related in one way or another to
the business logic that applies to an object.
Yes.
As per
my previous example, some settings will be more or
less absolute for an object, such as that
ttOrder.CustName, if you choose to include such a
field in a dataset, is not modifiable through that
Order object -- ever. That's a business rule that in
this case derives from the structure of the database
data the dataset is derived from. Your example is one
that is state-dependent: if Order.Shipped THEN
OrderDate = read-only, however you set this (and
speaking of this, there is a READ-ONLY flag that's
available to you for buffer fields, like the
MANDATORY flag, though the runtime engine doesn't do
anything with it). I would expect the READ-ONLY flag
in this case to be set by something like a FILL event
handler on the dataset.
That's excellent, but how are these values marshalled to .Net? Hopefully we persuaded Thomas that some people may want to exploit these features, so we can now return to the original question: how to model it in a ProDataSet going to .Net for instance?
In either case, the result is
a business rule that can be enforced to make sure no
update tries to modify those fields. The UI can
certainly make use of this information to change
whether a field on a screen is enabled, and this can
be very handy, but it is not in any way a UI-specific
flag.
And the business logic doesn't have to pay any attention to these flags, since it can't trust these values: they are hints to logic one tier above or below!
My point, though, is that one really has no need to
be thinking in terms of UI oriented fields within the
domain object. There shouldn't be UI oriented flags,
there should be states and it is the UI that
interprets those states to produce the correct
behavior.
What's a "state"? Is it somekind of flag? And how does that flag translate to: "you can't edit those 3 fields, but the other 5 can"? Where does the "state" come from? I understand UI-state, which is the collected user input so far, perhaps the original state of the row-values, other contexts like which user is editing. But other state coming from the business logic needs somekind of translation by the Controller, meaning teh Controller has the understand the "state" (= "business rule").
My point is that, if the rule is that the order date can't be modified if he order is shipped, one doesn't need a read-only flag on the order date field to enforce that. One simply needs the UI to not enable the field because of the state which is already a part of the record.
That's interpretation of flag "A", which is business logic.
So, according to this rule in which the UI must remain blissfully ignorant of any aspect of business logic, apparently it should be legal for the user to enter ZZ in the state field ... or perhaps you want to attach a list of legal values to the state field in the business logic?
How is the UI going to interpret the state thats with the record w/out the associated BL?
So, according to this rule in which the UI must
remain blissfully ignorant of any aspect of business
logic, apparently it should be legal for the user to
enter ZZ in the state field ... or perhaps you want
to attach a list of legal values to the state field
in the business logic?
That's exactly how Microsoft has modelled XAML right now. And sometimes this can be usefull, especially when you want to present the state-field in a combobox.
But with the MVC-architecture this is not the way it goes: the Model provides this information. Perhaps the user pressed "Find" when the state field has focus, the control's event is handled by the View and translated to a known and abstracted FindLegalList action which is passed to the Controller. The Controller passes the request to the Model, which fetches the data and tells the listeners (View) there is new data available. Now the interesting part: in ABL, and most modern applications, the Model is actually a proxy to AppServer services. In the original MVC-architecture the Model was the collection of actual domain objects.
In a remoted scenario it's interesting to design a solution for the following problem: what kind of data (context) needs to flow to the server to fullfill the client's request "get me a list of legal order states". Does it need to now the administration the user in working in, does it need the order type as well, does it need the entire order to provide the proper status list... But this is another challenge you're facing when you want to tie the tiers together (and Thomas, like you stated earlier, you haven't touched the UI-tier yet).
What's a "state"? Is it somekind of flag? And how does that flag translate
to: "you can't edit those 3 fields, but the other 5 can"? Where does
the "state" come from?
State is the business rule relevant condition of the record. The translation of state to behavior of the UI depends on the UI applet. Let me go back to the Siebel applets. Siebel is an application that runs in a browser with a highly interactive UI achieved by the means of some automatic download components in the browser. When one defines a Siebel applet, the result is a split between some code that runs in the browser itself and some code that runs on the server, roughly corresponding to a model and controller with mechanisms for interacting with other layers. For any given domain object like a customer or order, there can be multiple applets. One applet may be restricted in use to managers, for example, and may have priveleges to change things that can't be changed in the applet used by a clerk. Or, an applet may be entirely read-only because it is intended for use by people who don't have the authority to muck with anything. The same domain object is behind all of these, but the business logic of who can do what in what state includes not only the state of the domain object itself, but also the identity and privledges of the user. This is all quite easily implemented in the Siebel toolset by merely putting rules based on state in the applet and by creating a different applet for each user class difference. None of this involves the domain layer setting flags about a field being read-only, especially since this may be true in one applet and not in another.
Let me go back to the
Siebel applets.
Do you own some Siebel stocks
One applet may be
restricted in use to managers, for example, and may
have priveleges to change things that can't be
changed in the applet used by a clerk. Or, an applet
may be entirely read-only because it is intended for
use by people who don't have the authority to muck
with anything.
Don't you see that "security" is a feature, an aspect of an application? It has nothing to do with the actual business logic, since it lies on top of it. Therefor it doesn't fit in this discussion.
So, we've got this order and, being an order in a sophisticated application, let's say that it contains 30 or 40 columns which are codes relating to various aspects of the order. According to what you seem to be suggesting, when I marshal this order object, I should include in the object every value of every code table column which is modifyable.
Alternatively, suppose I marshal just the code current values and possibly the description or whatever it is that I need about the code and instead of bundling the full list of values into the domain object I create collection classes with the list of values for each code and I cache these for use by the UI.
Me, I much prefer the latter.
Do you own some Siebel stocks
As it happens I did, until they were acquired by Oracle. More relevently, I have been trained as a Siebel consultant and done a small Siebel implementation incuding customization.
Don't you see that "security" is a feature, an aspect of an application? It
has nothing to do with the actual business logic, since it lies on top of it.
Therefor it doesn't fit in this discussion.
How the ACL is maintained and accessed may or may not be a part of this discussion, but the rule that clerks can change some information, managers can change other information, and customers can't change any information is certainly a part of the business logic. I can't see why you would think otherwise.
Alternatively, suppose I marshal just the code
current values and possibly the description or
whatever it is that I need about the code and instead
of bundling the full list of values into the domain
object I create collection classes with the list of
values for each code and I cache these for use by the
UI.
Me, I much prefer the latter.
Yes, absolutely, valid choices for modifiable data need either to be cached on the client, when this is practical -- and made a part of the UI as drop-down lists or whatever when this is practical -- or you have to undergo the expense of a call to the back-end when the cacheing is unwieldy; or in extreme cases postpone the validation until the data is actually submitted for update, though this is not very friendly.
How the ACL is maintained and accessed may or may not
be a part of this discussion, but the rule that
clerks can change some information, managers can
change other information, and customers can't change
any information is certainly a part of the business
logic. I can't see why you would think otherwise.
Yes, I think we're agreed that it's part of the business logic. What I'm not quite getting is why -- unless I'm misunderstanding your explanation altogether -- this is then reflected in a series of different View applets that are tailored for different sets of user types and privileges.
The use of different view applets is certainly only one way to solve this kind of problem. One could have a single view applet with more complex behavior instead, but I think the Siebel approach is a very elegant and clean solution. For one thing, it certainly demonstrates the principle of having different views living on top of the same domain objects. But, it also makes for easy configuration without programming because all one needs is a generalized mechanism for specifying which applets are associated with a particular role and a way to attach one or more roles to a user. What a user can see and do is thus the sum of his or her roles.