Re: Announcement: pretzel - a predicate library + call for suggestions
On 12 April 2011 04:31, Ken Wesson kwess...@gmail.com wrote: There's a difference between the program parsing the same *object* multiple times, and the program's own source code containing duplication! But there isn't any duplication: (defn present? [x] (not (string/blank? x))) (defn- parse-int [x] (try (-? x Integer/parseInt) (catch NumberFormatException _ nil))) (defn integer-string? [x] (boolean (parse-int x))) (defn over [n] (fn [x] (-? (parse-int x) ( n Unless you're asserting that calling parse-int twice is code duplication? Actually, nil is returned. And you're cheating. Your validate function is presumably as complex. The same information ends up in its docstring, or distributed among present?, email-address?, and the like. But as a developer who is using the API, why should I care what validations the validate-user applies, so long as those validations are correct? We seem to have different ideas about what complexity is at this point. My assertion is that the internal complexity of a function does not matter, but the complexity of its return values and arguments does. If we disagree on that fundamental point, we probably should just agree to disagree. And any function that validates range-limited integer inputs ends up checking the same four things. Yes, but not necessarily in a divisible fashion. I was not. I only claimed that forgetting anything *could* cause a security risk, depending on the system. Looks like I misinterpreted you, then. But, but, but. You made a universal statement that I've proven was wrong. You've basically admitted this by admitting that there are any exceptions at all to your universal rule. So, why keep arguing? What universal statement are you talking about? You made a blanket claim that deny-by-default is superior. Now you're misinterpreting me :) There may conceivably be a situation where deny-by-default is less secure than allow-by-default. However, I cannot think of such any such scenario, and I've never encountered or heard of any such scenario arising in practise. It's therefore my opinion that deny-by-default is the best option in at least 99% of cases. You're viewing it the wrong way. Once a new owner takes possession of the device, that new owner should decide its policy. If the old owner's policies keep intruding after that point, that's unauthorized. The new owner *should* be able to obliterate and replace any such policies. If they cannot, the dead hand of the old one has in effect intruded. That's a very strange definition of what unauthorised access constitutes. Assuming no-one (including the manufacturer) was able to access the device, I'd consider the device to be very secure - just utterly useless. In my experience, deny-by-default is the right answer in less than 100% of cases. I didn't say that. At least 99% is not necessarily less than 100%. In any case, I don't understand your objection. If you accept that in the majority of cases, deny-by-default is the best choice, then surely it's the best default security policy? - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Tue, Apr 12, 2011 at 6:34 AM, James Reeves jree...@weavejester.com wrote: On 12 April 2011 04:31, Ken Wesson kwess...@gmail.com wrote: There's a difference between the program parsing the same *object* multiple times, and the program's own source code containing duplication! But there isn't any duplication Don't be ridiculous. If you're putting that (chain ...) sexp of yours in every separate place where a field is checked for being an integer in a range, then that's duplication. And if you extract it into a function that just takes the endpoints as parameters (and maybe the error strings, or a map of these), then you have a compound function. (defn present? [x] (not (string/blank? x))) (defn- parse-int [x] (try (-? x Integer/parseInt) (catch NumberFormatException _ nil))) (defn integer-string? [x] (boolean (parse-int x))) (defn over [n] (fn [x] (-? (parse-int x) ( n Unless you're asserting that calling parse-int twice is code duplication? Way to not see the forest for the trees. That level isn't where the duplication is. It's at the level that calls these, or the level above that. Actually, nil is returned. And you're cheating. Your validate function is presumably as complex. The same information ends up in its docstring, or distributed among present?, email-address?, and the like. But as a developer who is using the API, why should I care what validations the validate-user applies, so long as those validations are correct? What? Now you're confusing the layers again. Presumably validate-user takes a structure and applies predicate tests and potentially generates error messages. That puts it at the same level as the *caller* of my not-int-in-range? function. So if you're comparing that with your validate-user, you're comparing apples and oranges. We seem to have different ideas about what complexity is at this point. No, just about *where* it is. And the difference seems to stem from confusion on your part that I'm beginning to think may even be intentional, sadly. And any function that validates range-limited integer inputs ends up checking the same four things. Yes, but not necessarily in a divisible fashion. Define divisible? The in-range check depends on there being an integer. The integer check depends on the field not being blank. The in-range check thus can't be divided out more than I've already done. Unless you make it the calling layer's responsibility to check for blank and for non-integer first, and that way lies that code duplication again, as the same pattern of sequential check-and-branch logic repeats everywhere where an integer has to be in some range. I was not. I only claimed that forgetting anything *could* cause a security risk, depending on the system. Looks like I misinterpreted you, then. For some odd reason that seems to be happening a lot lately. But, but, but. You made a universal statement that I've proven was wrong. You've basically admitted this by admitting that there are any exceptions at all to your universal rule. So, why keep arguing? What universal statement are you talking about? You made a blanket claim that deny-by-default is superior. Now you're misinterpreting me :) No I am not. There may conceivably be a situation where deny-by-default is less secure than allow-by-default. However Well, that makes a *slight* change from But. You're viewing it the wrong way. Once a new owner takes possession of the device, that new owner should decide its policy. If the old owner's policies keep intruding after that point, that's unauthorized. The new owner *should* be able to obliterate and replace any such policies. If they cannot, the dead hand of the old one has in effect intruded. That's a very strange definition of what unauthorised access constitutes. Now you're just going around in circles. I think we're just about done here. In my experience, deny-by-default is the right answer in less than 100% of cases. I didn't say that. Yes, you did. In any case, I don't understand your objection. You don't have to understand it. You just have to stop arguing around in circles. If you accept that in the majority of cases, deny-by-default is the best choice, then surely it's the best default security policy? For network-facing and/or multiple-user mission critical systems, yes. But its costs tend to outweigh its benefits for single-user personal devices and software in a lot of cases. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
All this stuff on complexity of validations is interesting, but my take on most of this (and especially on the pretzel functions) is that predicates should just test for validity, strictly if possible, and nothing else, since there are too many ways of combining these tests into more abstract functions for anyone to agree on and trying to do force these choices in the predicates themselves would make them less useful and more confusing. An input string of foobar is obviously not a number between 10 and 20, so whatever predicate you use to test for that should just return false. That not everybody here agrees on that indicates to me that people are trying to shove too much functionality into single tests/ predicates. I want simple, correct, well tested predicates that people can use. I'm trying NOT to make design decisions that can be made by the user of the library instead. IOW, how you combine tests should not be up to the code in this level of abstraction; it should be in the validation framework(s) that can be build on top of them. I've made my tentative choices about *that* in clj-decline, and if those don't turn out to be flexible enough for me I'll change them. If they turn out to be too cumbersome, I'll probably write some higher level abstractions on top of them. YMMV. Cheers, Joost. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 12 April 2011 12:02, Ken Wesson kwess...@gmail.com wrote: Don't be ridiculous. If you're putting that (chain ...) sexp of yours in every separate place where a field is checked for being an integer in a range, then that's duplication. And if you extract it into a function that just takes the endpoints as parameters (and maybe the error strings, or a map of these), then you have a compound function. I think our differences lie in when that compound function is constructed. My opinion is that you should only combine your validations when you are certain of all the parameters. Because only the end developer knows what messages should be used, it should be the end developer's responsibility to combine those validations. In your case, you're combining your validations *before* you know what the messages are, so your validation function then needs to be combined with an external map of error message. Both approaches amount to the same thing, but I prefer the former approach. It makes sense (to me) to combine functions only when they can be said to contain a combined purpose (e.g. to define the valid values of a particular type of object). In my experience, deny-by-default is the right answer in less than 100% of cases. I didn't say that. Yes, you did. If you're going to be childish, I don't think we should continue this. Less than 100% is not the same thing as at least 99%, but this is such a minor detail that we shouldn't be even talking about this at all. I have not deliberately misinterpreted anything you have said. You don't seem to disagree that deny-by-default is the most secure scheme in most scenarios, so I'm uncertain why you think this wouldn't be a sensible default. At this point, I don't believe we'll reconcile our differences, and your tone is becoming just a touch hostile. Let's end the discussion here. You have the option of adding in some last words to sum up your points, but this will be my final response to your messages on this subject. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Tue, Apr 12, 2011 at 8:05 AM, James Reeves jree...@weavejester.com wrote: On 12 April 2011 12:02, Ken Wesson kwess...@gmail.com wrote: Don't be ridiculous. If you're putting that (chain ...) sexp of yours in every separate place where a field is checked for being an integer in a range, then that's duplication. And if you extract it into a function that just takes the endpoints as parameters (and maybe the error strings, or a map of these), then you have a compound function. I think our differences lie in when that compound function is constructed. My opinion is that you should only combine your validations when you are certain of all the parameters. Because only the end developer knows what messages should be used, it should be the end developer's responsibility to combine those validations. That's silly in a number of common cases. For example, it will be very common to need a field to be an integer within a certain range. So it makes sense for the library to provide a single function for that very common case instead of every app developer having to reinvent the check it's not blank, check it's not non-integer, check it's not low, check it's not high wheel over and over again. In your case, you're combining your validations *before* you know what the messages are, so your validation function then needs to be combined with an external map of error message. So? I'm factoring out the logic that is common to all applications and leaving the application-specific details as parameters. Both approaches amount to the same thing, but I prefer the former approach. And I don't. I don't want to have to compose everything from ultra-primitive bits from scratch. If I did I wouldn't use a third-party library. In fact I'd probably code in ASM instead of Lisp. It makes sense (to me) to combine functions only when they can be said to contain a combined purpose (e.g. to define the valid values of a particular type of object). And combining is not empty and is an integer with is an integer in a certain range is NOT a combined purpose?! In my experience, deny-by-default is the right answer in less than 100% of cases. I didn't say that. Yes, you did. If you're going to be childish, I don't think we should continue this. If you're going to be childish, I don't think we should continue this. I have not deliberately misinterpreted anything you have said. Then you must be one of the most accident-prone people on the planet. :P You don't seem to disagree that deny-by-default is the most secure scheme in most scenarios Oh, but I do. Most scenarios are not large, mission-critical multi-user net-facing systems. Most scenarios are single-user personal software, internal-use-only stuff used by a small trusted group (e.g. internal tools used by a game company's 3 level designers), or one-offs for individual, personal use. so I'm uncertain why you think this wouldn't be a sensible default. We don't NEED a sensible default when anyone designing something should know before they write a single line of code whether it's going to be big and either net-facing or many-user! At this point, I don't believe we'll reconcile our differences, and your tone is becoming just a touch hostile. MY tone? You're the one who keeps coming back every couple of hours with a post full of innuendos that I'm in some way wrong, silly, or deficient. So far, you're the only one to have brushed close to engaging in name-calling in this thread (having twice said something about me was strange). Let's end the discussion here. Fine. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 12 April 2011 12:16, Joost jo...@zeekat.nl wrote: An input string of foobar is obviously not a number between 10 and 20, so whatever predicate you use to test for that should just return false. That not everybody here agrees on that indicates to me that people are trying to shove too much functionality into single tests/ predicates. I want simple, correct, well tested predicates that people can use. I'm trying NOT to make design decisions that can be made by the user of the library instead. I whole-heartedly agree with the sentiment; my only reservation is that it might make validating form data using those predicates a little more difficult to use in practise. I'm hoping you'll eventually prove me wrong, as your predicates seem to be the more correct way of doing things. But even if you don't, it would still make sense for me to base the validation functions in Valip on the more generic predicates in Pretzel. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 12 April 2011 22:04, Joost jo...@zeekat.nl wrote: For now, I think of the pretzel library as the lowest useful level of abstraction for input tests. And for low level abstractions, I prefer to place a higher value on correctness, extensibility, consistency and possibly even performance (in roughly that order) than ease of use from a direct programmer's stand point. I think I agree. It might be better to put those predicates in a numeric namespace or library that doesn't address strings at all, maybe relying on a conversion layer somewhere if your input is really string- based, or maybe to have string-based counterparts relying on the numeric tests. That's a good idea. Perhaps something like: (defn from-string [f] (comp f parse-number)) (from-string (in-range 1 10)) But with a better name than from-string. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 10 April 2011 22:24, Ken Wesson kwess...@gmail.com wrote: On Sun, Apr 10, 2011 at 1:37 PM, James Reeves jree...@weavejester.com wrote: By adding error messages to predicates, we tightly couple the validation error with the predicate, which in general is considered bad. However, this might be a valid compromise, but only if it improves readability. I showed two posts ago how to keep that decoupled. You decoupled the validation message (e.g. age is required) from the validation error (e.g. :blank), but validation error is still tightly coupled to your predicate. Putting it another way, I can represent this code: (age-invalid-en (not-int-in-range? age 1 120)) With four separate predicates: (validate thing [:age present? age is required] [:age integer-string? age must be a whole number] [:age (at-least 1) age must be at least 1] [:age (at-most 120) nobody is that old]) So your not-int-in-range? function is a compound function, made up of four simple functions. I think it's a bit subtler than that. On the face, I wouldn't disagree with that statement. But if you arrive at your security rules by two different procedures, one resulting set of rules might specify what-to-deny and be more secure than another that specifies what-to-allow. That's possible, but is there anything that indicates the predicates I've used so far are less secure than the validation functions you've used? And ultimately there's a mathematically equivalent what-to-allow set for any what-to-deny set, and vice versa, like a photograph and its negative. But if people are used to creating photographs, why change it around so they have to use the negative? - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Mon, Apr 11, 2011 at 3:09 AM, James Reeves jree...@weavejester.com wrote: On 10 April 2011 22:24, Ken Wesson kwess...@gmail.com wrote: On Sun, Apr 10, 2011 at 1:37 PM, James Reeves jree...@weavejester.com wrote: By adding error messages to predicates, we tightly couple the validation error with the predicate, which in general is considered bad. However, this might be a valid compromise, but only if it improves readability. I showed two posts ago how to keep that decoupled. You decoupled the validation message (e.g. age is required) from the validation error (e.g. :blank), but validation error is still tightly coupled to your predicate. Of course it is. Blank is blank. Putting it another way, I can represent this code: (age-invalid-en (not-int-in-range? age 1 120)) With four separate predicates: (validate thing [:age present? age is required] [:age integer-string? age must be a whole number] [:age (at-least 1) age must be at least 1] [:age (at-most 120) nobody is that old]) So your not-int-in-range? function is a compound function, made up of four simple functions. So? This whole discussion arose because some of them have preconditions, like at-least 1 not making sense for blank or non-integer input. I think it's a bit subtler than that. On the face, I wouldn't disagree with that statement. But if you arrive at your security rules by two different procedures, one resulting set of rules might specify what-to-deny and be more secure than another that specifies what-to-allow. That's possible, but is there anything that indicates the predicates I've used so far are less secure than the validation functions you've used? Is there anything that indicates they're more secure? And ultimately there's a mathematically equivalent what-to-allow set for any what-to-deny set, and vice versa, like a photograph and its negative. But if people are used to creating photographs, why change it around so they have to use the negative? If people are having a problem with the existing way, it's useful to suggest alternative ways of looking at the problem. Here, for instance, there was some difficulty regarding preconditions, and generating the right error message when more than one thing failed (e.g. it wasn't in the range 1 to 120 because it wasn't an integer at all). I just thought it might be helpful to look at things from another direction. Now we can all look at things from *both* directions. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 11 April 2011 08:31, Ken Wesson kwess...@gmail.com wrote: So your not-int-in-range? function is a compound function, made up of four simple functions. So? This whole discussion arose because some of them have preconditions, like at-least 1 not making sense for blank or non-integer input. Yes, but remember that I said I was looking for non-compound solutions. In my view, simple functions are more idiomatic Clojure. Is there anything that indicates they're more secure? I'd argue that encouraging people to think of what to allow is better than encouraging people to think of what to deny. You could also programmatically ensure that keys are invalid by default. If people are having a problem with the existing way, it's useful to suggest alternative ways of looking at the problem. Here, for instance, there was some difficulty regarding preconditions, and generating the right error message when more than one thing failed (e.g. it wasn't in the range 1 to 120 because it wasn't an integer at all). I just thought it might be helpful to look at things from another direction. Now we can all look at things from *both* directions. Sure, and I'm not saying there aren't clear advantages to having inverted validations. It's because your idea has merit that I'm taking the opposite side and arguing against it. If it turned out that I came to believe that the advantages to this approach outweighed any disadvantages, I'd whole-heartedly adopt the idea. For that reason, my current approach requires a vigorous defence. I'm certainly not saying you shouldn't have brought the idea up in the first place! I agree that it's useful to look at this problem from as many different angles as we can. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Mon, Apr 11, 2011 at 4:12 AM, James Reeves jree...@weavejester.com wrote: On 11 April 2011 08:31, Ken Wesson kwess...@gmail.com wrote: So your not-int-in-range? function is a compound function, made up of four simple functions. So? This whole discussion arose because some of them have preconditions, like at-least 1 not making sense for blank or non-integer input. Yes, but remember that I said I was looking for non-compound solutions. In my view, simple functions are more idiomatic Clojure. Mine were built up starting from very simple functions. Is there anything that indicates they're more secure? I'd argue that encouraging people to think of what to allow is better than encouraging people to think of what to deny. What is your basis for this? If people are having a problem with the existing way, it's useful to suggest alternative ways of looking at the problem. Here, for instance, there was some difficulty regarding preconditions, and generating the right error message when more than one thing failed (e.g. it wasn't in the range 1 to 120 because it wasn't an integer at all). I just thought it might be helpful to look at things from another direction. Now we can all look at things from *both* directions. Sure, and I'm not saying there aren't clear advantages to having inverted validations. Then why are you arguing as if you think I'm wrong about something? It's because your idea has merit that I'm taking the opposite side and arguing against it. If it turned out that I came to believe that the advantages to this approach outweighed any disadvantages, I'd whole-heartedly adopt the idea. For that reason, my current approach requires a vigorous defence. Ah. Devil's advocacy, then, or something like it? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
Hi, On 11 Apr., 10:43, Ken Wesson kwess...@gmail.com wrote: What is your basis for this? Because the phantasy of the average human being is quite limited. While a missed this is allowed might cause trouble, it doesn't compromise the system. A missed this is not allowed however will. Solutions are not always equivalent when you also consider system robustness or fail safe or whatever it is called by the experts. Just for illustration: Who designs a system, which starts an atomic war on a bitflip in a test message? (Yeah, this happened and we are only alive because of the gut feeling of an operator. The bombers were already in the air.) Sincerely Meikel -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
Hi, On 11 Apr., 11:16, Ken Wesson kwess...@gmail.com wrote: Just for illustration: Who designs a system, which starts an atomic war on a bitflip in a test message? (Yeah, this happened and we are only alive because of the gut feeling of an operator. Petrov? This was on the russian side. But it also happen in the west. Some comm relay somewhere in Alaska had a hardware defect which sprinkled some bit flips into the transported messages every once in a while. The alarm messages said something like The russians come with x rockets. The test message was basically the same with x = 0. Now imagine a bit flip in the right place. There you go. Some guy at NORAD had a bad feeling. These numbers sure look funny. And only from this single station in Alaska. H... Sincerely Meikel -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Mon, Apr 11, 2011 at 5:07 AM, Meikel Brandmeyer m...@kotka.de wrote: What is your basis for this? Because the phantasy of the average human being is quite limited. ? While a missed this is allowed might cause trouble, it doesn't compromise the system. A missed this is not allowed however will. Solutions are not always equivalent when you also consider system robustness or fail safe or whatever it is called by the experts. That depends on the system. Some stuff is mission critical or really really dangerous. Then it makes sense to default to forbid. On the other hand, for a lot of other things, where security isn't a concern but utility is (e.g. single-user products), it may make sense to default to allow. Just for illustration: Who designs a system, which starts an atomic war on a bitflip in a test message? (Yeah, this happened and we are only alive because of the gut feeling of an operator. Petrov? The bombers were already in the air.) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
Hi, On 11 Apr., 12:04, Ken Wesson kwess...@gmail.com wrote: So, similar incidents happened on both sides. And to illustrate this point: Because the phantasy of the average human being is quite limited. ? No one obviously imagined what happens when there is a malfunction in the hardware which might cause a bit flip in this single important field. From my personal experience with software, I'm not really surprised. Many things are fixed afterwards (lessons learned, oh god, I said it...), but in a system where there is no afterwards this is rather disadvantageous. (Another example: NORAD early warning radar got confused by the moon. Well, to defend the designers: it was not pointed out in the spec that the moon might raise above the horizon.) Although not every system launches the Rockets, I'd prefer systems with robustness and fault tolerance as default. Even if it's only the egg clock gadget. Sincerely Meikel -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Mon, Apr 11, 2011 at 5:29 AM, Meikel Brandmeyer m...@kotka.de wrote: Hi, On 11 Apr., 11:16, Ken Wesson kwess...@gmail.com wrote: Just for illustration: Who designs a system, which starts an atomic war on a bitflip in a test message? (Yeah, this happened and we are only alive because of the gut feeling of an operator. Petrov? This was on the russian side. But it also happen in the west. Some comm relay somewhere in Alaska had a hardware defect which sprinkled some bit flips into the transported messages every once in a while. The alarm messages said something like The russians come with x rockets. The test message was basically the same with x = 0. Now imagine a bit flip in the right place. There you go. Some guy at NORAD had a bad feeling. These numbers sure look funny. And only from this single station in Alaska. H... So, similar incidents happened on both sides. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Mon, Apr 11, 2011 at 6:27 AM, Meikel Brandmeyer m...@kotka.de wrote: Although not every system launches the Rockets, I'd prefer systems with robustness and fault tolerance as default. Even if it's only the egg clock gadget. But you must admit that the mission-criticalness of robustness and fault tolerance varies from one application to the next. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
Hi, On 11 Apr., 12:45, Ken Wesson kwess...@gmail.com wrote: But you must admit that the mission-criticalness of robustness and fault tolerance varies from one application to the next. I do. And I also admit, that I think that someone not able to write a simple, non-critical application in a robust and fault tolerant way per default is a able to write a complex, critical application in a robust and fault tolerant way. Sincerely Meikel -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
I do. And I also admit, that I think that someone not able to write a simple, non-critical application in a robust and fault tolerant way per default is a able to write a complex, critical application in a robust and fault tolerant way. Bleh. ... that I *don't* think ... -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 11 April 2011 09:43, Ken Wesson kwess...@gmail.com wrote: On Mon, Apr 11, 2011 at 4:12 AM, James Reeves jree...@weavejester.com wrote: Yes, but remember that I said I was looking for non-compound solutions. In my view, simple functions are more idiomatic Clojure. Mine were built up starting from very simple functions. Sure, but all functions are. My point is that you have an additional layer of complexity that's I don't think is necessary: (defn not-abc [x] (cond (not (a x)) :a (not (b x)) :b (not (c x)) :c)) ((not-abc x) {:a A failed, :b B failed, :c C failed} If you already have a, b, and c, then compounding them into one function, only to then use a map to split them up again doesn't seem a good solution. In my view it's better to separate out the logic used to compound the function instead. e.g. (defn validation [f m] (fn [x] (if-not (f x) m))) (defn chain [ vs] (fn [x] (some (fn [v] (v x)) vs))) (chain (validation a A failed) (validation b B failed) (validation c C failed)) Here each function does precisely one thing (i.e. they are simple), so we achieve the same effect without compounding. Is there anything that indicates they're more secure? I'd argue that encouraging people to think of what to allow is better than encouraging people to think of what to deny. What is your basis for this? Because if you forget to validate a field that is allow by default, then you end up with invalid data in your database and a potential security risk. If, on the other hand, you forget to validate a field that is deny by default, then you end up with a failed validation. Sure, and I'm not saying there aren't clear advantages to having inverted validations. Then why are you arguing as if you think I'm wrong about something? I'm not saying you're wrong. I'm saying that there are better solutions to the problem. However, I'm not certain I'm right, and that's why I'm debating this; because I think your arguments have worth, and they could potentially change my mind. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Mon, Apr 11, 2011 at 7:17 AM, Meikel Brandmeyer m...@kotka.de wrote: I do. And I also admit, that I think that someone not able to write a simple, non-critical application in a robust and fault tolerant way per default is a able to write a complex, critical application in a robust and fault tolerant way. Bleh. ... that I *don't* think ... Who said anything about whether anybody was *able* to do so? And surely you don't think that considering *more* angles and different implementation options could make someone *less* able? Anyway, this is getting off track. The point was that different systems have different security needs. For some, almost any kind of unexpected allowed access is a potential disaster and far worse than unexpected denied access (nuclear stuff, for instance). For others, almost any kind of unexpected denied access is worse than unexpected allowed access (your MP3 player's firmware). You simply cannot take a one-size-fits-all approach over so diverse a range of applications. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Mon, Apr 11, 2011 at 1:09 PM, James Reeves jree...@weavejester.com wrote: On 11 April 2011 09:43, Ken Wesson kwess...@gmail.com wrote: On Mon, Apr 11, 2011 at 4:12 AM, James Reeves jree...@weavejester.com wrote: Yes, but remember that I said I was looking for non-compound solutions. In my view, simple functions are more idiomatic Clojure. Mine were built up starting from very simple functions. Sure, but all functions are. My point is that you have an additional layer of complexity that's I don't think is necessary: (defn not-abc [x] (cond (not (a x)) :a (not (b x)) :b (not (c x)) :c)) ((not-abc x) {:a A failed, :b B failed, :c C failed} If you already have a, b, and c, then compounding them into one function, only to then use a map to split them up again doesn't seem a good solution. The preconditions have to be checked. The preconditions for integer-in-range checks are the integer check and the non-blank check, in the original example. I don't really see any way of simplifying that further, unless the logic of verifying the preconditions is moved out to the caller (and, thus, duplicated for every caller). In my view it's better to separate out the logic used to compound the function instead. e.g. (defn validation [f m] (fn [x] (if-not (f x) m))) (defn chain [ vs] (fn [x] (some (fn [v] (v x)) vs))) (chain (validation a A failed) (validation b B failed) (validation c C failed)) Here each function does precisely one thing (i.e. they are simple), so we achieve the same effect without compounding. You have compounding, via your chain here. You've just broken out a couple of more explicit steps. Is there anything that indicates they're more secure? I'd argue that encouraging people to think of what to allow is better than encouraging people to think of what to deny. What is your basis for this? Because if you forget to validate a field that is allow by default, then you end up with invalid data in your database and a potential security risk. If you forget to do *anything* in a security-critical system, that's a potential security risk. If, on the other hand, you forget to validate a field that is deny by default, then you end up with a failed validation. Depending on the application, even dead functionality can be a security risk. Perhaps it causes a police fingerprint-database search to not work or produce a false negative, for instance. Ultimately, assessing security risks requires knowing the particulars of the application and its intended uses. Sure, and I'm not saying there aren't clear advantages to having inverted validations. Then why are you arguing as if you think I'm wrong about something? I'm not saying you're wrong. I'm saying that there are better solutions to the problem. In some cases, perhaps. However, I'm not certain I'm right, and that's why I'm debating this; because I think your arguments have worth, and they could potentially change my mind. Okay then. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 11 April 2011 21:26, Ken Wesson kwess...@gmail.com wrote: On Mon, Apr 11, 2011 at 1:09 PM, James Reeves jree...@weavejester.com wrote: If you already have a, b, and c, then compounding them into one function, only to then use a map to split them up again doesn't seem a good solution. The preconditions have to be checked. The preconditions for integer-in-range checks are the integer check and the non-blank check, in the original example. I don't really see any way of simplifying that further, unless the logic of verifying the preconditions is moved out to the caller (and, thus, duplicated for every caller). You wouldn't necessarily need to explicitly verify each precondition, but it might be the case that the same string is parsed multiple times. However, I'm unsure why you think this is a problem. (chain (validation a A failed) (validation b B failed) (validation c C failed)) Here each function does precisely one thing (i.e. they are simple), so we achieve the same effect without compounding. You have compounding, via your chain here. You've just broken out a couple of more explicit steps. If the chain of validations were placed in a function, then it could be described as compound. But it's compound by necessity, and has a singular purpose - to validate a particular object. Your not-int-in-range? function is not compound by necessity, as three or four simpler functions could perform the same task, and it doesn't have a singular purpose. It's a more complex, and to my mind, less idiomatic solution. Because if you forget to validate a field that is allow by default, then you end up with invalid data in your database and a potential security risk. If you forget to do *anything* in a security-critical system, that's a potential security risk. If you forget a deny rule, that's a potential security risk, but if you forget an allow rule, it usually isn't. For instance, say you have a firewall that's deny all by default. You want to allow ports 22 and 80, but forget port 80. This will result in your web server being inaccessible, but your security won't be compromised. In fact, by forgetting a rule, you've made the system *more* secure, if less useful. If, on the other hand, you forget to validate a field that is deny by default, then you end up with a failed validation. Depending on the application, even dead functionality can be a security risk. Perhaps it causes a police fingerprint-database search to not work or produce a false negative, for instance. But these situations are rare, and usually easily discovered. For instance, if a validation always fails, then it will either show up as an unexpected error message, or will be discovered by any unit test suite with decent coverage. If, on the other hand, you let through fields that you're not supposed to (like user_id, is_admin, etc.), then you have a potential security breach that is not obvious and very difficult to check for. Ultimately, assessing security risks requires knowing the particulars of the application and its intended uses. Sure, but it helps to have sensible defaults, and deny all is usually the most secure place to start. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Mon, Apr 11, 2011 at 7:09 PM, James Reeves jree...@weavejester.com wrote: On 11 April 2011 21:26, Ken Wesson kwess...@gmail.com wrote: On Mon, Apr 11, 2011 at 1:09 PM, James Reeves jree...@weavejester.com wrote: If you already have a, b, and c, then compounding them into one function, only to then use a map to split them up again doesn't seem a good solution. The preconditions have to be checked. The preconditions for integer-in-range checks are the integer check and the non-blank check, in the original example. I don't really see any way of simplifying that further, unless the logic of verifying the preconditions is moved out to the caller (and, thus, duplicated for every caller). You wouldn't necessarily need to explicitly verify each precondition, but it might be the case that the same string is parsed multiple times. However, I'm unsure why you think this is a problem. I don't. My own code posted earlier parses some strings multiple times. I eschewed premature optimization there; a temporary memoized version of each predicate, new per field being validated per request, can be used to get rid of the multiple parsings if it's really, really necessary. (chain (validation a A failed) (validation b B failed) (validation c C failed)) Here each function does precisely one thing (i.e. they are simple), so we achieve the same effect without compounding. You have compounding, via your chain here. You've just broken out a couple of more explicit steps. If the chain of validations were placed in a function, then it could be described as compound. Where is your (chain ...) sexp going to go? At top level? If it's not, then it's placed in a function. But it's compound by necessity, and has a singular purpose - to validate a particular object. So's mine. Your not-int-in-range? function is not compound by necessity, as three or four simpler functions could perform the same task No, since it has to deal with blank/non-integer input somehow anyway. Either it has to check those preconditions, or its caller does. Either it is a compound predicate, its caller is a compound predicate, or the code at the bottom of the next layer up contains duplicated precondition logic for every separate case of an integer range check. and it doesn't have a singular purpose. It's a more complex, and to my mind, less idiomatic solution. Yours is simpler at the expense of forcing the caller to check the preconditions. Either you end up with duplicated code for every separate integer range check (bad), or you end up with a function in between the two that checks the preconditions, and is then a compound predicate. Because if you forget to validate a field that is allow by default, then you end up with invalid data in your database and a potential security risk. If you forget to do *anything* in a security-critical system, that's a potential security risk. If you forget a deny rule, that's a potential security risk, but if you forget an allow rule, it usually isn't. But it sometimes is. For instance, say you have a firewall that's deny all by default. You want to allow ports 22 and 80, but forget port 80. This will result in your web server being inaccessible, but your security won't be compromised. In fact, by forgetting a rule, you've made the system *more* secure, if less useful. If the web server is providing security patches and updates, its inaccessibility may make a wider system less secure. If, on the other hand, you forget to validate a field that is deny by default, then you end up with a failed validation. Depending on the application, even dead functionality can be a security risk. Perhaps it causes a police fingerprint-database search to not work or produce a false negative, for instance. But these situations are rare, and usually easily discovered. But, but, but. You made a universal statement that I've proven was wrong. You've basically admitted this by admitting that there are any exceptions at all to your universal rule. So, why keep arguing? Ultimately, assessing security risks requires knowing the particulars of the application and its intended uses. Sure, but But, but, but! What is it with you? :) it helps to have sensible defaults, and deny all is usually the most secure place to start. Again, that depends on the system and on what you mean by secure. Is deny all a sensible default when designing MP3 player firmware? Security in such a context means nobody unauthorized can screw with my music storage, organization, and playback. Things not working would be the player's manufacturer having effectively screwed with your music storage, organization, and playback. So deny all is effectively a *less* secure default in that case (and this goes for a lot of non-mission-critical, single-user applications). It is often a more secure default in other cases (important, multi-user or network-facing systems). There is no single right answer
Re: Announcement: pretzel - a predicate library + call for suggestions
On 10 April 2011 09:49, Ken Wesson kwess...@gmail.com wrote: (def age-invalid-en {:low age must be at least 1 :high nobody is THAT old! :blank age is required :non-integer age must be a whole number}) (def qty-invalid-en {:low quantity must be at least 1 :high maximum 10 per customer per order :non-integer quantity must be a whole number}) (if-let [err (age-invalid-en (not-int-in-range? age 1 120))] (println err) (if-let [err (qty-invalid-en (not-int-in-range? qty 1 10))] (println err) (process-order age qty))) IMO, that's not as as simple or as easy to read as: (validate thing [:age present? age is required] [:age integer-string? age must be a whole number] [:age (at-least 1) age must be at least 1] [:age (at-most 120) nobody is that old] [:qty integer-string? quantity must be a whole number] [:qty (at-least 1) quantity must be at least 1] [:qty (at-most 10) maximum 10 per customer per order]) But I guess to an extent that's a matter of opinion. I don't agree. Everything that is not forbidden is allowed. Specific chunks of the input-space are wrong for specific reasons; what's valid it what's left after whittling all of those away. My perception of validations is that they are a contract that a particular map of data has to conform to. I don't like the idea of encouraging people to think in terms of allow by default, as that's not considered good security practise. However, I'm undecided whether the validation system itself should enforce a deny by default policy. That seems like the right thing to do, but I can't think of a way to do that without making the validation system more complex. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Sun, Apr 10, 2011 at 11:42 AM, James Reeves jree...@weavejester.com wrote: On 10 April 2011 09:49, Ken Wesson kwess...@gmail.com wrote: (def age-invalid-en {:low age must be at least 1 :high nobody is THAT old! :blank age is required :non-integer age must be a whole number}) (def qty-invalid-en {:low quantity must be at least 1 :high maximum 10 per customer per order :non-integer quantity must be a whole number}) (if-let [err (age-invalid-en (not-int-in-range? age 1 120))] (println err) (if-let [err (qty-invalid-en (not-int-in-range? qty 1 10))] (println err) (process-order age qty))) IMO, that's not as as simple or as easy to read as: (validate thing [:age present? age is required] [:age integer-string? age must be a whole number] [:age (at-least 1) age must be at least 1] [:age (at-most 120) nobody is that old] [:qty integer-string? quantity must be a whole number] [:qty (at-least 1) quantity must be at least 1] [:qty (at-most 10) maximum 10 per customer per order]) I thought you were the one who wanted the strings moved out to a data structure that could be swapped with localized versions? :) But I guess to an extent that's a matter of opinion. Obviously. I don't agree. Everything that is not forbidden is allowed. Specific chunks of the input-space are wrong for specific reasons; what's valid it what's left after whittling all of those away. My perception of validations is that they are a contract that a particular map of data has to conform to. I don't like the idea of encouraging people to think in terms of allow by default, as that's not considered good security practise. On the contrary, if you don't think carefully about each specific thing that could cause a problem and forbid that thing, you can end up accidentally allowing corner cases that break the security model. If you work backwards from the security model to derive a set of constraints, though, those constraints are often mostly shalt-nots. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 10 April 2011 12:33, Ken Wesson kwess...@gmail.com wrote: I thought you were the one who wanted the strings moved out to a data structure that could be swapped with localized versions? :) Not really. I just want the error messages to be independent of the predicates. In essence, I'm looking for a solution with two properties: 1. Non-compound (i.e. simple) 2. Readable By adding error messages to predicates, we tightly couple the validation error with the predicate, which in general is considered bad. However, this might be a valid compromise, but only if it improves readability. My perception of validations is that they are a contract that a particular map of data has to conform to. I don't like the idea of encouraging people to think in terms of allow by default, as that's not considered good security practise. On the contrary, if you don't think carefully about each specific thing that could cause a problem and forbid that thing, you can end up accidentally allowing corner cases that break the security model. If you work backwards from the security model to derive a set of constraints, though, those constraints are often mostly shalt-nots. I don't really understand what you're saying here. Do you disagree that deny by default is more secure in general than allow by default? - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Sun, Apr 10, 2011 at 1:37 PM, James Reeves jree...@weavejester.com wrote: By adding error messages to predicates, we tightly couple the validation error with the predicate, which in general is considered bad. However, this might be a valid compromise, but only if it improves readability. I showed two posts ago how to keep that decoupled. I don't really understand what you're saying here. Do you disagree that deny by default is more secure in general than allow by default? I think it's a bit subtler than that. On the face, I wouldn't disagree with that statement. But if you arrive at your security rules by two different procedures, one resulting set of rules might specify what-to-deny and be more secure than another that specifies what-to-allow. And ultimately there's a mathematically equivalent what-to-allow set for any what-to-deny set, and vice versa, like a photograph and its negative. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 8 April 2011 23:21, Ken Wesson kwess...@gmail.com wrote: Better yet: maybe we're looking at this backwards. Maybe what we want isn't a predicate for *passed* validation, but a predicate for *failed* validation: (defn s-blank? [x] (if (empty? (.trim x)) must not be blank)) That particular example ties a predicate to a particular error message. Error messages should be independent of predicates, otherwise they can't be localized or changed to fit a specific situation. This takes advantage of the fact that the error messages we want are all truthy. It's also the case that you often want to detect and handle invalid input right away, then get to the meat of the logic. The natural ordering of if, if-let, etc. puts the true case first. Making the true case the error case lets you easily get it out of the way first in your code. This would lead to a lot of validations with not in front of them. i.e not-email-address?, not-integer?, etc. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Sat, Apr 9, 2011 at 9:56 AM, James Reeves jree...@weavejester.com wrote: On 8 April 2011 23:21, Ken Wesson kwess...@gmail.com wrote: Better yet: maybe we're looking at this backwards. Maybe what we want isn't a predicate for *passed* validation, but a predicate for *failed* validation: (defn s-blank? [x] (if (empty? (.trim x)) must not be blank)) That particular example ties a predicate to a particular error message. Error messages should be independent of predicates, otherwise they can't be localized or changed to fit a specific situation. It can always be an integer or a keyword (or a string!) used to look up the localized or situation-specific message in a map. This takes advantage of the fact that the error messages we want are all truthy. It's also the case that you often want to detect and handle invalid input right away, then get to the meat of the logic. The natural ordering of if, if-let, etc. puts the true case first. Making the true case the error case lets you easily get it out of the way first in your code. This would lead to a lot of validations with not in front of them. i.e not-email-address?, not-integer?, etc. So? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 9 April 2011 10:07, Ken Wesson kwess...@gmail.com wrote: That particular example ties a predicate to a particular error message. Error messages should be independent of predicates, otherwise they can't be localized or changed to fit a specific situation. It can always be an integer or a keyword (or a string!) used to look up the localized or situation-specific message in a map. It's still not as flexible, because different keywords with the same validation may require different error messages. It could perhaps work with a Turing-complete localization system, i.e. one where localizations are performed by arbitrary scripts, but I don't think a validation system should depend on having a sophisticated localization system. I also don't like the idea of tying together two pieces of functionality that could conceivably be separated. I prefer simple functions over compound ones. This would lead to a lot of validations with not in front of them. i.e not-email-address?, not-integer?, etc. So? It's redundant, doesn't read as well, and reverses people's usual conceptions about validations. I'd prefer treating validations as a contract, i.e. defining what user data must do to pass, rather than what it must do to fail. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
James Reeves wrote: On 7 April 2011 20:03, Joost jo...@zeekat.nl wrote: Yup. I'm mostly in the same boat. That's why all the predicates I've produced for now are in the pretzel.strings namespace. I expect to end up with few non-string predicates, but those will have to go into pretzel.numbers or whatever make sense. What about predicates that operate on numbers encoded as strings? e.g. 1 or 4.2. IMO, they should be in the strings package. For your specific example of (integer-string? foo), that should just return false. The idea - for strings - is that any kind of input string can be supplied, and the function should just test whether it conforms to some kind of formatting. The same logic should, I think, apply to functions operating on numbers and other types such as files, if there's a need for those kinds of predicates. I think we differ a little in our end goals, then. I'm less concerned about general use, and more concerned about generating good error messages for form-data validation. For instance, with normal predicates, one might get error messages like: {:score [is not present is not an integer is not between 1 and 10]} But in my view, it would be better to have a error message like: {:score [is not present]} Because if a value is blank, there's no point in telling the user it's also not an integer or between a certain range. Also, one might have integer fields that can be blank. Sure, but that's part of the validation mechanism that uses the predicates; the predicates all return just true or false. The messages associated with that aren't (and IMO, shouldn't) be part of the predicates. Basically the problem is one of combining validations (the functions that generate feedback); some validations can be parallel, that is, each validation should be run and the messages they return should be compounded, but others are dependent on each other, in your example, the test for integer-formatting should only be run if the test for existence doesn't return an error message. In clj-decline you can specify this by using the valiations function to combine parallel validations and validate-some to specify dependent validations. A simple example from https://github.com/joodie/flutter-decline-demo/blob/master/src/flutter_decline_demo/validations.clj (defn required [param] (validate-val param seq {param [this is a required field]})) (def validate-entry (validations (required :name) (validate-some (required :email) (validate-val :email str/looks-like-email? {:email [must contain an @ sign, and a dot in the domain name]})) (validate-some (required :phone) (validate-val :phone str/looks-like-phone? {:phone [this doesn't look like a phone number.]})) (required :address))) There's a related question on how to merge predicates (instead of validations) which is what the pretzel.combine namespace is for, but that's on a lower level since it really just merges predicates into new ones without doing anything with messages. So I think Valip needs its own predicate library, but I can probably factor out a lot of the general stuff to Pretzel (e.g. email-address? integer? etc.) I'm not so sure you actually need to have another level of predicates to do what you want, but of course, if it's possible to merge the useful predicates from valip into pretzel, I'd be happy with that :) Joost. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 8 April 2011 08:43, Joost jo...@zeekat.nl wrote: What about predicates that operate on numbers encoded as strings? e.g. 1 or 4.2. IMO, they should be in the strings package. The strings namespace could get rather large then, considering that strings are how most raw data is represented. Sure, but that's part of the validation mechanism that uses the predicates; the predicates all return just true or false. The messages associated with that aren't (and IMO, shouldn't) be part of the predicates. I'm not saying they should be. I'm saying that if a predicate is passed a value that doesn't match a precondition, the predicate could return a truthy value, rather than false. Basically the problem is one of combining validations (the functions that generate feedback); some validations can be parallel, that is, each validation should be run and the messages they return should be compounded, but others are dependent on each other, in your example, the test for integer-formatting should only be run if the test for existence doesn't return an error message. That's another way of looking at it, and it has a certain neatness and simplicity to it. The problem I have with such a scheme is that it seems more complex to use in practise. For instance, let's say I wanted an optional value. If predicates that fail a precondition return a truthy value (such as :pass) I could write: (defn validate-rating [rating] (validate rating [:score integer-string? must be an integer] [:score (between 1 10) must be between 1 and 10])) This would not return an error if the :score field was left blank, because integer-string? and (between 1 10) would return :pass for an empty string. How would you do this in clj-decline? (BTW, I'm not trying to pick holes in your library - I'm not decided on Valip's syntax, so I'm curious how clj-decline handles certain validation situations. It's possible there's a much better way to approach validation than my current attempts.) - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Fri, Apr 8, 2011 at 9:48 PM, James Reeves jree...@weavejester.com wrote: I'm saying that if a predicate is passed a value that doesn't match a precondition, the predicate could return a truthy value, rather than false. Better yet: maybe we're looking at this backwards. Maybe what we want isn't a predicate for *passed* validation, but a predicate for *failed* validation: (defn s-blank? [x] (if (empty? (.trim x)) must not be blank)) (defn s-not-integer-or-blank? [x] (if-not (s-blank? x) (try (Integer/parseInt x) (catch Exception _ must be an integer) nil))) (defn s-out-of-range-integer? [x lo hi] (if-not (s-blank? x) (if-not (s-not-integer? x) (let [n (Integer/parseInt x)] (if ( n lo) (str must not be less than lo) (if ( n hi) (str must not be greater than hi))) (defn s-not-in-range-integer? [x lo hi] (or (s-blank? x) (s-not-integer-or-blank? x) (s-out-of-range-integer? x lo hi))) (defn s-not-blank-or-in-range-integer? [x lo hi] (or (s-not-integer-or-blank? x) (s-out-of-range-integer? x lo hi))) ... (if-let [err (s-not-blank-or-in-range-integer? input 5 10)] (println Input err) (if-not (s-blank? input) (do-something-with input))) This takes advantage of the fact that the error messages we want are all truthy. It's also the case that you often want to detect and handle invalid input right away, then get to the meat of the logic. The natural ordering of if, if-let, etc. puts the true case first. Making the true case the error case lets you easily get it out of the way first in your code. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On Apr 7, 1:47 am, James Reeves jree...@weavejester.com wrote: I've been writing a small validation library, Valip, with a number of included predicates. The predicates in Valip are curried if they have more than one argument, but there is probably some overlap between Valip and Pretzel, and it might be an idea to farm out some more generic functionality to Pretzel. I think your choice of currying makes more sense, at least in the context of validations, so it might be a good idea to switch pretzel over to that scheme. https://github.com/weavejester/valip/blob/master/src/valip/predicates... Also, it looks like your ^String type hint is in the wrong place for your length? predicate. Oh, you're right. I really should work on extending the tests... If you want, I can take a stab at unifying the code for this. Cheers, Joost. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 7 April 2011 06:48, Joost jo...@zeekat.nl wrote: I think your choice of currying makes more sense, at least in the context of validations, so it might be a good idea to switch pretzel over to that scheme. Would it make sense for clj-decline? The Valip predicates are designed with HTML form validation in mind, so they have a couple of unusual properties: 1. Valip predicates expect to test strings, e.g. ((between 1 10) 5) = true ((between 1 10) 0) = false 2. I'm considering adding an extra :pass return value, to denote the case when the input string cannot be tested by the predicate. For instance: ((between 1 10) foo) = :pass (integer-string? foo) = false This is to ensure I don't get exceptions for predicates when the input is incorrect: (defn validate-rating [rating] (validate rating [:score present? should be present] [:score digits? should be a number] [:score (between 1 5) should be between 1 and 5])) (validate-rating {:score }) = {:score [should be present]} (validate-rating {:score foo}) = {:score [should be a number]} (validate-rating {:score 15}) = {:score [should be between 1 and 5]} So the predicates I'm writing for Valip are somewhat customised for validating string data, and are not generic predicate functions. Is Pretzel designed for general-use predicates, or for predicates designed for form validation? - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
James Reeves wrote: On 7 April 2011 06:48, Joost jo...@zeekat.nl wrote: I think your choice of currying makes more sense, at least in the context of validations, so it might be a good idea to switch pretzel over to that scheme. Would it make sense for clj-decline? Yes. The main idea of clj-decline is to get rid of unesessary restrictions on predicates and validation errors, but curried predicates to me fit in slightly better than in-line functions. valip looks pretty similar in design with regards to the predicates. The Valip predicates are designed with HTML form validation in mind, so they have a couple of unusual properties: 1. Valip predicates expect to test strings, e.g. ((between 1 10) 5) = true ((between 1 10) 0) = false Yup. I'm mostly in the same boat. That's why all the predicates I've produced for now are in the pretzel.strings namespace. I expect to end up with few non-string predicates, but those will have to go into pretzel.numbers or whatever make sense. 2. I'm considering adding an extra :pass return value, to denote the case when the input string cannot be tested by the predicate. For instance: ((between 1 10) foo) = :pass (integer-string? foo) = false This is to ensure I don't get exceptions for predicates when the input is incorrect: (defn validate-rating [rating] (validate rating [:score present? should be present] [:score digits? should be a number] [:score (between 1 5) should be between 1 and 5])) (validate-rating {:score }) = {:score [should be present]} (validate-rating {:score foo}) = {:score [should be a number]} (validate-rating {:score 15}) = {:score [should be between 1 and 5]} So the predicates I'm writing for Valip are somewhat customised for validating string data, and are not generic predicate functions. Is Pretzel designed for general-use predicates, or for predicates designed for form validation? As I alluded to above, the predicates in pretzel.string expect a string as an argument. As long as that requirement is met, they shouldn't throw exceptions or return any special value. I see that as general use for these kinds of functions. Either the argument is valid or it is not. Any handling above that cannot be up to the predicate, and this is one of the reasons I added the pretzel.combine functions ~ though I'm not sure that the functions in that namespace are named well. For your specific example of (integer-string? foo), that should just return false. The idea - for strings - is that any kind of input string can be supplied, and the function should just test whether it conforms to some kind of formatting. The same logic should, I think, apply to functions operating on numbers and other types such as files, if there's a need for those kinds of predicates. Cheers, Joost. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Announcement: pretzel - a predicate library + call for suggestions
On 6 April 2011 13:27, Joost jo...@zeekat.nl wrote: The idea is to have a simple collection of these kinds of functions outside of possibly unwanted frameworks. I'm using them myself for doing validation with clj-decline, but it should at least be useful for most code that has to deal with free-form text input. I've been writing a small validation library, Valip, with a number of included predicates. The predicates in Valip are curried if they have more than one argument, but there is probably some overlap between Valip and Pretzel, and it might be an idea to farm out some more generic functionality to Pretzel. https://github.com/weavejester/valip/blob/master/src/valip/predicates.clj Also, it looks like your ^String type hint is in the wrong place for your length? predicate. - James -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en