Why Did I Write Interacx?
I wanted a tool that allowed me to write client-server
applications as quickly and easily as possible. I’ve experienced the drudgery
of writing SQL for every CRUD operation, the frustration of having to instrument
every transaction because they were scattered all throughout the code calling
into the DB API directly, the pain of making minor business rule and UI tweaks,
the fear of adding new features because the data access layers, business rules,
and UI’s were all entangled.
After doing it wrong once, ok maybe more than once (many
years ago), then doing it better with a generalized automation API (but still 2
tier, still hand coding SQL statements), I felt that I finally acquired enough
experience to do it right.
What Is The Right Way?
The right way for me is:
·
In General:
o
The client should be generic—any application specific stuff is
done as plug-ins
o
The server should be generic—any application specific stuff is
done as plug-ins
o
Centralized transaction points for traceability
o
Small client API easily unit tested
o
Small middleware features easily unit tested
o
Server architecture implemented as “services” with interfaces
·
The communication layer:
o
Should be as lightweight as possible (no heavy .NET
serialization).
o
Should be secure—asymmetric keys
·
The middleware should:
o
Serve the client forms and reports—makes it easy to update all
clients without stopping the client
o
Use virtualized views (not SQL views) so that it can manage
view-based CRUD operations
o
Provide a mechanism to write server-side business rules triggered
on transactions-- There are several advantages to doing this in the middleware
rather than in the DB (flexibility, easily overridden [merging], unlimited
capability [launch apps, etc], version control the source [DB’s are just getting
to that point], traceable execution…)
o
Generate SQL automatically from the schema
o
Automate table dependencies with regards to CRUD operations, using
the schema to determine insert order, cascading deletes, etc.
o
Implement extended features, such as using a delete flag to mark a
record as deleted rather than deleting the row
o
Robust—catch exceptions and pass them to the client
o
Instrumented—log communications, transactions, exceptions,
business rule triggers
·
The client:
o
Derive from platform API controls—allows me to add necessary
automation to the UI controls
o
Client API platform agnostic (no WinForm dependencies). Interface
used to implement client platform specific functionality—this allows me to
implement console, WinForm, and Web-based applications easily
o
No data access layer in the client—the client communicates to the
middleware for all DB operations
o
No ORM—the client automates databinding without the use of ORM
o
Robust—catch exceptions and execute predefined workflow for
handling and reporting errors
o
Instrumented—log workflow events, communications, exceptions
·
Forms:
o
Client forms should be in XML—makes it platform neutral (including
implementing as a web app)
·
Reports:
o
Report definitions persisted in XML on the server
o
Can be served to the client to run locally
o
Can be run at the server and the resulting output sent to the
client (for web apps)
·
Scripted Workflows (client side):
o
Expressed in XML
o
Functionality can be changed at the server and propagated to
clients automatically
o
Decouples layers—workflow implements a mediator between disparate
objects
o
Exposes common operations—100% of typical operations can be
handled by workflow automation
o
Provide mechanism for plug-ins to expose methods callable by the
script
·
Scripted State Management:
o
On the list to implement
o
Manage UI state
o
Manage application state
·
ORM:
o
Support generation of classes from view specification—used by
server and client-side business rules if necessary.
·
Start with tools—so we’re not editing XML:
o
Schema designer
o
Form designer (includes workflow and state definition)
o
Report designer
·
Security:
o
Role based menu permissions
o
Role based UI control state (visible, enabled)
o
Role based data access (not implemented)
·
Compromises:
o
All tables have a single PK
o
PK is GUID
o
XML merge not yet supported
o
Role-based security is currently weak, implementation may need to
be revisted
How Do We Start?
We start from two ends more or less simultaneously—the
schema and the client UI.
The Schema
The schema actually isn’t necessary. Interacx can be used
a form server without any associated DB. A DB is usually associated with a
client-server application. The schema consists of two parts—table definitions
and view definitions.
Table Definitions
The tables define the optimal way for the DB to manage the
user data requirements.
View Definitions
The views define the optimal way to combine the tables into
different associations that are suitable for visualization at the client and/or
manipulating data via business rules. All server operations against the
database are done with views. Tables are never directly accessed. The client
exposes only view-based operations. This leverages .NET’s DataView
capabilities, which are quite useful.
Schema Management
Interacx stores the schema on the server as an XML file.
The server uses the schame for SQL generation. The client requests the schema
and uses it for validation and default value automation. The schema is DB
agnostic.
The Client UI
Obviously, some applications don’t have a UI, or at
minimum, are a client console app. In this case, there are no forms to define,
but the client application might still want to take advantage of the scripted
workflow as a mediator pattern for managing plug-ins.
Typically, the client has a UI consisting of some number of
forms. The goal of the Interacx client is to automate, as fully as possible,
the visualization of that data. This includes data binding, row cursor
management, validation, persistence and rollbacks. By automating these tasks,
they alleviate the programmer from the drudgery of managing these tasks in code
and provide a centralized, provably correct (unit tested) automation
architecture.
Form Layout
The UI consists of a form with controls, a menubar, a
statusbar, a workflow and a state machine. Any one of these are of course
optional.
Controls
Controls are derived from the .NET controls, so that I can
add the code necessary for the automation engine. In many cases, this amounts
to basically nothing at all, in other cases it can be a fair amount of code.
One of the decisions I made was to go with a stand-alone
designer that is not based on the Visual Studio designer. I did for two
reasons: I’d like to ability to port the designer to other platforms, and I
didn’t want to be tied to the vagaries of Microsoft’s designer and frequent
changes. Yes, the Visual Studio designer in VS 2005 is really good looking, but
the designer is such an integral aspect of Interacx, tying it to .NET’s designer
support seemed like the wrong direction. Then again, there’s no reason that a
.NET-based designer couldn’t be used. Incidentally, I use the same architecture
(which I’ve written an article about) for the schema, form, and report
designers.
I also wanted to limit the number of properties exposed in
the designer. For one thing, with the automation framework, one has to be
careful as to what properties are exposed—some may break the automation (such as
allowing the user to bind a control to a data source—a definite wrong thing
to do) and others may not be supported by the automation framework (or
should be supported intelligently rather than the rather coarse way properties
are handled in .NET). Exposing specific properties also means that it’s easier
to port the control to another platform—not every one of 500 properties needs to
be implemented!
Workflows
Workflows are one of the key aspects of Interacx. The
workflow service is like a plug-in manager. The client workflow service
provides a variety of automation methods for loading and saving data, binding
that data to controls, and managing the transaction of those controls. In
addition, client-side plug-ins can expose methods that become accessible to the
workflow service. A large number of forms can be managed entirely with
workflows, including undo/redo, sandboxing, and master-detail management.
Workflows are triggered by UI events from controls like
buttons. The programmer does not write code for wiring up a UI event to some
processing algorithm. Instead, the event is wired up to a workflow. Among
other things, this creates the possibility of running the application in a web
form, where a UI event posts a callback to the web server which executes the
workflow. Or, in a more exotic scenario, the workflow functions are implemented
in JavaScript (perhaps even dynamically) and “Ajaxed”.
State Machine
Not implemented (a separate state service currently
exists). The purpose of the state machine is two-fold. To manage the UI state,
mainly control visibility and edit state, and to manage application-specific
state with which a plug-in would interact.
Decision Graph
Not implemented (a separate decision graph service
currently exists). The purpose of the decision graph is to externalize complex
decision rules that determine the application state, state transition, or
workflow event.
Transaction Management
The heart of Interacx is a transaction manager that logs
all DataTable transactions. I spent a lot of time researching and building this
component so that it can accurately log field and row changes. A subset of the
transaction manager supports undo/redo capability, a very nice feature that
allows the client application to feel like a “real” application rather than that
feeling you usually get, that you’re closely tied to a database.
Sandboxing Management
Sandboxing is another feature that I spent a lot of time
on. The idea is to allow the UI to look like a typical application with “OK”
and “Cancel” buttons rather than a DB application where a field change is
immediately committed to the DB, especially when changing the row cursor.
Sandboxing lets the application accumulate all the transactions and post them
when the user clicks on “OK”, and of course they can be completely discarded
when the user clicks on “Cancel”. Sandboxing is not something that is required
when creating a Form—it’s up to the application designer and the user
requirements as to whether the form (or a section of the form) should be
sandboxed.
Conclusion
Interacx is more than a form server and more than an SQL
generator. It encorporates a variety of design patterns to provide the
programmer with considerable automation in developing a sophisticated
client-server application—plugins, workflows, UI data management, transaction
management, communication, and security.
Marc |