> When I'm trying to move to a more OOP style of building CF applications, I

> always find that when it comes to building sections like a login section 
> or a message recording form, I can't relate OO to it. When I read examples

> in both Java and CF they are always cars, people or animals.

Don't get me started on the tortured metaphors and examples that litter the
OO landscape. If I see one more ridiculous car.goFaster() example I'm going
to scream.

> I find it 
> hard to turn the idea of having properties and methods to a login screen. 
> Then I find I fall back into procedural programming.
> 
> How do those who do use OOP create login screens or forms?

Personally, I wouldn't use objects for the screens and forms. I would use
cfm templates and custom tags, respectively. In general, I use cfm's for
display and cfc's for logic. Screens and forms fall under the former.

I would (and do) use objects to control authentication. A simple check might
look something like this:

  <cfset sessionManager = createObject("component", "SessionManager")>
  
  <cfif not sessionManager.isUserAuthenticated()>
    
    <cflocation url="login.cfm">
    
  </cfif>
  
  <cfset account = sessionManager.getAccount()>
  
  <cfoutput>
    #account.getAccountNumber()#
  </cfoutput>

In this example, SessionManager is responsible for keeping track of the
user, whether or not they've logged in, and (assuming they've logged in and
identified themselves) which account they belong to.

A prerequisite of calling SessionManager.getAccount() would be that
SessionManager.isUserAuthenticated() returns true. Otherwise,
SessionManager.getAccount() should throw an error.

Ostensibly, SessionManager stores all of this in the session scope, but it
could place it anywhere. Often, I'll place an instance of the SessionManager
itself in the session or request scope just for ease of reference. This
usually happens in the Application.cfm. I won't reference it directly from
within custom tags, just from the requested cfm pages.

The login page might look something like this:

  <cfimport taglib="tagLibs/layout" prefix="layout">
  <cfimport taglib="tagLibs/login" prefix="login">
  
  <layout:page title="Log In">
    
    <login:form formAction="authenticate.cfm" />
    
  </layout:page>

And the authentication page:

  <cfimport taglib="tagLibs/layout" prefix="layout">
  <cfimport taglib="tagLibs/login" prefix="login">
  
  <cfparam name="form.userName" type="string">
  <cfparam name="form.password" type="string">
  
  <cfset sessionManager = createObject("component", "SessionManager")>
  
  <cfset sessionManager.authenticate(form.userName, form.password)>
  
  <cfif sessionManager.isUserAuthenticated()>
    
    <cflocation url="success.cfm"> 
    
  </cfif>
  
  <layout:page title="Log In Failed">
    
    <p>
      We're sorry, but we were unable to log you in. Please try
      again.
    </p>
    
    <login:form formAction="authenticate.cfm" username="#form.userName#" />
    
  </layout:page>

SessionManager.authenticate() would be responsible for checking the user
name and password against a table or list of logins. It could also perform a
check to ensure that the login hasn't failed more than 10 times in the past
hour and lock the account if necessary.

The point is, that kind of logic will be encapsulated in the
SessionManager.authenticate() method. All we'll know is whether or not the
authentication process was successful.

The SessionManager.authenticate() method could also return another
component, AuthenticationResult, which would contain a more useful error
message (account expired, account locked out, etc.):

  <cfimport taglib="tagLibs/layout" prefix="layout">
  <cfimport taglib="tagLibs/login" prefix="login">
  
  <cfparam name="form.userName" type="string">
  <cfparam name="form.password" type="string">
  
  <cfset sessionManager = createObject("component", "SessionManager")>
  
  <cfset result = sessionManager.authenticate(form.userName, form.password)>
  
  <cfif sessionManager.isUserAuthenticated()>
    
    <cflocation url="success.cfm">
    
  </cfif>
  
  <cfif result.getResult() is result.RESULT_ACCOUNT_EXPIRED>
    
    <cflocation url="accountExpired.cfm">
    
  <cfelseif result.getResult() is result.RESULT_ACCOUNT_LOCKED_OUT>
    
    <cflocation url="accountLocked.cfm">
    
  </cfif>
  
  <layout:page title="Log In Failed">
    
    <p>
      <cfoutput>
        #htmlEditFormat(result.getMessage())#
      </cfoutput>
    </p>
    
    <login:form formAction="authenticate.cfm" username="#form.userName#" />
    
  </layout:page>

In this example RESULT_ACCOUNT_EXPIRED and RESULT_ACCOUNT_LOCKED_OUT are
constant values defined by the AuthenticationResult component itself. They
could be numeric values, strings, whatever. That's not important as long as
you use the property name to reference them.

The calling template could be coded to handle as many different result
scenarios as necessary, just as long as SessionManager.isUserAuthenticated()
is the one true authority on whether or not the user successfully logged in.

You can wrap all of this in an OO framework like Mach-II or Model-Glue. In
essence, they will replace the cflocations in the examples above,
controlling the flow of the application from page-to-page (or
event-to-event). You'll find various examples for these frameworks on the
Web, starting with:

  http://www.mach-ii.com/
  http://www.mach-ii.info/
  http://www.model-glue.com/

But they still won't make your screens or forms object oriented. They will
make the control-flow object oriented. Specifically, they both use a method
known as implicit invocation...but that's a whole 'nother topic.

Anyway, I'll stop now. All that typing and I'm not sure if I've even begun
to answer the question. :)

Ben Rogers
http://www.c4.net
v.508.240.0051
f.508.240.0057



----------------------------------------------------------
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).

CFCDev is supported by New Atlanta, makers of BlueDragon
http://www.newatlanta.com/products/bluedragon/index.cfm

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


Reply via email to