6 ms·
Folks, please do not fall into the simple error of arguing whether Haskell’s typing beats Hungarian notation. This would be bikeshedding. The safe/unsafe string
by raganwald 15y ago
Folks, please do not fall into the simple error of arguing whether Haskell’s typing beats Hungarian notation. This would be bikeshedding. The safe/unsafe strings are given as an example, the larger point he is making is about using coding conventions to highlight potential semantic errors.
Every program is going to have some kind of semantic problem that cannot easily be fixed with compile-time analysis. Unsafe strings in web applications are merely one example for one class of programs written in one class of languages. If you grasp what he’s saying about coding conventions, ignore the example.
So to his actual point: Do you agree with my contention that there are always going to be some semantically wrong bits of code that cannot be automatically detected by the compiler, or that it is awkward to do so?
If so, do you think coding conventions help more than they hinder? In other words, do they increase code safety without imposing too much of a burden on readability?
- kolektiv 15y agoOK, reasonable point, I had only mentioned that example in another reply because that was the one he used. Do I agree that there will always be semantically wrong bits of code that can't be detected by a compiler (whether as part of a type system or otherwise)? I'm not sure I do. OK, sure, it's probably possible to come up with some contrived examples that fit the case, but generally? No, I think that most problems are more tractable if looked at as a language design issue (be that literal language design, some form of internal DSL, or other) than as a convention issue. And surely bringing up something like Haskell is germane? The article implies that this is the best/only/right way of dealing with issues like this, when that definitely isn't true for languages with a different/stronger type system, as one case. Of course, this is pure opinion and supposition on my part - I suspect a proof either way is NP-BloodyImpossible. I do feel like coding conventions such as those he suggests make code harder to read, even if only a little bit. And that's ignoring IDE support as well - I feel the same if I'm in Emacs. If there are enough things in scope that I can't hold in my head the relevant [meta] information about them for that usage, that's a problem for me, probably of quite a different kind.
- raganwald 15y agoIf there are enough things in scope that I can't hold in my head the relevant [meta] information about them for that usage, that's a problem for me, probably of quite a different kind. This is a brilliant observation, thanks. Reminds me of Yegge’s observations about large codebases being like dirt, and the more dirt you have, the more machinery you need for pushing dirt around, and the more people, and the more systems for managing people and dirt-moving machines, ... And the better way forward might simply be to have less dirt. http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.html http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.ht...
- vilya 15y ago> Do I agree that there will always be semantically wrong bits of code that can't be detected by a compiler (whether as part of a type system or otherwise)? I'm not sure I do. Here's a very simple counterexample that I don't believe it's possible for a compiler to detect: writing a - b when you should have written b - a. More generally, that applies to any non-commutative function which takes two arguments of the same type. This is also a good example of where a coding convention could help: if those variables had been named more descriptively it would have been much easier to see which way around they should go.
- ajanuary 15y agoI'm sure I'm just missing something, but I'm struggling to come up with a reasonable case where you couldn't just have a and b be different types and provide an operator for typeof a - typeof b but not typeof b - typeof a (or vice-versa). Of course, that would upset Joel on account of not knowing what - did without knowing the types.
- masklinn 15y agoDepends what you mean by "reasonable" I'm guessing. Manually encoding a semantic analysis would have a very high overhead, and you might be able to do it via dependent types instead (not sure though, they tend to hurt my brain when I try to actually understand them), but I don't think they're considered practical (yet).
- perlgeek 15y ago> Every program is going to have some kind of semantic problem that cannot easily be fixed with compile-time analysis. Unsafe strings in web applications are merely one example for one class of programs written in one class of languages. If you grasp what he’s saying about coding conventions, ignore the example. I disagree. If the example has a better solution (and in some other comment here I argue it does, though it's not at compile time), it's well worth looking if that solution could be transferred to other problem domains that could be used as examples instead. The deeper issue is that naming conventions are a kind of automatism, and humans shouldn't be bothered with that, they are simply not very good with this type of automatism. For repetitive patterns, automated solutions should be used. Advocating these repetitive type prefixes reminds me of the classical Design Patterns -- they might be the best option if you're stuck with one set of tools, but IMHO it's important to take a broader view and see if there are maybe other tools that can alleviate the need of such patterns. And indeed, in the case of the classical Design Patterns, there are. More powerful languages render some of them obsolete, or turn them into trivial 3 line solutions that you can hardly call "patterns" anymore.
- raganwald 15y agoThe deeper issue is that naming conventions are a kind of automatism, and humans shouldn't be bothered with that, they are simply not very good with this type of automatism. For repetitive patterns, automated solutions should be used. I agree, and this is what I am trying to get at with my comment: The deeper issue of whether naming conventions are a good way to make code better is much more interesting and important than the question of how to sanitize strings in a web app.
- endlessvoid94 15y ago> If so, do you think coding conventions help more than they hinder? In other words, do they increase code safety without imposing too much of a burden on readability? I think there's a relationship between the number of people working on a codebase and how effective/burdensome coding conventions are. The more people on a project, the more friction there will be (at first) getting everyone to adhere to conventions. And this assumes there are code reviews in place. I think this curve happens starting much lower than you'd think, too. Good hackers will be picky about conventions as soon as a codebase reaches ~4 hackers. Thoughts?
- yesbabyyes 15y agoI think this curve happens starting much lower than you'd think, too. Good hackers will be picky about conventions as soon as a codebase reaches ~4 hackers. I don't think so. I wouldn't have any problems working with GNU Style or Apps Hungarian if it was an interesting project.
- tedunangst 15y agoI would much rather work on a project with just about any convention, no matter how disagreeable, than a project with four different pet conventions that varies from file to file.
- endlessvoid94 15y agoYep, me too.
- stonemetal 15y agoThe right set of coding conventions can improve readability and write ability. Like when he is talking about the conversion functions in the article, the cognitive load of XfromY is quite low. You don't have to consult the documentation to find out what it is called, or how it works, etc. You don't have to think about the name when writing it or how it should work. In a setting without conventions that function could have a dozen names, another dozen ways to arrange the args, and do error handling. There would be no way you would call it with out consulting the docs. As far as encoding semantics in to the type system, it would be great and help eliminate bugs, it wouldn't do a single thing to reduce the mental overhead out lined above. Basically they solve the same problem by two different paths, one makes doing the right thing easy, the other makes doing the wrong thing hard. Full semantic analysis probably isn't possible in a reasonable way, but catching the low hanging fruit should be possible.
- Dn_Ab 15y agoI think what the Haskell people are doing is mostly criticizing the way things are. They are saying instead of making do with a fudge that won't be followed nor applied consistently why not mechanize as much as possible into the tools? When there is no choice you must make do but amongst those with choice, why not look for better tools? Haskell monads have already been mentioned. I await easy to use dependent types and or statically verified contracts. But till then many powerful but relatively simple though different concepts can already be used today. These give static leverage over many semantic issues. Giving the act of building a program a flavour of the elegance in Euclid's Elements. As noted, monads are useful and available in any with parametric polymorphism or dynamic types * . Haskell has Generalized Algebraic Datatypes. Pattern Matching Views is available in Haskell,ocaml,f#, scala. predicate dispatch is mostly there in clojure. People should be doing as much as possible to reduce errors and mechanize as much as possible. *I'm aware monads become really powerful with higher kinds and that you give up some guarantees when you drop purity and even more when you go dynamic but it still remains a powerful and useful mechanism due to the body of theory backing it.
- JadeNB 15y ago> Giving the act of building a program a flavour of the elegance in Euclid's Elements. This is the most gorgeous description I have ever seen of this approach to programming.
- kisielk 15y agoTheoretically in a strongly and statically typed language like Haskell shouldn't it be possible to fix the safe/unsafe string problem by having separate a string type for unsanitized input? Not that I've tried this approach myself, but I'd be curious to hear from anyone who has.
- raganwald 15y agoYes I have implemented something like this and I still do this from time to time. For example, I don’t always use plain strings for things like SSNs/SINs and phone numbers, sometimes I create a brand new class. You can do this in any language today by boxing strings. In an “untyped” language like Ruby, you’ll get runtime errors if you try to use an UnsafeString where you expect a String, and in a statically typed language you’ll get a compiler error. Some languages make this easier than others, but the main problem is not whether you can use types or boxes to solve the problem. The main problem is that if you are using libraries/frameworks that doesn’t support your types or boxes, you still have to be careful to place boxing and unboxing code where your code interacts with the library. Taking a web framework as an example, if its template system expects PUS (plain unsafe strings) and it provides post parameters as PUS, it’s up to you to box things up so that your code never passes PUS straight through the system. I agree that once you box up a PUS it won’t get inserted into a template, but the pain point is that library authors don’t implement anything like this so you are going to have to deal with the rather broad interface between your code and almost every library that does something with a string. Which is not to say that types are or are not better than coding conventions, but rather to say that in theory types are an airtight solution in any language, but in practice there is still broad scope for human error thanks to libraries.
- eru 15y agoYes, that's possible in Haskell. And it's actually one of the canonical examples. And even in C you could wrap your (char*)s up in different structs. The typing overhead would be higher than in Haskell, though. (There's even a language extension to allow you to overload string literals. But you probably don't want that, because s = TaintedString "My string literal" is easier to read than: s :: TaintedString s = "My string literal" The overloading makes more sense for implementation details like using a different String implementation like ByteStrings instead of a linked list of Characters. You actually want to be able to see the semantic differences.)
- ori_b 15y agoI'd have to take some time to think. I'm not convinced that coding conventions can solve any semantic problems that a good type system couldn't also fix.
- ori_b 15y agoFollowing up, I'm almost certain that a rigorously followed coding convention is entirely equivalent to a sufficiently powerful type system. The coding conventions are statically fixed at compile time, and can therefore are decidable at compile time. One possible advantage that conventions have is that they can be easier to understand, and they can be transparently and painlessly broken when they don't make sense. In other words, they're equivalent to a weak (ie, can have holes punched in it), informal type system.
- kragen 15y ago> Do you agree with my contention that there are always going to be some semantically wrong bits of code that cannot be automatically detected by the compiler, or that it is awkward to do so? It seems to me that answering this question is more or less exactly "arguing whether Haskell’s typing beats Hungarian notation," although of course Haskell type systems aren’t the only possible alternative. For example, any number of templating systems in languages like Python use late-bound method calls and run-time type checks, instead of static typing, to avoid cross-site scripting errors. The problem, to me, is that Hungarian notation (and other coding conventions) only helps you detect semantic errors in cases where the errors can be detected by shallow, local analysis — exactly the kinds of errors that can be detected automatically by a program, either at compile-time or run-time. So, what do we do about the deeper errors? Well, I don't know. I don't think abandoning coding conventions is a solution — I still want the code I read to be written in a predictable style, so that the variation in it is semantically meaningful — but I don't think coding conventions can do a better job than software of detecting errors. However, if I were trying to write a GUI on a 1-MIPS machine with 1 MiB of RAM in the late 1980s, it might work better to do a bunch of that checking by hand (with Hungarian) than to try to invent a better programming language that does the checking for me automatically.