The PhoneBook is a simple application, with a single "Entry" entity.
We describe entities in terms of a Story, Overview, Schemas, and Screen.
This is an high-level description of the architecure being used with the PhoneBook application.
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.
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.
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.
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 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.
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.
- [RFC - Chain of Responsibility pattern]
- [RFC - A key by any other name]
- Detail for an employee listed in the directory.
- Does: Provides detail about an employee.
- Knows: First Name, Last Name, Username, Extension, Hire Date, Hours, Editor.
- Last Name
- First Name
- Hire Date
All Filters link back to the directory page.
- Last Name
- First Name
- Hire Date
All Commands link back to the directory page.
|Add New||If Editor|
|Edit||For any row, if Editor|