A few weeks ago, I shared the RemoveSpecialCharsExceptQuote AmpersandApostropheOpenBracket CloseBracketCommaHyphenFull StopCommaForwardSlash() method that Paul G. was forced to implement by his superior. Now this may come as a surprise, but there were a few more "oddities" at that organization. And shortly after leaving the longest-three-months-of-his-life contract, Paul was nice enough to share some more of them.
"The job interview went pretty well," Paul wrote, "everyone was pretty level-headed and seemed to have a pretty strong grasp of .NET and web technologies. Their description of the core application was like any other ASP.NET app: a Web Server communicated to a Database Server via ADO.NET and used a handful of Web Services. It seemed like a great fit."
However, after signing the contract and turning up to work, Paul got a slightly different impression about their system. His first clue was that everyone simply referred to it as The Beast. And for good reason. The Beast sported it all:
AJAX? Check.
Code Generation? Check.
Multi-megabyte “Business Logic” Configuration Files? Check.
Web Services? Check.
.NET Remoting? Check.
Message Queuing? Check.
Home-Built “Enterprise Framework”? Check.
Custom wrapper/abstraction layer for ADO.NET? Check.
Windows Services? Check.
The use of the word “Factory” in at least half of the class names? Check.
Worker threads, processors, semaphores, mutexes? Check.
As for what The Beast actually does? It’s an information system used by a few hundred employees across the world to process orders. Sure, it may not seem like much, but it does it oh-so elegantly. Following is the life cycle of a simple request from an end user.
- User enters some data into a few form fields and hits the "Save" button.
- Custom AJAX/JavaScript framework captures all fields into an XML document and sends to a webservice via an XmlHttp request
- Web service code creates a graph of "business entity objects"
- Objects are serialized into an XML document through a custom serialization engine
- XML document is converted to a string and set to one of three back-end web services methods: Update, Get, or Delete. Each method takes in a single string parameter called "dataXml."
- Back-end webservice converts the string to an XML Document and uses XPath to find out the class name
- Via an seperate XML configuration file, locate which IFactory implementation to use for the particular class
- Load up an instance the correct IFactory implementer via Reflection
- Call IFactory.CreateObject
- Determine the object's type via a large case statement
- Read another XML configuration file to determine which remoting service should be used for the object's type
- Binary serialize the object
- Call the 'Processor' remoting service, hosted within its own Windows service
- Queue the request in the remoting service
- Worker process reads from the queue and loads the incoming request
- Worker process looks at the request type using an XML mapping file, then routes the request through to the DatabaseAdapter remoting service
- Database remoting service moves incoming request to a work queue
- Worker thread reads from the queue
- Incoming request is inspected, and the object deserialized back into its original type
- An XML file that maps objects to stored procedures is loaded and read for a list of stored procedures to call
- Create hashtables, arraylists, stored procedure parameters, etc. via Reflection
- Load information into a custom ADO.NET wrapper
- Run the stored procedure
- Return query results in XML
Paul has since left the position, discouraged by the complexity of making what would otherwise be simple fixes and updates. Adding a field to a form would affect a number of steps of this process, not to mention all of the XML files that would have to be updated. Sadly, he never had the opportunity to add another layer, you know, for even more extensibility.