Kenneth Ismert
kismert at gmail.com
Tue Apr 12 10:38:39 CDT 2011
>Charlotte Foust: > I have to say, that I would put those module level functions into a > utility class and call the class method. I don't like calling module > level stuff from a class. The built in things you call are already > part of a library/dll so it isn't the same. But if they are just utility functions, why go through the effort of instantiating a class, when you can just call it directly in a module? If a block of code doesn't require state, why should it be in a class? As long as you write side-effect-free functions, you can write libraries that work just as well as the built-in stuff. > jwcolby: > Do you program in .Net? Everything is an object. There is > no "module", though there can be static classes / functions. > I haven't done a poll, but I doubt seriously that anyone uses > your paradigm in .net. Static classes would work just fine for function libraries -- they meet the criteria of being globally available, and not requiring instantiation. You can use Namespaces to group and name function libraries, as well. > Shamil Salakhetdinov > http://fsharp.net ? F# is one of the most interesting .NET languages for me. I dabbled with Nemerle years ago, which had all kinds of Lispy features, but it doesn't seem to be very actively developed now. > No, wait - in fact VB.NET <http://vb.net/> and C# do support first-order > functional programming paradigms (LINQ and related stuff...) > http://www.info.ucl.ac.be/~pvr/paradigms.html > And here they say that MS Excel is a kind of functional > programming environment > http://en.wikipedia.org/wiki/Functional_programming > So you should know and use them for quite some time already - > foundations of functional programming paradigm... :) Having functions as first-class data types (like strings, doubles, etc) turns out to be very handy. The Lisp idea of closures is fundamental to getting Javascript to do lots of useful things. Test-driven programming comes from loosely-typed languages like Lisp and Python. It is a way to define and enforce function, just contracts in Eiffel. VBA is not a very capable language, but you can directly use most of these ideas, and approximate and simulate others in a more-or-less satisfactory way. You can treat VBA as a loosely-typed, partly functional, test-driven programming language, and get tangible benefits. -Ken ---------- Forwarded message ---------- > From: Kenneth Ismert <kismert at gmail.com> > To: accessd at databaseadvisors.com > Date: Mon, 11 Apr 2011 15:09:32 -0500 > Subject: Re: [AccessD] AccessD Digest, Vol 98, Issue 7 > John, > > 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". > > > > It is always possible to over-factor, and merge two similar pieces of code > together that really should be separate. In that case, you factor the code > back into multiple pieces, and correct the dependencies. > > > > 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. > > > > I would submit that calling side-effect free functions from a class does > not > pierce the black box. The important things, state and access, are protected > by the class. But the function can be anywhere: built-in VBA functions, > Access application methods, or DAO library calls. You undoubtedly call > these > functions from within your classes. > > > > 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. > > > > Test cases replace questionability with a guarantee of proper function. The > function shouldn't define what it does -- the test cases should. If changes > to a function break a test, then you know immediately that there is a > problem. Functional unit testing guards against changes that would break > dependent code. > > I haven't found a reason why classes can't rely on properly crafted and > tested module-level functions. > > -Ken > > > > > > 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 >