From: kangax on
Thomas 'PointedEars' Lahn wrote:
> kangax wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> I do not know if this is really news to you, but since I have encountered
>>> it not before today in one of my commercial projects (XHR had not been a
>>> priority there), and a Google Groups search here for "1223" returned it only
>>> once in a rather long posting of Conrad Lender that advocates browser
>>> sniffing to deal with this kind of problem[1], I thought I could as well
>>> tell you about it.
>> It was reported to Prototype a little more than a year ago [...]
>
> I know. Read again:
>
>>> In a nutshell:
>>>
>>> As described e.g. in [2], contrary to the MSDN Library documentation[3], the
> ^^^^^^^^^^^^^^^^^^^^^^^^
>>> IXMLHTTPRequest implementation in MSXML HTTP (at least in IE 8.0 on Windows
>>> XP SP3+) does not handle HTTP responses with status code 204 (No Content)
>>> properly; the `status' property has the value 1223 then (which I found out
>>> thanks to IE 8.0's built-in debugger). The used ActiveX/COM ProgID to
>>> reproduce the bug was "Microsoft.XMLHTTP" which should select MSXML 3.0 or
>>> earlier (AFAIK).[4]
>>>
>>> As a result, I have changed
>>>
>>> status: {
>>> OK_EXPR: /\b(0|2\d\d)\b/,
>>>
>>> // ...
>>> }
>>>
>>> into
>>>
>>> status: {
>>> /*
>>> * NOTE: MSXML translates 204 to 1223, see
>>> * https://prototype.lighthouseapp.com/projects/[...]
>>> */
>>> OK_EXPR: /\b(0|2\d\d|1223)\b/,
>> Don't you think regex is really a wrong tool for the job in this case?
>
> No. Here I have the positive (and negative) cases composed into one
> "constant"; for considering MSXML's quirk now, I did not need to modify the
> code of a single method. Think about it.

Which negative case are you talking about? Yes, you did not need to
modify "code of a single method"; you modified regex value of a
property. Is there some substantial difference I'm not seeing here?

>
>> It would be much more clear and efficient to perform a plain number
>> comparison.
>
> As for clarity, I don't think so. As for efficiency, maybe; but iff number
> comparison is more efficient, is the difference really relevant?

Efficiency difference most definitely doesn't matter. I am mainly
concerned about clarity in this case. It's not a big deal for simple
expression like that, but it will get cryptic as more "exceptions" are
added to it.

[...]

--
kangax
From: Thomas 'PointedEars' Lahn on
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> [...]
>>>> status: {
>>>> /*
>>>> * NOTE: MSXML translates 204 to 1223, see
>>>> * https://prototype.lighthouseapp.com/projects/[...]
>>>> */
>>>> OK_EXPR: /\b(0|2\d\d|1223)\b/,
>>> Don't you think regex is really a wrong tool for the job in this case?
>> No. Here I have the positive (and negative) cases composed into one
>> "constant"; for considering MSXML's quirk now, I did not need to modify the
>> code of a single method. Think about it.
>
> Which negative case are you talking about?

It could be argued that what doesn't match the positive case can be
considered the negative one; thus the expression for the positive case could
be reused. However, I define and use

FAILED_EXPR: /\b[45]\d\d\b/,

among others, instead, which is what I was referring to.

> Yes, you did not need to modify "code of a single method"; you modified
> regex value of a property.

Not just any property.

> Is there some substantial difference I'm not seeing here?

Modifying the property requires much less effort than modifying the method.
And as in my library the response listener can be user-defined (a setter can
shadow the inherited method), the RegExp provides the user which much an
easier-to-use tool to refine their listener without the need to depend on
the RegExp.

>>> It would be much more clear and efficient to perform a plain number
>>> comparison.
>> As for clarity, I don't think so. As for efficiency, maybe; but iff number
>> comparison is more efficient, is the difference really relevant?
>
> Efficiency difference most definitely doesn't matter. I am mainly
> concerned about clarity in this case. It's not a big deal for simple
> expression like that, but it will get cryptic as more "exceptions" are
> added to it.

IBTD. Compare

if (oStatus.OK_EXPR.test(reqStatus))

against your

if (status >= 200 && status < 300 || status === 1223) {

and think about the mess (not) created (and efficiency [not] decreased) if
you need to handle another "exception". (Also think about the possible need
of renaming the `status' property some day; refactoring tools and
RegExp-search-and-replace don't always serve.)

