Subject: Re: Problem computing places (generalized references)? From: Erik Naggum <erik@naggum.no> Date: 25 Dec 2002 22:04:10 +0000 Newsgroups: comp.lang.lisp Message-ID: <3249842650899575@naggum.no> * Daniel P. Katz | This code works well enough, but I find myself dissatisfied by the | repetition of the logic represented by | | (if (node-foo node) | (query (node-foo node)) | (setf (node-foo node) (ask-answer))) | | in two of the cases. Could you explain why you find yourself dissatisfied by this? An argument against gratuitous abstraction is that apparently minor differences betray incidental similarity. The branches /are/ quite similar, but if that is the end of the story, leave it be. If you predict changes and adopt abstractions to simplify them, consider the consequenes of asymmetric changes. Speaking from years of experience, I predict the probability of symmetric changes (in the macro) to be below 1 in 1000. When you do make changes, you will either revert to the dissatisfying code and make straightforward changes or you will want to protect your abstraction investment and make an unnatural and more complex change that you will recognize as stupid and you will have another minor battle with yourself over which is the optimal form of expression, only wasting more time. The expert programmer intuitively recognizes code that needs tuning to improve system performance, after ample experience and mistakes. The novice believes his grasp of the computer and of his program will guide him intuitively as he decides to optimize his code, but the experience of his elders strongly suggests that he should not optimize inefficient algorithms and half-solutions, but learn more efficient algorithms and how to implement them correctly. Similarly for the writing process, but the novice believes benefits he can see are benefits to exploit regardless of the resources that will consume. The general problem is the metric for "better code". The naïve optimization may well improve something, but experienced programmers appreciate its costs and make a more balanced call on when to spend time on it. The novice programmer views his time as inconsequential compared to the quality of the code, which suggests a lack of focus on priorities. Habits adopted while still forming are hard to change when they shaped what one has become. The time you spend weighs heavier as you grow wiser; older programmers value their time over irrelevant perfection, and thereby attain relevant perfection sooner. You cannot get everything right at once, so set your priorities to maximize /overall/ success in finite time. Originally military disciplines now vital to business, logistics and triage embody the complex tasks of having the resources you need available as and when you need them and of spending them where they will maximize the end result. Novice programmers are lousy at both disciplines and their concept of the end result is fuzzy if they have one at all. Tragically, those who teach programming do not value their students' time, either, and encourage wastes on trivialities that make them feel good about local improvements at the cost of teaching the wrong values, lack of focus on the end result, and therefore no understanding of the process of achieving the optimal end results with minimal waste. I implore you to waste no more of your time on such trifle issues and instead appreciate that a simple cut and paste will save you time. If you absolutely have to make an abstraction before you can move on to more worthwhile tasks, make a local one with `macrolet´. A global macro with a general name like "process-node" which has such a limited scope makes your code harder to read. Experienced programmers will search for the purpose of this abstraction and as they find none other than fickle aesthetics, will wince at it. -- Erik Naggum, Oslo, Norway Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.