Hi
Seth,
Many
thanks for the great response. I should elaborate on my setup. I have an
application generator, so all of the meta data that relates to an objects
properties (field type, data type, data length, field type properties, value
list, validations, transformations, etc.) is stored in a set of data tables. My
app generator knows everything there is to know about an object and how to
display it.
In CF
5 where I didn't have to consider OO principles, I generated display scripts,
business logic scripts and data access scripts. A bunch of mutual including
occurred and my application worked fine.
I
still have all of the object information authoritatively in my database. The
code I generate is an artifact used to improve runtime performance, not an
authoritative source of information, but I'm still trying to use OOP
principles to generate the right code in the right places. For instance, I used
to use index.cfm to get Page.SecurityLevel and include authentication if
required. Now I call Page.securePage() - a method of the page object that
handles whether or not to invoke user security thus avoiding the coupling of my
index.cfm having to know about the Page.SecurityLevel property (even via a
getter which still includes knowledge of the name and possibly the type of a
private property).
I have
just read a few books on OO, but I just didn't see why you needed the UI
templates to know anything about the object properties - it seemed to break
encapsulation.
I have
a widget generator that uses a set of questions to fully define an element of
display (something capable of displaying 1 or n records in a table, columns, one
record per row, etc. and that can support any or all of the fields being viewed,
added or edited with the editable and viewable field lists being generated
from a master list at runtime to allow different user roles to view and/or edit
different sets of fields using the same widget). The widget is usually the only
part of the screen that knows about object data and n-widgets can be combined in
a screen template which is used to suppot a mode (display products, view to
cart, send email newsletter, etc.) and which sits within a page template that
supports n-dynamic screen areas so you can have a couple of navigational areas,
a list of featured products or news down the right and a main content area (for
example).
My
question is why the widgets would be anything other than a method of the object
that they are displaying. Surely the User object should be responsible
for generating well formed HTML for displaying single users, user forms and/or
user lists. It is the only way to avoid encapsulation.
A lot
of people seem concerned about keeping HTML out of cfc's and I believe they may
be confusing a newbie mistake (renaming custom tags with database access and
display generation all in one script as cfc's) vs. a valid OO
principle.
I see
having a getUserProperties method that validates the request and then passes it
to the DAO to get the data. However, most of the time I don't see that method
being used by other objects (I may even make it a private method). If I want to
display a few users in the center of the page, my template knows that I want to
use the "default_admin_user_list" widget to handle that, and I should call a
method of the user object to handle that. The method would be something like
getDefaultAdminListHTML() and would return a string ready for display. Of course
you'd probably use some kind of pattern so that getDefaultAdminListHTML() didn't
have to know how to generate HTML, but it'd handle calling the appropriate data
and UI generator (which would know nothing about users or products or whatever
other than what it was passed). You would probably also have a
getDefaultAdminListXML() method for returning the data as XML and could easily
generate another method that would display in tables vs. CSS or using
WAP.
As
previously mentioned, I'm still very new to this. Also, all of my code is
generated, so it really doesn't matter to me where it goes, but I'd really like
to use best practices and I don't see how anything other than the User object
should know how to display users as you're hard coding a dependence into the
display layer. I understand that this approach might be a little more work if
you were actually writing the code, but it seems to me a better practice.
However, that is "me" who hasn't actually completed more more than a hello world
example in real OO code (other than some university projects almost 15 years
ago), so education much appreciated!
Best
Wishes,
Peter
Peter
---------------------------------------------------------------Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Seth Petry-Johnson
Sent: Friday, January 20, 2006 10:53 AM
To: [email protected]
Subject: Re: [CFCDev] UI and encapsulation> Still trying to get my head around best UI practices in CFMX.> Responses to date seem equally split between using UI cfc's> and preferring custom tags.I'm not sure I understand the distinction between a "UI cfc" and a custom tag approach, and how that has anything to do with encapsulating object data.To me a "UI cfc" means a CFC whose primary purpose is generating and/or outputting HTML, and a "custom tag" (in the context of a user interface) is a CF custom tag that outputs HTML. Depending on which one you are using your display page (or view or whatever) looks like one of these:#myUI.addLayout("Blah blah blah")#-- or --<cf_addLayout>Blah blah blah</cf_addLayout>But neither one of these approaches really has anything to do with your primary question (as I understand it), which is...
> In short, how can I create a specific UI for an object while> ensuring that the UI has no knowledge of the fields and their> associated display properties for that object?!Does this mean you are looking to automagically generate a details form for an object, but you need to have some control over the form details (input type, maxlength, etc)?The simplest way would be to obtain the object's meta data and then look for all methods with a name starting with "get". These indicate getter methods, so you would pull off the "get" part to obtain the field name and then invoke the getter to get the value. This doesn't give you granular control over the field properties though.A more advanced "automagical" approach might introspect the database to determine things like field length, data type, etc. Of course, you'd need to tell your form generator which DSN and table to introspect, so this ins't really "automagical" after all. Plus, you still don't have manual control over specific form fields.A far less automatic approach, but the best one IMHO, would be an XML config file that describes how the form should be built. You'd have one of these files for each object type, and then a generic FormGenerator CFC that reads the XML and creates the appropriate form.Depending on your application, it might be appropriate to add a generateFormBuilderXml() method directly to your objects. This method would generate the XML for that object. (You might even add this method to a generic base class with a default implementation that introspects the object's private data members and creates a default XML schema. You would then override this implementation with a specific one on the objects that require it)Hope that helps a bit... if I totally misunderstood you let me know and I'll try again :)On 1/20/06, Peter Bell <[EMAIL PROTECTED]> wrote:Hello All,
Still trying to get my head around best UI practices in CFMX. Responses to
date seem equally split between using UI cfc's and preferring custom tags.
Here's a question that maybe someone on the "custom tag" side should speak
to.
Lets say I need an HTML UI comprising of a form, and the FirstName field
must have the following code: <input type="text" name="UserFirstName"
size=="50" maxlength="150">. Lets further assume that some of those
properties are unique to FirstName, so I can't just generically loop through
a struct of passed field names in the UI and use default field HTML for all
of the properties.
How can I put the code above into a custom tag without breaking
encapsulation? In short, how can I create a specific UI for an object while
ensuring that the UI has no knowledge of the fields and their associated
display properties for that object?!
It seems to me that I must put the UI into the appropriate object as a
displayAsHTML method or similar otherwise something other than the object
knows about and depends on the internal structure of what should be private
properties. (Of course, the displayAsHTML should wrap the getUserDetail
method rather than knowing anything about data access)
I'm sure I am missing something here. Any input on what I'm missing would be
most gratefully received!
Best Wishes,
Peter
----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email to [email protected] with the words 'unsubscribe cfcdev' as the subject of the email.
CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting ( www.cfxhosting.com).
An archive of the CFCDev list is available at www.mail-archive.com/[email protected]
----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email to [email protected] with the words 'unsubscribe cfcdev' as the subject of the email.
CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting (www.cfxhosting.com).
An archive of the CFCDev list is available at www.mail-archive.com/[email protected]
You are subscribed to cfcdev. To unsubscribe, send an email to [email protected] with the words 'unsubscribe cfcdev' as the subject of the email.
CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting (www.cfxhosting.com).
An archive of the CFCDev list is available at www.mail-archive.com/[email protected]
