jwcolby
jwcolby at colbyconsulting.com
Mon Apr 11 15:36:04 CDT 2011
> I haven't found a reason why classes can't rely on properly crafted and tested module-level functions. 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. John W. Colby www.ColbyConsulting.com On 4/11/2011 4:09 PM, Kenneth Ismert wrote: > 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 >>> >>>