Peter Bex wrote:
On Thu, Dec 14, 2006 at 04:45:11AM -0800, Brandon J. Van Every wrote:
Some tests need additional code for support (setting
things up in a particular way etc). Why would one want to put all that
code (which may be twice as big as the code itself, or even bigger, if done
properly) in one huge file?
You do it if you want your code to actually work, and you think it's
better to run the automated tests than to pay someone $XX/hour
after-the-fact to show you your bugs.
I know and understand why to use tests. I'm not opposed to tests,
but I am opposed to lumping the tests in with the main code.
I'd much rather just keep the code clean and put the tests in
another file.
Well, I question why we have files. We have historical reasons for it;
all of our text editors are built in terms of them. But a program is
really just one big database of stuff, and it might make more sense to
have it all uniformly accessed and searched, rather than being cobbled
across a filesystem.
Thus I am saying, "why should it appear together" vs. "why should it
appear apart," is pretty arbitrary and historical. If one regarded the
program as a database, then either is just a view of the database.
Inline documentation is useful to the reader,
Agreed.
and so are contracts since
they describe the specification a function should adhere to.
Only if those specifications are terse, legible, and universal enough to
describe nearly any class of problem that needs specification. I have
my doubts, but I haven't tried this paradigm. I suspect my eyes will
glaze over, and that deciphering contracts isn't much better than
deciphering simple tests.
Tests
don't say shit. They're a very low-level and nonsemantic way of
groping around to ensure your corner cases are covered.
Depends on the test. I think the comments are what help. I don't care
what kind of code someone writes, it's gonna make my eyes glaze over.
Contracts
are more semantic and declarative, so they tell you more about
what type of input is expected.
Declarative styles are not panacea. Some problems are better specified
imperatively. Sometimes you really want to know that "A happens, then B
happens, then C happens" and it's easier to debug.
What would you prefer?
(define/contract (+ a b)
((is-natnum a)
(is-natnum b)
(result-natnum))
(if (= 0 a) b (+ (sub1 a) (add1 b))))
(define/test (+ a b)
((throws negativeerror (+ -1 1))
(throws negativeerror (+ 1 -1))
(= 1 (+ 0 1))
(= 1 (+ 1 0))
(= 2 (+ 1 1))
(= 0 (+ 0 0))
(if (= 0 a) b (+ (sub1 a) (add1 b)))))
The latter. Because I'm probably implementing a bit twiddling
optimization algorithm, and I need to know exactly what's happening as
the code converts to machine instructions. When you state a preference
for declarative interfaces, you are implicitly stating you don't want to
be bothered with the implementation details. That you prefer abstract
problems. Now that may have its place in various problem domains, but
not typically in mine.
As you can see, proper testing often results in bigger code.
Bigger is fine. I'm interested in *clearer*. Declarative may be more
terse, but that doesn't make it more clear. And for some problems,
declarative makes it verbose, if you actually want A --> B --> C.
Cheer,
Brandon Van Every
_______________________________________________
Chicken-users mailing list
Chicken-users@nongnu.org
http://lists.nongnu.org/mailman/listinfo/chicken-users