Prev: FAQ Topic - How can I access the client-side filesystem? (2010-05-11)
Next: apparently wrong function.
From: Scott Sauyet on 14 May 2010 11:16 Thomas 'PointedEars' Lahn wrote: > A helper function that by design makes it hard for it to be reused, that > makes code less legible and less reliable than if it was not used, a > function that is not generally applicable, is not a goal to be attained. I can buy this: "A helper function that by design makes it hard for it to be reused, that makes code less legible and less reliable than if it was not used, is not a goal to be attained." But I'm not buying your "generally applicable" clause. Code needs to have an reasonable domain. It should be clear as to what it accepts and handle errors consistently, but it does not have to be able to give reasonable results for unreasonable input. Defining what is and is not reasonable is a large part of designing an API. But I find myself in an odd position here. I'm defending something I don't really support, only to say that the problems aren't as bad as stated. I think that Matt probably should use a multiple-string API, with the main reason being the sort of problems many of us have pointed out, but may best be seen in your response to one of my code snippets: |> $prop(obj, "longer.path.with.some[0].brackets.included"); | So, is `some' the property name or is it `some[0]', which is entirely | possible and realistic with DOM scripting? Matt made it clear that he wants to use his function for searching DOM nodes. Simply because of that, I find it reasonable to complicate the API with multiple strings. But still I see issues. The technique I used when I did this was to search first using the entire string ("some[0]") for a property name, and if that wasn't found to try "some", then 0 on the results. It worked and it never turned around and bit us. But I was never happy with it. When we found this need (when we switched server framework and now had to deal with brackets as attribute values) we were already invested in the single-string API. We never did have to introduce a delimiter, but we did have a slightly more complex API that allows brackets to contain additional hierarchies: $prop(obj, "prop1.prop2[current.left.size].color"); I suppose the way to do that with the multiple string array would be something like this: $prop(obj, "prop1", "prop2", $prop(current, "left", "size"), "color"); But that clearly is neither as convenient nor as legible as the original. So again I want to argue both sides of this issue. I think I'd better just stop here! :-) -- Scott
From: Thomas 'PointedEars' Lahn on 14 May 2010 16:46 Scott Sauyet wrote: > Thomas 'PointedEars' Lahn wrote: >> A helper function that by design makes it hard for it to be reused, that >> makes code less legible and less reliable than if it was not used, a >> function that is not generally applicable, is not a goal to be attained. > > I can buy this: "A helper function that by design makes it hard for > it to be reused, that makes code less legible and less reliable than > if it was not used, is not a goal to be attained." But I'm not buying > your "generally applicable" clause. Perhaps you are misunderstanding, then. > Code needs to have an reasonable domain. The domain is property access. > It should be clear as to what it accepts and handle errors > consistently, but it does not have to be able to give reasonable > results for unreasonable input. Defining what is and is not > reasonable is a large part of designing an API. Property names that contain what property names may contain are not unreasonable input. > But I find myself in an odd position here. I'm defending something I > don't really support, only to say that the problems aren't as bad as > stated. Without giving a good reason for your opinion that they are not, so you should ask yourself if you are trying to defend something that is worth defending. PointedEars -- realism: HTML 4.01 Strict evangelism: XHTML 1.0 Strict madness: XHTML 1.1 as application/xhtml+xml -- Bjoern Hoehrmann
From: nick on 14 May 2010 20:30 On May 12, 3:57 pm, Garrett Smith <dhtmlkitc...(a)gmail.com> wrote: > Stefan Weiss wrote: > > This may be obvious, but did you consider simply catching and ignoring > > the ReferenceError? > > try { var color = body.firstChild.style.backgroundColor; } catch(e) {} This seems like the most obvious way to do it. > Starting a statement that way isn't "not as nice" it is a failure of the > code to express its intent. The try statement misleads the reader. True, it would be nice if we could wrap it in a function. > Someone may also mention that using try/catch is inefficient, and it is, > but that is the least of the problems. It's probably at least as efficient as executing a bunch of other code to get around it as in the OP... Matt, I've been using a build script and putting C++ preprocessor directives in my js source to keep things manageable (initially just for includes and ifdefs). I've been playing with a header file containing some function macros; they can be useful for inlining and doing things you can't do with normal functions (like pass in a non- existing variable). "Error-free deep property access" might make a good candidate for that header file: #define CAN_ACCESS(v) \ (function(){ \ try{void(v); return true;} \ catch(e){return false;}})(); You can use it in your source something like this: if (CAN_ACCESS(document.forms[2])) document.forms[2].submit(); else notifyUser("Swing and a miss."); ....And it will expand to... well, something fairly ugly. But, your source code is still plenty readable, and you have less code to support :)
From: David Mark on 14 May 2010 21:20 nick wrote: > On May 12, 3:57 pm, Garrett Smith <dhtmlkitc...(a)gmail.com> wrote: >> Stefan Weiss wrote: > >>> This may be obvious, but did you consider simply catching and ignoring >>> the ReferenceError? > >>> try { var color = body.firstChild.style.backgroundColor; } catch(e) {} > > This seems like the most obvious way to do it. The trouble is that it is ham-fisted. You will have no idea why the exception is thrown, so the pattern has very limited potential in anything but the simplest of contexts.
From: Scott Sauyet on 14 May 2010 21:57
Thomas 'PointedEars' Lahn wrote: > Scott Sauyet wrote: >> Thomas 'PointedEars' Lahn wrote: >>> A helper function that by design makes it hard for it to be reused, that >>> makes code less legible and less reliable than if it was not used, a >>> function that is not generally applicable, is not a goal to be attained.. > >> I can buy this: "A helper function that by design makes it hard for >> it to be reused, that makes code less legible and less reliable than >> if it was not used, is not a goal to be attained." But I'm not buying >> your "generally applicable" clause. > > Perhaps you are misunderstanding, then. Maybe, but I think it's more that I disagree. >> Code needs to have an reasonable domain. > > The domain is property access. Not to my mind. And perhaps that is the crux of the matter. The language already has '[]' for property access, and a shortcut for some simpler cases: '.'. I have little need to use a function that has the same domain as those language constructs. The reason I created my version -- and I really wish I still had it available -- was that doing all the error checking on something that would otherwise be very simple made the source code much harder to read. The goal of the function was to make the source code simpler to read without actually sacrificing safety. So the domain was limited to replacing the sorts of source code that I would like to use except that it wasn't safe, something like obj.prop1.[key1.prop2.prop3].prop4 with a similar looking construct that gained the required safety. Part of the goal of my code was the very similarity to the desired source code above. If I remember correctly, unlike Matt, I didn't separate out the initial object, so mine looked something like fetch('obj.prop1[key1.prop2.prop3].prop4'); The whole point of mine was to make it look like as much as possible like the desired source code. >> It should be clear as to what it accepts and handle errors >> consistently, but it does not have to be able to give reasonable >> results for unreasonable input. Defining what is and is not >> reasonable is a large part of designing an API. > > Property names that contain what property names may contain are not > unreasonable input. So are you saying that all functions should be written to work seamlessly with any values of their parameters that the language might allow? Or are we allowed to write functions whose behavior is only well-defined for some specified subset of the allowed values? I've have always believed the latter. Do you really believe the former? That's got to be hard to do in a loosely typed language. >> But I find myself in an odd position here. I'm defending something I >> don't really support, only to say that the problems aren't as bad as >> stated. > > Without giving a good reason for your opinion that they are not, so you > should ask yourself if you are trying to defend something that is worth > defending. My code was not originally intended to work with DOM nodes. The data structures I used were built in other JS code, and I'm quite certain they never contained property names that wouldn't be allowed as an identifier. When I had to support "[]" as well, it was not a hard extension. Had my requirements grown further, I might have had to abandon some of the initial simplicity. But I wouldn't do so unless circumstances forced it on me. The overriding goal was to simplify my code and make it more readable. It's easy enough to defend the decisions I made. But Matt seems to have somewhat different requirements, and I don't think my approach would suit those requirements as well. I have stated the reasons for both sides of this argument several times. I think the categorical statements that string parsing is wrong here are overblown. But if I were writing the code for him under my understanding of his requirements, I probably would use the multiple parameter approach. For my own requirements, I think string parsing is clearly better. It's all about the simplicity of the API. -- Scott |