Hacker News new | ask | show | jobs
by darrencauthon 4906 days ago
He wrote: "As much static checking as possible: Static checking is good. Did you ever write a larger piece of code in one go, compiled it and it produced tons of errors? All these error would still be there, if you would not have static checking. You err much more than you think."

I think he errors much more than he really thinks. If errors are what he's truly trying to avoid, he'd be more focused on unit testing and TDD than passing syntax.

Descriptions like his make me wonder how many static typing proponents have actually spent any legitimate amount coding in a dynamic language for a production application. It seems all scary to code applications without a big IDE, but I promise that it's possible and a lot of people make it work.

3 comments

Java developer: "How can you code without an IDE?"

non-Java developers: "How can you code in fucking Java?"

I write Java in Vim on occasion.

I think I'm broken.

I'm a bad person: this made me spit-take.
FTFY

Java developer: "How can you code without a fucking IDE?"

Non-Java developers: "How can you fucking code in Java?"

Type systems are a little more than just syntax. Static analysis can identify unreachable sections of code, for instance, which will often indicate a bug.

Unit tests cannot prove correctness, only provide a finite set of ways in which the program /isn't/ wrong. (having said that, they're definitely useful)

And above all, he's talking about his ideal programming language. Test coverage is the domain of the programmer. There's very little you can put in a language spec to improve test quality.

For the record, I'm a static typing proponent, and I do most of my coding in vim; I only use an IDE when I /have/ to (I use C# at work). I think a lot of people assume static typing necessarily means very verbose languages like Java, which isn't at all true. My ideal solution is some combination of type inference and optional typing that I haven't quite arrived at yet. I like being able to whip up a quick program without worrying about manual type annotations, but it's nice to be explicit about expected types in an API for instance.

"There's very little you can put in a language spec to improve test quality"

You could require presence of unit tests with 100% code coverage (compile both in memory, run unit tests, write object file if 100% coverage)

I'm pretty sure it would drive people crazy, though, and would have them write almost meaningless tests. 100% coverage isn't enough, either.

As I said, very little that can improve test quality. :)

Good to brainstorm though. But in my experience, anything that breaks flow (like those languages that refuse to compile if there's unused code, even if you've just commented something out for debugging) is a bad idea. Often it's nicest just to write the code, then write the unit tests once you've got the core idea down, rather than having to alternate between them at high frequencies.

OK, try #2:

Loosen the unit test restrictions to just require that edge cases for function preconditions are tested. For example, a precondition 'x>3' would require a test calling a function the function with x=4 and one with x=MAXINT (if x is an int) or with x=nextFloat(3) and one with x=MAXFLOAT (if x is a float)

Ideally, the language would require gets for all edge conditions, but doing that is impossible. Instead, specify something similar to what Java does for 'variables must be provably initialized before use' to find easily detectable (in some sense) edge cases.

Also, allow the IDE to run and debug unit test code before it complies with the rules.

Keep the rule 'never write an object file that can be used outside of the IDE until the code passes tests'.

I think I could find such restrictions useful, if I were writing pacemaker software or something similarly critical.

If you find that too restricting, also allow debugging non-unit tet code from the debugger.

I like the idea of automatically generating a set of test cases, but requiring you to fill out the tests. Even better if I can run

    my-lang --gen-test-cases input.lang
and it outputs stub tests for the edge cases.
I think that static and dynamic type systems are classic incommensurable goods [1]. There's no way to pick between them based on some sort of value calculus; you just have to toss your hat in one ring or the other and live with the weaknesses as well as the strengths of your chosen approach.

[1] http://plato.stanford.edu/entries/value-incommensurable

I think people pick dynamic more often because of the reward schedule. Dynamic languages don't dish out as many errors upfront; most of the time it'll "work"-as-written. Immediate positive feedback.

Meanwhile the static typing compiler is spitting grumpy errors about some nitpicktastic piece of fluff it spotted. Immediate negative feedback.

So given the weekend-new-language thing, which example leaves a better impression?

Basically -- generalising enormously -- dynamic languages reward in the short term and punish in the long term; static languages are the opposite.

But human cognition is dreadful at long term prediction or comparison. So static languages will always be underrepresented unless, I dunno, Haskell compilers start doling out XP for fixing errors in your code.

But the overall calculus, in terms of, say, "productivity" (which is the hand-waviest of hand-waveries) is going to zero out. Or at least, that's my contention, based on these facts (∅) and twenty years of opinion and anecdote.
The problem is that the hand-waving could conceal a lot of useful variables -- and different people will care about different variables.

So one variable might be "time to customer value", and dynamic languages have been steadily dominating this space. But another variable might be "lifetime cost of defects" and static languages might come out in front by simply precluding many classes of defect.

And just like that we're back to trading off the long term and short term.