I'm not sure how correct it is, but I tend to create two objects:

1) A domain object - in your case "employee".  This contains all the
information that could be needed by a single instance of the domain object.

2) An implementation object for working with the domain object - for example
"employeeCollection".  This collection object is designed to hold multiple
employee components.  It would contain methods like "getEmployees()",
"getSortedBySalary()", etc.

Basically anything to do with lists of things would be handled by specific
collection objects.  I've found actually that my collection objects have a
tendency towards sameness - so I'm currently working on a generic collection
object that can be extended in domain specific ways.

Like I said - I'm new to this too and may be way off base on this, but the
method works for me.

Jim Davis

> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf
> Of Kairoh!
> Sent: Monday, December 08, 2003 7:43 AM
> To: [EMAIL PROTECTED]
> Subject: [CFCDev] Wanted: OOP Best Practice for CFC's with database
> interaction
> 
> Hi everyone,
> 
>  I have build a simple employee CFC - shown below - that interacts with a
> database. This CFC uses a utilities CFC for handling zero-length strings
> and
> preparing datefields for a database insert or update. The CFC does the job
> as expected. So far so good. But there are two questions bothering me:
> 1. From an OOP perspective an employee.cfc should not contain a
> listEmployees method. How could I solve this? Sometimes you need a list of
> employees. How should this be done in a OOP best practice example? Two
> CFC's? A design pattern?
> 2. I have the idea my implementation for accessing, inserting and updating
> could be done in a much cleaner fashion. Does anyone has a suggestion how
> to
> improve it.
> 
> In summary, can anyone of you provide me with a best practice example for
> building an OOP-based CFC with integrated database interaction that does
> listings too. I have read Hal's book, but it does not discuss database
> access implementations. Ben's book has a nice example of OOP and database
> access but the example is based on a CFC/CFM combination. I am planning to
> use the CFC as part of a RIA application(CFC/SWF combination). All
> suggestions, links, book titles, articles are welcome.
> 
> This is my first time on this list. (Don't shoot me, I have searched the
> archives but could not find the answer to my question).
> 
> Vinny
> 
> 
> <cfcomponent displayname="Employee dataprocessing services" hint="This
> component provides employee information services">
> 
>   <cffunction name="listEmployees" access="remote" output="no"
> returntype="query" displayname="List employees" hint="Returns a list of
> employees">
> 
>     <!--- Optional keyword argument --->
> 
>     <cfargument name="Keyword" type="string" required="false"
> hint="Optional
> search criteria; if not given, all employees are returned.">
> 
>     <!--- Get the employees information --->
> 
>       <cfset var q_EmployeesInfo="">
> 
>     <cfquery name="q_EmployeesInfo" datasource="#APPLICATION.DataSource#">
>       SELECT  Employees.EmployeeID,
> Offices.OfficeName,Employees.FirstName
> 
>       FROM            Employees, Offices
>       WHERE   Employees.Office = Offices.OfficeID
> 
>     <!--- If a keyword has been specified --->
> 
>     <cfif IsDefined("ARGUMENTS.Keyword")>
>       AND             FirstName LIKE '%#ARGUMENTS.Keyword#%' OR LastName
> LIKE '%#ARGUMENTS.Keyword#%')
>     </cfif>
> 
>       ORDER BY        Employees.LastName
>     </cfquery>
> 
>       <!--- Finally, return the populated employee query. --->
> 
>     <cfreturn q_EmployeesInfo>
>   </cffunction>
> 
>   <cffunction name="getEmployee" access="remote" output="no"
> returntype="struct" displayname="Get employee information" hint="Returns
> detailed information about the specified employee">
>     <cfargument name="EmployeeID" type="numeric" required="true" hint="ID
> specifying the particular employee to get">
> 
>       <!--- Get the employee information --->
> 
>       <cfset var q_EmployeeInfo="">
> 
>       <cfquery name="q_EmployeeInfo"
> datasource="#APPLICATION.DataSource#">
>               SELECT  *
>               FROM            Employees, Offices
>               WHERE   Employees.Office = Offices.OfficeID
>               AND             EmployeeID =
> <cfqueryparamvalue="#ARGUMENTS.EmployeeID#" cfsqltype="cf_sql_integer">
>       </cfquery>
> 
>       <!--- If we do not find a record for the employee, the object ID is
> invalid. Throw an exception to notify the caller --->
> 
>       <cfif not q_EmployeeInfo.RecordCount>
>               <cfthrow message="ERROR_UNKNOWN_USER">
>       </cfif>
> 
>       <!--- Create a structure for the employee information. --->
> 
>       <cfset st_Employee = StructNew()>
> 
>       <!--- Populate the employee structure with employee information.--->
> 
>       <cfset st_Employee.EmployeeID           = q_EmployeeInfo.EmployeeID>
>       <cfset st_Employee.OfficeID             = q_EmployeeInfo.OfficeID>
>       <cfset st_Employee.FirstName            = q_EmployeeInfo.FirstName>
>       <cfset st_Employee.Login                = q_EmployeeInfo.Login>
>       <cfset st_Employee.Password             = q_EmployeeInfo.Password>
>       <cfset st_Employee.LastName             = q_EmployeeInfo.LastName>
>       <cfset st_Employee.BirthDate            = q_EmployeeInfo.BirthDate>
>       <cfset st_Employee.Email                = q_EmployeeInfo.Email>
>       <cfset st_Employee.Remarks              = q_EmployeeInfo.Remarks>
>       <cfset st_Employee.Picture              = q_EmployeeInfo.Picture>
> 
>       <!--- Finally, return the populated employee structure. --->
> 
>     <cfreturn st_Employee>
>   </cffunction>
> 
>   <cffunction name="createEmployee" access="remote" output="no"
> returntype="struct" displayname="Insert new employee" hint="Inserts a new
> employee in the system">
>       <cfargument name="Office" type="numeric" required="false" default=""
> hint="The employee's office">
>       <cfargument name="Login" type="string" required="true" hint="The
> user's login">
>       <cfargument name="Password" type="string" required="true" hint="The
> user's password">
>       <cfargument name="LastName" type="string" required="false"
> default="" hint="The user's last name">
>       <cfargument name="BirthDate" type="date" required="false" default=""
> hint="The user's birthdate">
>       <cfargument name="Email" type="string" required="false" default=""
> hint="The user's email">
>       <cfargument name="Remarks" type="string" required="false" default=""
> hint="Remarks concerning the user">
>       <cfargument name="Picture" type="string" required="false" default=""
> hint="The user's photo">
> 
>       <!--- Create a structure for the employee information. --->
> 
>       <cfset st_Employee = StructNew()>
> 
>       <cfset st_Employee.Login = " ">
> 
>       <!--- Before we add the employee, we need to make sure that the
> employee's login does not already exist. If the employee does exist, we'll
> throw an exception. --->
> 
>       <cfif IsDefined("ARGUMENTS.Login")>
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Login">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Login#">
>               </cfinvoke>
>       </cfif>
> 
>       <cfquery name="EmployeeCheck" datasource="#APPLICATION.DataSource#">
>                SELECT         *
>                FROM   Employees
>                WHERE  Login = <cfqueryparam value="#st_Employee.Login#"
> cfsqltype="cf_sql_varchar">
>       </cfquery>
> 
>       <cfif EmployeeCheck.RecordCount>
>               <cfthrow message="ERROR_USER_EXISTS">
>       </cfif>
> 
>       <cftransaction action="begin"/>
> 
>       <cfset st_Employee.Office = " ">
>       <cfset st_Employee.Login = " ">
>       <cfset st_Employee.Password = " ">
>       <cfset st_Employee.LastName = " ">
>       <cfset st_Employee.BirthDate = " ">
>       <cfset st_Employee.Email = " ">
>       <cfset st_Employee.Remarks = " ">
>       <cfset st_Employee.Picture = " ">
> 
>       <!--- Add the information from the arguments if they exist. --->
> 
>       <cfif IsDefined("ARGUMENTS.Office")>
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Office">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Office#">
>               </cfinvoke>
>       </cfif>
> 
>       <cfif IsDefined("ARGUMENTS.Login")>
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.login">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Login#">
>               </cfinvoke>
>       </cfif>
> 
>       <cfif IsDefined("ARGUMENTS.Password")>
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.password">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Password#">
>               </cfinvoke>
>       </cfif>
> 
>       <cfif IsDefined("ARGUMENTS.LastName")>
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.LastName">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.LastName#">
>               </cfinvoke>
>       </cfif>
> 
>       <cfif IsDefined("ARGUMENTS.BirthDate")>
>               <cfinvoke component="common" method="prepareDateField"
> returnvariable="st_Employee.BirthDate">
>                       <cfinvokeargument name="DateString"
> value="#ARGUMENTS.BirthDate#">
>               </cfinvoke>
>       </cfif>
> 
>       <cfif IsDefined("ARGUMENTS.Email")>
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.email">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Email#">
>               </cfinvoke>
>       </cfif>
> 
>       <cfif IsDefined("ARGUMENTS.Remarks")>
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Remarks">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Remarks#">
>               </cfinvoke>
>       </cfif>
> 
>       <cfif IsDefined("ARGUMENTS.Picture")>
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Picture">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Picture#">
>               </cfinvoke>
>       </cfif>
> 
>       <!--- Insert a employee info record into the database. --->
> 
>       <cfquery datasource="#APPLICATION.DataSource#">
>                INSERT INTO    Employees (Office,
>                                       Login,
>                                       Password,
>                                       LastName,
>                                       BirthDate,
>                                       Email,
>                                       Remarks,
>                                       Picture)
>                VALUES         (<cfqueryparam value="#st_Employee.Office#"
> cfsqltype="cf_sql_integer">,
>                                       <cfqueryparam
> value="#st_Employee.Login#" cfsqltype="cf_sql_varchar">,
>                                       <cfqueryparam
> value="#st_Employee.Password#" cfsqltype="cf_sql_varchar">,
>                                       <cfqueryparam
> value="#st_Employee.LastName#" cfsqltype="cf_sql_varchar">,
>                                       <cfqueryparam
> value="#st_Employee.BirthDate#" cfsqltype="cf_sql_date">,
>                                       <cfqueryparam
> value="#st_Employee.Email#" cfsqltype="cf_sql_varchar">,
>                                       <cfqueryparam
> value="#st_Employee.Remarks#" cfsqltype="cf_sql_varchar">,
>                                       <cfqueryparam
> value="#st_Employee.Picture#" cfsqltype="cf_sql_varchar">)
>       </cfquery>
> 
>       <!--- Commit the database changes. --->
> 
>       <cftransaction action="commit"/>
> 
>       <!--- Get the new ID. --->
> 
>       <cfquery name="q_returnQuery" datasource="#APPLICATION.DataSource#">
>                SELECT         @@identity
>                AS                     newId
>       </cfquery>
> 
>       <!--- Finally, return the new ID. --->
> 
>     <cfreturn getEmployee(q_returnQuery.newId)>
>   </cffunction>
> 
>   <cffunction name="editEmployee" access="remote" output="no"
> returntype="struct" displayname="Update employee information"
> hint="Updates
> employee information in the system">
>       <cfargument name="EmployeeID" type="numeric" required="true"
> hint="The unique object ID for the user">
>       <cfargument name="Office" type="numeric" required="false" hint="The
> employee's office">
>       <cfargument name="Login" type="string" required="true" hint="The
> user's login">
>       <cfargument name="Password" type="string" required="true" hint="The
> user's password">
>       <cfargument name="LastName" type="string" required="false" hint="The
> user's last name">
>       <cfargument name="BirthDate" type="date" required="false" hint="The
> user's birthdate">
>       <cfargument name="Email" type="string" required="false" hint="The
> user's email">
>       <cfargument name="Remarks" type="string" required="false"
> hint="Remarks concerning the user">
>       <cfargument name="Picture" type="string" required="false" hint="The
> user's photo">
> 
>       <!--- Create a structure for the employee's information. --->
> 
>       <cfset st_Employee = StructNew()>
> 
>       <cfset st_Employee.EmployeeID = ARGUMENTS.EmployeeID>
> 
>       <!--- Prepare the user info text fields for updating the database
> --->
> 
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Office">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Office#">
>               </cfinvoke>
> 
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Login">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Login#">
>               </cfinvoke>
> 
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Password">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Password#">
>               </cfinvoke>
> 
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.LastName">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.LastName#">
>               </cfinvoke>
> 
>               <cfinvoke component="common" method="prepareDateField"
> returnvariable="st_Employee.BirthDate">
>                       <cfinvokeargument name="DateString"
> value="#ARGUMENTS.BirthDate#">
>               </cfinvoke>
> 
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Email">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Email#">
>               </cfinvoke>
> 
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Remarks">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Remarks#">
>               </cfinvoke>
> 
>               <cfinvoke component="common" method="prepareTextField"
> returnvariable="st_Employee.Picture">
>                       <cfinvokeargument name="TextField"
> value="#ARGUMENTS.Picture#">
>               </cfinvoke>
> 
>       <!--- Update the employee's info --->
> 
>       <cftransaction action="begin"/>
> 
>       <cfquery datasource="#APPLICATION.DataSource#">
>               UPDATE          Employees
>               SET                     Office = <cfqueryparam
> value="#st_Employee.Office#" cfsqltype="cf_sql_integer">,
>                                       Login = <cfqueryparam
> value="#st_Employee.Login#" cfsqltype="cf_sql_varchar">,
>                                       Password = <cfqueryparam
> value="#st_Employee.Password#" cfsqltype="cf_sql_varchar">,
>                                       LastName = <cfqueryparam
> value="#st_Employee.LastName#" cfsqltype="cf_sql_varchar">,
>                                       BirthDate = <cfqueryparam
> value="#st_Employee.BirthDate#" cfsqltype="cf_sql_date">,
>                                       Email = <cfqueryparam
> value="#st_Employee.Email#" cfsqltype="cf_sql_varchar">,
>                                       Remarks = <cfqueryparam
> value="#st_Employee.Remarks#" cfsqltype="cf_sql_varchar">,
>                                       Picture = <cfqueryparam
> value="#st_Employee.Picture#" cfsqltype="cf_sql_varchar">
>               WHERE           EmployeeID = #st_Employee.EmployeeID#
>       </cfquery>
> 
>       <!--- Commit the database changes. --->
> 
>       <cftransaction action="commit"/>
> 
>       <!--- Finally, return the userdata. --->
> 
>     <cfreturn getEmployee(st_Employee.EmployeeID)>
>   </cffunction>
> 
>   <cffunction name="deleteEmployee" access="remote" output="no"
> returntype="numeric" displayname="Delete employee information"
> hint="Deletes
> all information for the specified employee">
>     <cfargument name="EmployeeID" type="numeric"  required="true"
> hint="Unique object ID specifying the particular employee to delete">
> 
>     <cftransaction action="begin"/>
> 
>       <!--- Delete the item from tbEmployees --->
> 
>     <cfquery datasource="#APPLICATION.DataSource#">
>       DELETE FROM     Employees
>       WHERE           EmployeeID = #ARGUMENTS.EmployeeID#
>     </cfquery>
> 
>     <!--- Commit the database changes. --->
> 
>     <cftransaction action="commit"/>
> 
>       <!--- Finally, return the deleted employee. --->
> 
>       <cfreturn ARGUMENTS.EmployeeID>
>   </cffunction>
> </cfcomponent>
> 
> 
> ----------------------------------------------------------
> You are subscribed to cfcdev. To unsubscribe, send an email
> to [EMAIL PROTECTED] with the words 'unsubscribe cfcdev'
> in the message of the email.
> 
> CFCDev is run by CFCZone (www.cfczone.org) and supported
> by Mindtool, Corporation (www.mindtool.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' 
in the message of the email.

CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).

An archive of the CFCDev list is available at www.mail-archive.com/[EMAIL PROTECTED]

Reply via email to