Please trim your quotes.


PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
From: kangax on
Thomas 'PointedEars' Lahn wrote:
> kangax wrote:
[...]
>> Is there some substantial difference I'm not seeing here?
>
> Modifying the property requires much less effort than modifying the method.

Much less effort? I wouldn't say so, but I guess this is all rather
subjective.

Compare changing:

`OK_EXPR: /\b(0|2\d\d)\b/`
to:
`OK_EXPR: /\b(0|2\d\d|1223)\b/`

vs.

function isOK(code) { return code >= 200 && code < 300;}
to:
function isOK(code) { return code >= 200 && code < 300 || code == 1223;}

Is former example "much less" effort, really?

> And as in my library the response listener can be user-defined (a setter can
> shadow the inherited method), the RegExp provides the user which much an
> easier-to-use tool to refine their listener without the need to depend on
> the RegExp.

Perhaps it does make sense in your case. However, don't forget that
method allows to hide implementation details, whereas property doesn't.
If you make that property part of public interface, it will definitely
be messier to change it in the future (comparing to method whose
implementation is encapsulated within, and can be changed without
affecting anything depending on it). Think about it ;)

>
>>>> It would be much more clear and efficient to perform a plain number
>>>> comparison.
>>> As for clarity, I don't think so. As for efficiency, maybe; but iff number
>>> comparison is more efficient, is the difference really relevant?
>> Efficiency difference most definitely doesn't matter. I am mainly
>> concerned about clarity in this case. It's not a big deal for simple
>> expression like that, but it will get cryptic as more "exceptions" are
>> added to it.
>
> IBTD. Compare
>
> if (oStatus.OK_EXPR.test(reqStatus))
>
> against your
>
> if (status >= 200 && status < 300 || status === 1223) {

Apples, oranges.

No need to compare 2 different abstraction levels.

Here's a more even comparison, first on a higher level -

if (oStatus.OK_EXPR.test(reqStatus))
vs.
if (isStatusOK(reqStatus))

- then, on a lower one -

OK_EXPR: /\b(0|2\d\d|1223)\b/
vs.
function isStatusOK(code){
return code >= 200 && code < 300 || code == 1223;
}

Obviously, the clarity of latter example is the one I was talking about.

[...]

--
kangax
From: Thomas 'PointedEars' Lahn on
kangax wrote:
> Thomas 'PointedEars' Lahn wrote:
>> kangax wrote:
> [...]
>>> Is there some substantial difference I'm not seeing here?
>> Modifying the property requires much less effort than modifying the method.
>
> Much less effort? I wouldn't say so, but I guess this is all rather
> subjective.
>
> Compare changing:
>
> `OK_EXPR: /\b(0|2\d\d)\b/`
> to:
> `OK_EXPR: /\b(0|2\d\d|1223)\b/`
>
> vs.
>
> function isOK(code) { return code >= 200 && code < 300;}
> to:
> function isOK(code) { return code >= 200 && code < 300 || code == 1223;}
>
> Is former example "much less" effort, really?

5 more characters vs. 16 plus likely additional reformatting of the code
(before it exceeds 80 characters per line) is definitely listed under "much
less" in my book. But this example shows a rather simple change; you should
consider what needs changing with either approach if a client would
translate 204 to 299 (for whatever reason), and the like, instead.

>> And as in my library the response listener can be user-defined (a setter can
>> shadow the inherited method), the RegExp provides the user which much an
>> easier-to-use tool to refine their listener without the need to depend on
>> the RegExp.
>
> Perhaps it does make sense in your case. However, don't forget that
> method allows to hide implementation details, whereas property doesn't.

I have never believed security by obscurity to be a sound concept.

> If you make that property part of public interface, it will definitely
> be messier to change it in the future

No, it won't.

> (comparing to method whose
> implementation is encapsulated within, and can be changed without
> affecting anything depending on it). Think about it ;)

ISTM you have a misconception of "in" and "out" with regard to these
languages. As it is, anything can be changed by the user, there are no
guarantees. Not even "private properties".

