Kenneth Ismert
kismert at gmail.com
Mon Apr 11 12:10:29 CDT 2011
John, All: I'm going to expand a little on what I'm trying to get at. This post really isn't advice on what you should do. And it certainly isn't criticism. I have been returning to the old Lisp idea of functional programming: libraries of functions that act only on their inputs and only return a result. The goal is 'side-effect-free' -- inputs are NEVER modified, and external variables are never referenced. If a function needs to return complex information, it returns either a type or an object. Database functions unavoidably have side-effects, but these are regarded as 'external' to the code, and are explicitly documented. The thing that surprised me was how well libraries play with objects. Libraries provide discrete, testable chunks of code that support any instance. Libraries separate functions into common-sense groups. Classes provide an instance wrapper over the libraries, stringing functions together to support the application. Plus, it is pretty easy to convert classes to this scheme while maintaining compatibility. The advantages became apparent when I refactored some of my early monolithic classes. These large, 'kitchen sink' classes had dozens of methods which mixed database, business, and application functionality. They were unwieldy, hard-to-understand, and hard-to-extend. I simply copied the class into a module, stripped out the instance stuff (properties and module-level variables), and turned the methods into side-effect-free functions. I then stripped out the code within the original class methods, turning them into wrappers calling library functions with their instance variables. The result: classes become lightweight, making their functionality much more obvious. Compatibility is maintained, but the new system is much easier to refactor and extend. The class on-top-of function approach is also a good answer to those who want to re-use your code, but can't because they need some method that is marked private in a class. They typically demand that all methods be made public, which is usually silly because the class designer has good reasons for limiting the public visibility of certain methods or properties. But with a function library, you can have your cake and eat it, too. Classes hold the instance information, and interact with libraries in an instance-safe way, because the functions never modify their inputs. Others with different needs can call the functions directly, or write their own classes. Heck, I even find myself cramped by my own classes at times, and having the option to call underlying functions directly has benefited me. Writing test code for functions is much easier than for complex class systems. Test code provides reasonable proof of reliability. Reliable complexity can only be built out of small, simple, understandable, and testable pieces. -Ken > ---------- Forwarded message ---------- > From: Kenneth Ismert <kismert at gmail.com> > To: accessd at databaseadvisors.com > Date: Wed, 6 Apr 2011 15:13:46 -0500 > Subject: Re: [AccessD] Autonumber when? > > > > jwcolby > > ... > > The code needs to work whether going to an MDB or SQL BE. The code works > > fine for an MDB BE but fails for a SQL BE. > > ... > > > > John, > > This is probably what you are trying to avoid, but I'll say it anyway: > > You should write separate code to handle the MDB and SQL Server BEs. > > First, the obvious: Jet and SQL Server are very different. > * It is unlikely that this is the only variation you will have to account > for throughout your code > * Variations in code make it harder to test > * When you do want to use SQL Server-specific features, like stored > procedures, you will have to split the code anyway > * I have a personal distaste of "On Error Resume Next" coding, which I use > only for object cleanup code where there is literally nothing to raise an > error to. > > All told, the cost and effort to make a large existing code base generic > will likely exceed the cost of just splitting it neatly into libraries that > support each database type. > > Plus, you get more modular, flexible, testable code. > > Again, this is what you are trying to avoid, but I felt I should say it, > anyway. > > -Ken > > > > ---------- Forwarded message ---------- > From: jwcolby <jwcolby at colbyconsulting.com> > To: Access Developers discussion and problem solving < > accessd at databaseadvisors.com> > Date: Wed, 06 Apr 2011 16:38:13 -0400 > Subject: Re: [AccessD] Autonumber when? > I hear you Ken. > > I have written a framework for MDB BEs. It is very large, and has tons of > functionality, and was never intended to run against SQL Server simply > because nobody was using that back when I wrote it. > > Now I am trying to use it for a SQL Server back end. It is not just a > simple case of "write a library for this and a library for that. > Additionally I need it to work where this table (or set of tables) is kept > in an MDB and that one is moved to SQL. > > I write frameworks. The framework does a ton of stuff which is handled > automatically. It handles the not in list and the dbl click of combos for > example. The dbl click of a combo opens a form and moves to the record that > the combo is displaying. Classes instantiate classes which instantiate > classes. > > I am just not sure that "writing separate libs" is a viable option. It > would mean a complete rewrite of the framework and then a complete rewrite > of the FE. > > John W. Colby > www.ColbyConsulting.com > > >