OverDrive
Added by Ted Husted, last edited by Ted Husted on Oct 25, 2005  (view change)
Labels: 
(None)


The PhoneBook is a simple application, with a single "Entry" entity.

We describe entities in terms of a Story, Overview, Schemas, and Screen.


RFC - PhoneBook Architecture

This is an high-level description of the architecure being used with the PhoneBook application.

Square One

The database statements are kept in an XML documents. Each statement has a unique name. The statement names follow the same general conventions we use with the database tables and columns. There is one database document for this application, named "Queries.xml". It's kept in the "Resources" folder.

The application uses Command objects to call the statements. One or more Commands can be assembled into a [Chain] (of Commands). Only some of the Commands call statements. Other Commands validate input or tweak the result of database statements.

Like the statements, each Command has a unique name. By default, the Commands that call the database are named after the statements. The "entry_list" Command calls the "entry_list" statement.

When we need to call more than one statement to complete a task, and the Commands are combined into a Chain, a column retrieved from one statement can be used as input to another, if needed.

For example, the directory list supports "paging" through dataset. The "entry_list" Command is actually a chain that invokes two other commands. One command retrieves the rows for the current page. Another command gets the total row count, so we can calculate the number of pages.

Consistency is Key

A key strategy of our architecture is to use consistent naming conventions to bind layers of the application together. Just as we name Commands after Statements, we also name controls on the server pages after Commands and database fields. If a field is named "entry_date" in the database, then we name the TextBox "entry_date" too. If we need a list of extension_key values, then the DropDownList is named "extension_key_list".

Consistent naming conventions help make an application easier to understand. If we see a control named "last_name", it's a safe bet that the value corresponds to the database column "last_name".

Consistent naming also make rote tasks easier to automate. We can bind a key-value dictionary to a collection of controls by matching an entry-key with a control-id. We can read back values the same way. We can even map the item selected on a list control by dropping the standard "_list" suffix. we can read back the selected item for "program_key_list" as "program_key", and use that value to populate a database statement. All without writing an extra drop of code.

ASP.NET uses the same stategy when mapping code-behind objects to page controls. If a page control is named "extension_key_list" then the server-side object must also be named "extension_key_list". Other frameworks, like Apache Struts, use reflection to populate controls from objects in much the same way.

Soup to Nuts

The Nexus architecture extends the notion of consistent naming from the page, through the code-behind and business logic classes, all the way back to the database. However, the page controls are not directly "bound" to the database columns. There are mapping layers in between, but, by default, we choose to use the same identifier, soup to nuts, whenever we can.

The "Special K" exception

A major exception is the [name of the key fields]. In the database, primary keys are named "pk_table", and the foreign keys would be named "fk_table". The primary key column for the facility table is named "pk_entry". A foreign key referring to the program table is "fk_entry".

Our "Special K" naming convention is useful within the database but not useful within the application. From the application's perspective, it's the same value and maintaining primary key versus foreign key attributes is extra work. In the application layer, the key attributes are all named "table_key". The database statements maps the field names back and forth. Other column names could also be mapped in the same way. But, all things remaining equal, we prefer to use consistent names throughout.

"But, don't some of the database naming conventions conflict with C# conventions?"

Yes, they do. But C# naming conventions are just that: conventions. When they are useful, we use them. But, when they are not helpful, we replace them with more useful conventions, and document the exceptions. Conventions are meant to serve us, not we them.

Of course, if our database naming conventions were worthless and weak, then it might be useful to map them to more meaningful names. We could map the identifiers any way we like, in the same way we map pk_* and fk_* to _key. But our database naming conventions *are useful, so we choose to use them.

Code-Behind Regions

Code-behind pages allow a clean separation of your HTML from your presentation logic. The server page hosts the HTML markup. The code-behind page provides the dynamic data. The client interacts with the server page to create an event. The code-behind logic handles the event. Separating these concerns make the HTML markup and logic code easier to create and maintain.

Within our code-behind pages, there are usually two distinct regions. One region hosts the usual ASP.NET event handlers. The other region hosts Command helper classes.

Separation of Concerns Redux

The event handler methods focus on the presentation logic. The Command helpers take care of the data access and business rules. The Command helpers are finely grained to provide exactly what the event handler needs, in exactly the way the event handler needs it. The helpers are the integration layer where we adapt our application to run on ASP.NET.

There is often a 1:1 relationship between a Command helper and a event handler. The primary purpose of the Command helpers is not to reuse code but to encapsulate code. Since they are not meant to be reused, the Command helpers are inner classes.

Occaisonally, the Command helpers may provide reuse by being used as delegates. The same event handlers may be used for more than one data set by swapping which Command helper delegates are used.

Nexus Helpers

... TBC

See also

  • [RFC - Chain of Responsibility pattern]
  • [RFC - A key by any other name]


Entry Overview

Description

  • Detail for an employee listed in the directory.

Responsibilities

  • Does: Provides detail about an employee.
  • Knows: First Name, Last Name, Username, Extension, Hire Date, Hours, Editor.

Collaborators

None.

Entry Schemas

View Schema

ID Label Control Contraints Item Hidden Error Hint
first_name First Name Input !empty        
last_name Last Name Input !empty        
user_name Username Input          
extension Extension Input          
hired Hire Date Input isDate        
hours Hours Input isDouble        
editor Can Edit Check1 isInt        

Data Schema

Table: entry
Column Type Nullable Default Indexed
pk_entry char(36)   ''
first_name char(18)   ''  
last_name char(18)   ''  
user_name char(9)   ''  
extension char(18)   ''  
hired date   '0000-00-00'  
hours double   0  
editor tiny(3)   0  

Entry Screen

Outputs

  • Last Name
  • First Name
  • Extension
  • Hire Date
  • Hours
  • Editor

Filters

All Filters link back to the directory page.

  • Last Name
  • First Name
  • Extension
  • Hire Date
  • Hours
  • Editor

Commands

All Commands link back to the directory page.

Label
Show All
Print
Add New If Editor
Edit For any row, if Editor

Site running on a free Atlassian Confluence Open Source Project License granted to OSS. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5.5 Build:#811 Jul 25, 2007) - Bug/feature request - Contact Administrators