>>>>> It would be much more clear and efficient to perform a plain number
>>>>> comparison.
>>>> As for clarity, I don't think so. As for efficiency, maybe; but iff number
>>>> comparison is more efficient, is the difference really relevant?
>>> Efficiency difference most definitely doesn't matter. I am mainly
>>> concerned about clarity in this case. It's not a big deal for simple
>>> expression like that, but it will get cryptic as more "exceptions" are
>>> added to it.
>> IBTD. Compare
>>
>> if (oStatus.OK_EXPR.test(reqStatus))
>>
>> against your
>>
>> if (status >= 200 && status < 300 || status === 1223) {
>
> Apples, oranges.

No. It is essentially doing the same thing.
-
> No need to compare 2 different abstraction levels.

Are you kidding? Using abstraction to make it easier both for the library
developer to adapt (e.g., for quirks like this) and the library user is what
this is all about.

> Here's a more even comparison, first on a higher level -

Now that's apples and oranges, really.


EOD for me.

PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16
From: Diego Perini on
On 10 Set, 08:16, kangax <kan...(a)gmail.com> wrote:
> Thomas 'PointedEars' Lahn wrote:
> > kangax wrote:
> [...]
> >> Is there some substantial difference I'm not seeing here?
>
> > Modifying the property requires much less effort than modifying the method.
>
> Much less effort? I wouldn't say so, but I guess this is all rather
> subjective.
>
> Compare changing:
>
> `OK_EXPR: /\b(0|2\d\d)\b/`
> to:
> `OK_EXPR: /\b(0|2\d\d|1223)\b/`
>
> vs.
>
> function isOK(code) { return code >= 200 && code < 300;}
> to:
> function isOK(code) { return code >= 200 && code < 300 || code == 1223;}
>
> Is former example "much less" effort, really?
>
> > And as in my library the response listener can be user-defined (a setter can
> > shadow the inherited method), the RegExp provides the user which much an
> > easier-to-use tool to refine their listener without the need to depend on
> > the RegExp.
>
> Perhaps it does make sense in your case. However, don't forget that
> method allows to hide implementation details, whereas property doesn't.
> If you make that property part of public interface, it will definitely
> be messier to change it in the future (comparing to method whose
> implementation is encapsulated within, and can be changed without
> affecting anything depending on it). Think about it ;)
>
>
>
>
>
> >>>> It would be much more clear and efficient to perform a plain number
> >>>> comparison.
> >>> As for clarity, I don't think so.  As for efficiency, maybe; but iff number
> >>> comparison is more efficient, is the difference really relevant?
> >> Efficiency difference most definitely doesn't matter. I am mainly
> >> concerned about clarity in this case. It's not a big deal for simple
> >> expression like that, but it will get cryptic as more "exceptions" are
> >> added to it.
>
> > IBTD.  Compare
>
> >   if (oStatus.OK_EXPR.test(reqStatus))
>
> > against your
>
> >   if (status >= 200 && status < 300 || status === 1223) {
>
> Apples, oranges.
>
> No need to compare 2 different abstraction levels.
>
> Here's a more even comparison, first on a higher level -
>
>    if (oStatus.OK_EXPR.test(reqStatus))
>    vs.
>    if (isStatusOK(reqStatus))
>
> - then, on a lower one -
>
>    OK_EXPR: /\b(0|2\d\d|1223)\b/
>    vs.
>    function isStatusOK(code){
>      return code >= 200 && code < 300 || code == 1223;
>    }
>
> Obviously, the clarity of latter example is the one I was talking about.
>
> [...]
>
> --
> kangax

Remember that "1223" is not the only exception status code here.

Mozilla/Firefox can return a status code of "0" for some type of
network errors while it will return "408" for network timeout.

IE may return these extra status codes in case of network errors/
timeouts:

- 12002 ERROR_INTERNET_TIMEOUT
- 12007 ERROR_INTERNET_NAME_NOT_RESOLVED
- 12029 ERROR_INTERNET_CANNOT_CONNECT
- 12030 ERROR_INTERNET_CONNECTION_ABORTED
- 12031 ERROR_INTERNET_CONNECTION_RESET
- 12150 ERROR_HTTP_HEADER_NOT_FOUND
- 12152 ERROR_HTTP_INVALID_SERVER_RESPONSE

Also, status code "304 Not modified" is not exactly an error so both
code examples I see here are not handling these situation correctly.

> OK_EXPR: /\b(0|2\d\d|1223)\b/
> vs.
> function isStatusOK(code){
> return code >= 200 && code < 300 || code == 1223;
> }

I agree that there is no need to detect/notify all errors
specifically, though some of them should be treated differently.

This obviously only applies if you deem "works well enough" not
sufficient as the target for your code.


--
Diego