jwcolby
jwcolby at colbyconsulting.com
Mon Apr 11 12:47:23 CDT 2011
Ken, I understand the reasoning and all however... because the code is no longer contained within the object that needs it, you now open yourself up to the old "I need to modify this method... oops... that change breaks something else that uses the code". Class programming exists for a reason. Placing code in the object that needs the code exists for a reason. Black box programming exists for a reason. The reason in many cases is to prevent exactly this kind of interaction when we accidentally change a piece of code used in many places and break one of those places. Yes, there are instances where lots of different things need the exact same code, and yes, I have been known to call module functions from classes, but it truly is a questionable practice in most cases. John W. Colby www.ColbyConsulting.com On 4/11/2011 1:10 PM, Kenneth Ismert wrote: > 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 >> >> >>