The unconditional checkfile exception condition idiom



  • Found this in the code base I am currently working on. Enjoy:

    The field:

            private boolean checkFileOnServer = true;
    

    The initialisation:

            private void readProperties(Config config) {
                ...
                if (!config.getProperty("CHECKFILEONSERVER").equalsIgnoreCase("")) {
                    String checkFile = config.getProperty("CHECKFILEONSERVER");
                    checkFileOnServer = checkFile.equalsIgnoreCase("true");
                }
                ...
            }
    

    WTF 1: equalsIgnoreCase() with an empty String
    WTF 2: Ignoring the method Boolean.valueOf(...)

    The application:

            if (client.checkFile(fileToReceive)) {
                logger.info("the file " + fileToReceive + " is on the server");
            } else {
                final XYZException ex = new XYZException("The File " + fileToReceive
                    + " was not found on the server !");
                logger.error(transferType + ", File not found on Server", ex);
            }
            final byte[] fileData = client.retrieveFile(slog, fileToReceive);
            ByteArrayInputStream bIn = new ByteArrayInputStream(fileData);
    

    WTF 3: Creating an exception for the purpose of logging it, not throwing it. Well, the Logger doesn't have an error-method without an exception-parameter. Therefore, one must be created, obviously!
    WTF 4: Even if the file wasn't found, it is still retrieved. This is called optimism, a trait that I am sometimes missing.
    WTF 5: Important to know: Creating a ByteArrayInputStream with a null parameter leads to a NullPointerException.

    The implementation, part 1:

            public boolean checkFile(final String remoteFileName) {
                try {
                    if (checkFileOnServer) {
                        Vector files = sftpChannel.ls(remoteFileName);
                        if (files.size() > 0) {
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        return true;
                    }
                } catch (SftpException e) {
                    // do nothing
                }
                return false;
            }
    

    WTF 6: if checkFileOnServer=false, then checkFileOnServer() returns true
    WTF 7: Exceptions are ignored
    WTF 8: Using Vector when that class has been replaced with List/ArrayList for almost a decade.

    The implementation, part 2:

            public byte[] retrieveFile(final LogSession slog, final String fileToReceive) throws LoggerExcpetion {
                if (sftpChannel.isConnected() && checkFile(fileToReceive)) {
                    try {
                        ByteArrayOutputStream bOut = null;
                        BufferedOutputStream bfOut = null;
                        try {
                            bOut = new ByteArrayOutputStream();
                            bfOut = new BufferedOutputStream(bOut);
                            sftpChannel.get(fileToReceive, bfOut);
                            bfOut.flush();
                            bfOut.close();
                            bOut.flush();
                            bOut.close();
                            byte[] retrievedFile = bOut.toByteArray();
                            if (slog != null) {
                                log.info(slog, "file " + fileToReceive + " successfully retrieved");
                            }
                            return retrievedFile;
                        } catch (Exception ex) {
                            disconnect();
                        }
                    } catch (Exception ex) {
                        // do nothing
                    }
                }
                return null;
            }
    

    WTF 9: We are only logging when successful! Jippie! The developer may have thought like this: The Logger may throw an exception, therefore we only risk logging if all else went well. Otherwise, we might destroy our potentially good case. Or you pass slog==null, then that danger is averted as well.
    WTF 10: If the file does not exist and checkFileOnServer=false, this results in an NullPointerException
    WTF 11: If the file does not exist and checkFileOnServer=true, there will also be a NullPointerException. But the Log says, the file exists.
    WTF 12: If retrieveFile() results in an Exception, another NPE results, but one doesn't know what the reason is, because exceptions are being swallowed.
    WTF 13: If all is well, the Logger may throw an exception and fuck it all up.

    What would we call this pattern? The unconditional checkfile exception condition idiom?



  •  Uhm, how is #6 a WTF (out of context) exactly? Isn't it a normal behavior, when you disable a check, to assume it succeeded? If one assumed it failed instead, there would be little "interest" in disabling it in the first place.

     (or course, the real WTF is disabling the check at all)



  • WTF8 is clearly due to the API of the SFTP library used. If that isn't in house then you can't really blame the author of this code.



  • Worthy of a front-page WTF, much better than some of the latest front-page articles. Way to go, but glad I'm not working there.

    A couple of unit tests could clean that up nicely.



  • #6 is not a WTF - the checkFileOnServer flag enables logging into the remote server just to see if the file exists, and disabling it implies a built-in assumption that the file will exist when requested (which leads to #10 if it doesn't. I can see disabling it in production for performance if you can ensure that the file exists when this application runs)

    #8 is a very small WTF - if you have no control over the sftp library (which if you do, why aren't you using one of the existing free ones) then you get what you get; and considering how often you expect an sftp library to change, there is no impetus to go back and change it just to use the new java collections. You can just gloss over that implementation detail and use: Collection files = sftp..., since you only care for the size (and actually you only care to know if the result is empty or not - you could simplify that block to: return sftpChannel.ls(remoteFileName).isEmpty(); )

    #11 - where does it log that the file exists when in that scenario checkFile(...) returns false? It logs that the file does NOT exist (with a worthless exception) and runs right into the NPE.

    #7 and 12 are probably because loggers throw exceptions, so we won't bother logging if we just get exceptions when trying to log. Fix #13 and then go back and put in proper logging.



  • @TheRider said:

    WTF 3: Creating an exception for the purpose of logging it, not throwing it. Well, the Logger doesn't have an error-method without an exception-parameter. Therefore, one must be created, obviously!

    That's not as much of a WTF as you suggest. If that's the logging framework you're stuck with using and you really need it to log a stack trace, then that's how you'd need to do it.



  • @Thuktun said:

    @TheRider said:

    WTF 3: Creating an exception for the purpose of logging it, not throwing it. Well, the Logger doesn't have an error-method without an exception-parameter. Therefore, one must be created, obviously!

    That's not as much of a WTF as you suggest. If that's the logging framework you're stuck with using and you really need it to log a stack trace, then that's how you'd need to do it.

    Except that there is no stack trace because the exception didn't get thrown up the stack (or the stack trace only has one item which is the point where the exception was created which is no more helpful than the logged error message).  The only reason for creating the exception is because log.error only has one override and that is the version that takes a String (the message) and an exception (and considering everything else here will probably throw an NPE if you try to just pass null for the exception) 

     



  • @airdrik said:

    Except that there is no stack trace because the exception didn't get thrown up the stack (or the stack trace only has one item which is the point where the exception was created which is no more helpful than the logged error message).

    Bwahahaha!! Where do you people get this shit from??



  • @morbiuswilters said:

    @airdrik said:
    Except that there is no stack trace because the exception didn't get thrown up the stack (or the stack trace only has one item which is the point where the exception was created which is no more helpful than the logged error message).

    Bwahahaha!! Where do you people get this shit from??

    Isn't that what the fillInStackTrace() method is for? But, I must confess, I never really understood the real purpose and use of that method.



  • @airdrik said:

    Except that there is no stack trace because the exception didn't get thrown up the stack (or the stack trace only has one item which is the point where the exception was created which is no more helpful than the logged error message).

    Except that's not how exception stack traces work. The exception doesn't need to traverse back up to fill it in, it gets filled in based on the call stack that constructed the exception.



  • @Thuktun said:

    @airdrik said:

    Except that there is no stack trace because the exception didn't get thrown up the stack (or the stack trace only has one item which is the point where the exception was created which is no more helpful than the logged error message).

    Except that's not how exception stack traces work. The exception doesn't need to traverse back up to fill it in, it gets filled in based on the call stack that constructed the exception.

    No shit. Why would anyone think otherwise? What use would a stack trace be that only showed the methods it was thrown through?



  • @airdrik said:

    @Thuktun said:
    @TheRider said:

    WTF 3: Creating an exception for the purpose of logging it, not throwing it. Well, the Logger doesn't have an error-method without an exception-parameter. Therefore, one must be created, obviously!

    That's not as much of a WTF as you suggest. If that's the logging framework you're stuck with using and you really need it to log a stack trace, then that's how you'd need to do it.

    Except that there is no stack trace because the exception didn't get thrown up the stack (or the stack trace only has one item which is the point where the exception was created which is no more helpful than the logged error message).  The only reason for creating the exception is because log.error only has one override and that is the version that takes a String (the message) and an exception (and considering everything else here will probably throw an NPE if you try to just pass null for the exception) 

     

    When having to deal with exceptions, I tend to want to throw up... throw "it" up the stack :-)



  • @morbiuswilters said:

    No shit. Why would anyone think otherwise? What use would a stack trace be that only showed the methods it was thrown through?

    I'm sure I've come across some environment in which the stack trace wasn't filled in until the exception was thrown. Of course, the easy workaround is to throw it and immediately catch it.



  • @pjt33 said:

    @morbiuswilters said:
    No shit. Why would anyone think otherwise? What use would a stack trace be that only showed the methods it was thrown through?

    I'm sure I've come across some environment in which the stack trace wasn't filled in until the exception was thrown. Of course, the easy workaround is to throw it and immediately catch it.

    Even then, it should still fill in the trace all the way back to the top, otherwise it's next to useless.



  • @TheRider said:

    WTF 1: equalsIgnoreCase() with an empty String

    Ugh.  I see that "pattern" way too often in the code of one of my coworkers that I have to maintain now.  (He's still with the company, but he's moved on to another project.)

    The guy's smart, don't get me wrong.  He knows how to write code that does what it's supposed to do, and he can almost always remember exactly where to find "the code that impllements the such-and-such functionality" when I get completely lost and have to ask him for help.  He just... doesn't have such a solid grasp of the details of writing clean code.  Stuff like keeping function sizes down to a manageable length, not making case-insensitive string comparisons against an empty string, or grouping related functionality into a class.

    A lot of his code consists of a single method with 20 local variables or so, 7 or 8 sub-procedures closing over those locals, (some of which have their own sub-procedures,) and then a main method body that's 200-300 lines long.  I used to be bewildered as to why anyone would ever want to write Delphi code that way.  Then I saw some JavaScript that he'd written, and the style was exactly the same, because JS has no classes and so that's basically the only way to do it.  (Though the 200-line function bodies are still a bit excessive.) And JS is his principal language, so I guess he just never learned proper OO style.

    So now I'm just bewildered as to why anyone would ever want to write JavaScript code. I guess it's TRWTF today. :P



  • @Mason Wheeler said:

    Then I saw some JavaScript that he'd written, and the style was exactly the same, because JS has no classes and so that's basically the only way to do it.

    You can do OOP in JS, you just can't (really) do inheritance. So your co-worker is an idiot.

    @Mason Wheeler said:

    So now I'm just bewildered as to why anyone would ever want to write JavaScript code. I guess it's TRWTF today. :P

    Compared to Delphi? JS is a dream.



  • @blakeyrat said:

    @Mason Wheeler said:
    Then I saw some JavaScript that he'd written, and the style was exactly the same, because JS has no classes and so that's basically the only way to do it.

    You can do OOP in JS, you just can't (really) do inheritance. So your co-worker is an idiot.

    @Mason Wheeler said:

    So now I'm just bewildered as to why anyone would ever want to write JavaScript code. I guess it's TRWTF today. :P

    Compared to Delphi? JS is a dream.

     

    If you really feel that way, please share your opinions with our competitors. If they listen, it might improve our competitive advantage.  (Not that we really need it; our Delphi code is the market leader by a long shot and is stomping all over other solutions written in .NET, Java, more .NET, more Java, C++, and Smalltalk.  (Yes, really.  Smalltalk.  Apparently people are still using it somewhere.) )



  • @Mason Wheeler said:

    If you really feel that way, please share your opinions with our competitors. If they listen, it might improve our competitive advantage.  (Not that we really need it; our Delphi code is the market leader by a long shot and is stomping all over other solutions written in .NET, Java, more .NET, more Java, C++, and Smalltalk.  (Yes, really.  Smalltalk.  Apparently people are still using it somewhere.) )

    Every time I see a post like this:

    1) I wonder if Delphi is actually a cult (like its namesake!)

    2) I muse about how similar Delphi developers sound to Lotus Notes developers, who frequently shit out similarly-glowing reviews on every forum they frequent.



  • @Mason Wheeler said:

    Then I saw some JavaScript that he'd written, and the style was exactly the same, because JS has no classes and so that's basically the only way to do it.

    What do classes have to do with writing maintainable code? This statement makes no sense. You can write unmaintainable code with or without classes. And, no, I don't think classes make it easier.



  • @blakeyrat said:

    @Mason Wheeler said:
    If you really feel that way, please share your opinions with our competitors. If they listen, it might improve our competitive advantage.  (Not that we really need it; our Delphi code is the market leader by a long shot and is stomping all over other solutions written in .NET, Java, more .NET, more Java, C++, and Smalltalk.  (Yes, really.  Smalltalk.  Apparently people are still using it somewhere.) )

    Every time I see a post like this:

    1) I wonder if Delphi is actually a cult (like its namesake!)

    2) I muse about how similar Delphi developers sound to Lotus Notes developers, who frequently shit out similarly-glowing reviews on every forum they frequent.

    Well, Lotus Notes was a bit before my time, so I can't really comment on that.  But it's a bit strange to try to argue with solid facts by saying "you're acting like a cultist." And the fact is, our product is the market leader and we're stomping all over the competition.  We've even been growing at a pretty good rate all throughout the recession.  It's the market leader for two reasons: it beats the pants off of the competition in high-stress performance tests, and its interface is more intuitive, easier to use, and a better fit to the domain issues it's designed to handle than the competition's, which means that the end-users love it.

    The high quality of our programs is due to two specific factors: We're careful to only hire good coders who really know what they're doing, and we work in Delphi, which makes writing good code easier.  (Pedantic note: People always misinterpret this.  It means exactly what I said, nothing more.  Specifically, I did not say that Delphi makes writing bad code harder.  I've never seen a language that does that.)



  • @morbiuswilters said:

    @Mason Wheeler said:
    Then I saw some JavaScript that he'd written, and the style was exactly the same, because JS has no classes and so that's basically the only way to do it.

    What do classes have to do with writing maintainable code? This statement makes no sense. You can write unmaintainable code with or without classes. And, no, I don't think classes make it easier.

     

    Among other reasons, because a big part of maintainability is readability, and code is easier to read when it's written in the idiomatic style that other users of the language will recognize.  (Jeff Atwood had a great post about that.)  When the other programmer is expecting classes and instead finds nested sub-procedures closing around local variables (which is basically equivalent to using an object, just done in a very different style,) it's confusing as all heck.



  • @Mason Wheeler said:

    And the fact is, our product is the market leader and we're stomping all over the competition.

    I've worked at places which were clearly the market leader, yet where the developers were idiots and the code was awful. I'm not saying that's the case with your company, just that being market leader proves very little.



  • I remember this conversation, I feel like we had it maybe half a year ago.  Summary: IT'S NOT BECAUSE OF DELPHI.



  • @Mason Wheeler said:

    Among other reasons, because a big part of maintainability is readability, and code is easier to read when it's written in the idiomatic style that other users of the language will recognize.  (Jeff Atwood had a great post about that.)  When the other programmer is expecting classes and instead finds nested sub-procedures closing around local variables (which is basically equivalent to using an object, just done in a very different style,) it's confusing as all heck.

    I agree that readability (and familiarity with conventions) is a good thing. But people can be educated. And by your logic most modern programming languages shouldn't exist, because certainly Java/Delphi/C# were unfamiliar to people when they first came out. In my opinion, I'd prefer to work with programmers who are versed in multiple idioms and paradigms because I think it makes for more flexible, informed thinking. When someone complains that Javascript isn't exactly like Java, I get the feeling they have very limited programming experience.



  • @morbiuswilters said:

    @Mason Wheeler said:
    Among other reasons, because a big part of maintainability is readability, and code is easier to read when it's written in the idiomatic style that other users of the language will recognize.  (Jeff Atwood had a great post about that.)  When the other programmer is expecting classes and instead finds nested sub-procedures closing around local variables (which is basically equivalent to using an object, just done in a very different style,) it's confusing as all heck.

    I agree that readability (and familiarity with conventions) is a good thing. But people can be educated. And by your logic most modern programming languages shouldn't exist, because certainly Java/Delphi/C# were unfamiliar to people when they first came out. In my opinion, I'd prefer to work with programmers who are versed in multiple idioms and paradigms because I think it makes for more flexible, informed thinking. When someone complains that Javascript isn't exactly like Java, I get the feeling they have very limited programming experience.

    +1



  • @morbiuswilters said:

    I agree that readability (and familiarity with conventions) is a good thing. But people can be educated. And by your logic most modern programming languages shouldn't exist, because certainly Java/Delphi/C# were unfamiliar to people when they first came out.

    They were all similar enough to existing languages to take off well.  Java explicitly designed as "a better C++".  Delphi was an evolution of Turbo Pascal with object-oriented programming and visual/RAD design elements.  And C# was essentially Delphi rewritten to look like Java.  And even if they hadn't been, there's a difference between "learning a newly-created language" and "working with a well-established, mature language that does have accepted conventions and idioms and not using them."

    In my opinion, I'd prefer to work with programmers who are versed in multiple idioms and paradigms because I think it makes for more flexible, informed thinking. When someone complains that Javascript isn't exactly like Java, I get the feeling they have very limited programming experience.
     

    Oh, I certainly agree.  But if you found someone who knew both Javascript and Java, who knew what the difference was, but who wrote all their Java code in JS idioms instead of Java idioms, what would you think of that developer's programming experience?


  • ♿ (Parody)

    @Mason Wheeler said:

    Oh, I certainly agree.  But if you found someone who knew both Javascript and Java, who knew what the difference was, but who wrote all their Java code in JS idioms instead of Java idioms, what would you think of that developer's programming experience?

    I'm confused. It seemed that morbs' point was about your ignorance of javascript idioms (or indeed, anything that wasn't OOP), and your exclamation that there's no way other than The One True OOP Way to write maintainable code. Now you're making his argument for him. Was that just a sneaky retraction?



  • @Mason Wheeler said:

    [...] who wrote all their Java code in JS idioms instead of Java idioms, what would you think of that developer's programming experience?

    Is that even possible? Granted, I've not touched Java in 5+ years, but I can't imagine the insanity that would be required to do JS in Java.

    Fake Edit: Non matching quote blocks in post I thought CS prefered to mangle text than throw an error?



  • @boomzilla said:

    @Mason Wheeler said:
    Oh, I certainly agree.  But if you found someone who knew both Javascript and Java, who knew what the difference was, but who wrote all their Java code in JS idioms instead of Java idioms, what would you think of that developer's programming experience?

    I'm confused. It seemed that morbs' point was about your ignorance of javascript idioms (or indeed, anything that wasn't OOP), and your exclamation that there's no way other than The One True OOP Way to write maintainable code. Now you're making his argument for him. Was that just a sneaky retraction?

     

    I certainly didn't say anything as absolutist as that.  But when you're working in an OO language, using non-OO tricks to emulate classes based on an idiom from a language that does not have classes is not very good for maintainability when you could just use a class instead.  That's what it's there for.  Can we all agree on that much at least?  Because that's the point I was actually trying to make



  • @pkmnfrk said:

    @Mason Wheeler said:
    [...] who wrote all their Java code in JS idioms instead of Java idioms, what would you think of that developer's programming experience?

    Is that even possible? Granted, I've not touched Java in 5+ years, but I can't imagine the insanity that would be required to do JS in Java.

    Fake Edit: Non matching quote blocks in post I thought CS prefered to mangle text than throw an error?

     

    No idea.  I haven't even touched Java since college, though from what I've heard, Java *still* doesn't have any form of closures or nested procedures, so this particular form of abuse would probably not be possible in Java.

     


  • ♿ (Parody)

    @Mason Wheeler said:

    @boomzilla said:
    I'm confused. It seemed that morbs' point was about your ignorance of javascript idioms (or indeed, anything that wasn't OOP), and your exclamation that there's no way other than The One True OOP Way to write maintainable code. Now you're making his argument for him. Was that just a sneaky retraction?

    I certainly didn't say anything as absolutist as that.

    Here's what you said:

    @Mason Wheeler said:

    Then I saw some JavaScript that he'd written, and the style was exactly the same, because JS has no classes and so that's basically the only way to do it.

    I think my interpretation is fair.

    @Mason Wheeler said:

    But when you're working in an OO language, using non-OO tricks to emulate classes based on an idiom from a language that does not have classes is not very good for maintainability when you could just use a class instead.  That's what it's there for.  Can we all agree on that much at least?  Because that's the point I was actually trying to make

    Agree on what? From your description, the Delphi code was a mess. Also, so was the javascript code. I think we can agree that both suck. But you said "that's basically the only way to do it," which just makes you look dumb. Javascript supports at least functional and imperative, OO and procedural idioms.



  • @Mason Wheeler said:

    Java still doesn't have any form of closures or nested procedures, so this particular form of abuse would probably not be possible in Java.

    Java's had anonymous inner classes forever. Although the syntax is painful and they require an interface or class to extend to use them effectively, these can be used in much the same way as closures.

    Many of us who still use Java (or at least the JVM) and want to use features like this have moved on to Groovy or Scala, though.



  • @Mason Wheeler said:

    The high quality of our programs is due to two specific factors: We're careful to only hire good coders who really know what they're doing,

    It sounds like that's the only "specific factor" that makes a difference. If they know what they're doing, they'd know what they're doing in ANY language.

    Except the one guy you're bitching about who apparently got hired even though he doesn't know what he's doing, but I'll ignore that for the moment.



  • @Thuktun said:

    Java's had anonymous inner classes forever. Although the syntax is painful and they require an interface or class to extend to use them effectively, these can be used in much the same way as closures.

    No. Anonymous classes/functions are not the same thing as closures. Closures are often implemented via anonymous functions, but they are conceptually distinct.



  • @Mason Wheeler said:

    But when you're working in an OO language, using non-OO tricks to emulate classes based on an idiom from a language that does not have classes is not very good for maintainability when you could just use a class instead.

    JavaScript is an OO language. As I've posted above.

    Please learn something about JavaScript before offering an opinion on it.



  • @Mason Wheeler said:

    Oh, I certainly agree.  But if you found someone who knew both Javascript and Java, who knew what the difference was, but who wrote all their Java code in JS idioms instead of Java idioms, what would you think of that developer's programming experience?

    Now I'm confused. Re-reading the thread, it seems you implied that JS doesn't have proper OO, which I disagree with. However, it seems your complain about conventions wasn't about JS conventions themselves, but about applying JS conventions to Delphi, which I agree is a reasonable objection.



  • @morbiuswilters said:

    Now I'm confused. Re-reading the thread, it seems you implied that JS doesn't have proper OO, which I disagree with.

    On what grounds?  The essence of OOP, the thing that makes it different from procedural programming, is language-level support for Liskov substitution, which is based on inheritance and polymorphism.  If your language has every other feature of [insert OO language here] but no Liskov substitution, then you don't have OOP, you have procedural programming with an object-style syntax.  And JavaScript doesn't have inheritance...



  • @boomzilla said:

    Here's what you said:

    @Mason Wheeler said:

    Then I saw some JavaScript that he'd written, and the style was exactly the same, because JS has no classes and so that's basically the only way to do it.

    I think my interpretation is fair.

     

    Huh?  How exactly do you get from "the only way to do class-style encapsulation in JavaScript is with sub-procedures acting as closures around variables that are local to an outer procedure" to "there's no way other than The One True OOP Way to write maintainable code"?  There's a leap of logic there somewhere that I'm just not following.  I don't even believe that there's no way other than The One True OOP Way to write maintainable code.  I grew up on BASIC, ASM, C and Pascal.  I recognize the benefits of OO because I learned to code without them, but I also know that it's not the best tool for every job.  When I have a task that doesn't map well to the OO paradigm, I don't write the solution in OO style.

     



  • @blakeyrat said:

    @Mason Wheeler said:
    The high quality of our programs is due to two specific factors: We're careful to only hire good coders who really know what they're doing,

    It sounds like that's the only "specific factor" that makes a difference. If they know what they're doing, they'd know what they're doing in ANY language.

     

    As obnoxious as Paul Graham is, I think I'm gonna have to invoke the Blub Paradox here.

     



  • @Mason Wheeler said:

    The essence of OOP, the thing that makes it different from procedural programming, is language-level support for Liskov substitution, which is based on inheritance and polymorphism.

    Bunk.

    The essence of OOP is that the data and the functions that operate on the data are stored in the same container. JavaScript has that. The first sentence in Wikipedia's article on prototype-based programming starts: "Prototype-based programming is a style of object-oriented programming..."

    Inheritance and polymorphism are not required for OOP. What you're describing could be called "Class-based languages" I suppose. (And, in fact, that appears to be exactly what Wikipedia calls them.) JavaScript is OOP, but it does not have classes.


  • ♿ (Parody)

    @Mason Wheeler said:

    @boomzilla said:
    Here's what you said:
    @Mason Wheeler said:
    Then I saw some JavaScript that he'd written, and the style was exactly the same, because JS has no classes and so that's basically the only way to do it.

    I think my interpretation is fair.

    Huh?  How exactly do you get from "the only way to do class-style encapsulation in JavaScript is with sub-procedures acting as closures around variables that are local to an outer procedure" to "there's no way other than The One True OOP Way to write maintainable code"?

    I guess when you actually say that, instead of what you actually said, it sounds much more reasonable. I think you left out a little bit of that when you originally typed what you typed. But, while I'm no javascript expert, I suspect that you're still incorrect, and that another way to do it is to use the actual inheritance the javascript has, which is to say, prototypal inheritance.

    @Mason Wheeler said:

    When I have a task that doesn't map well to the OO paradigm, I don't write the solution in OO style.

    And you've got an incomplete idea of what OO style actually is.



  •  @blakeyrat said:

    @Mason Wheeler said:
    The essence of OOP, the thing that makes it different from procedural programming, is language-level support for Liskov substitution, which is based on inheritance and polymorphism.

    Bunk.

    The essence of OOP is that the data and the functions that operate on the data are stored in the same container.

    That's just an implementation detail.  Any object method can be rewritten as a procedural routine that takes an extra parameter for the object reference, and it will do exactly the same thing.  You can even do that (trivially) in C, just with structs instead of objects.  But you can't do Liskov substitution in C.  It's something that you can only do with compiler support, and it's what makes OO languages different from non-OO languages, and even from non-OO languages that adopt object syntax because someone thought it looks cool.  (Like Javascript.)

    The first sentence in Wikipedia's article on prototype-based programming starts: "Prototype-based programming is a style of object-oriented programming..."

    ...and we all know that Wikipedia is an infallible, authoritative source!

    They call prototype-based programming OO because it's cool to be OO, but that doesn't make it true.  What can you do with the prototype model that you can't trivially emulate in C?

     



  • @Mason Wheeler said:

    The essence of OOP, the thing that makes it different from procedural programming, is language-level support for Liskov substitution, which is based on inheritance and polymorphism.

    This is so wrong, I don't know where to start. I would say the essence of OOP is actually three things: encapsulation; inheritance; and polymorphism. Javascript has inheritence (just not class-based inheritence)*. Javascript is capable of polymorphism.

    Liskov substitution is not a language feature, it is a design principle. Of course, your language has to support subtype polymorphism to even get to the point where Liskov becomes relevant, but Javascript does. And there are plenty of people (like the GoF) who think that most Liskov violations are due to inheritance and that composition should be preferred.

    Long story short: your understanding of OOP is limited and has been warped by only being exposed to class-based languages.

    *In casual conversation most people (myself included) would say Javascript lacks inheritance, but what is really meant by this is class-based inheritance.



  • @Mason Wheeler said:

    ...and we all know that Wikipedia is an infallible, authoritative source!

    They call prototype-based programming OO because it's cool to be OO, but that doesn't make it true.

    Seriously, you are the first person I've ever encountered who doesn't know that prototype-based programming is OO. You may not like prototype-based languages, but that doesn't change the fact that this is firmly settled CS.

    @Mason Wheeler said:

    What can you do with the prototype model that you can't trivially emulate in C?

    What the fuck does that have to do with anything?


  • ♿ (Parody)

    @Mason Wheeler said:

    That's just an implementation detail.  Any object method can be rewritten as a procedural routine that takes an extra parameter for the object reference, and it will do exactly the same thing.  You can even do that (trivially) in C, just with structs instead of objects.  But you can't do Liskov substitution in C.  It's something that you can only do with compiler support, and it's what makes OO languages different from non-OO languages, and even from non-OO languages that adopt object syntax because someone thought it looks cool.  (Like Javascript.)

    I'm not interested in a pedantic dickweed contest about programming paradigms, but to show that you are ignorant of javascript, here's an article about Liskov Substitution in Javascript. Oops.



  • @morbiuswilters said:

    And there are plenty of people (like the GoF) who think that most Liskov violations are due to inheritance and that composition should be preferred.

    That's a ridiculous statement.  What would you think if someone said, "there are plenty of people who think that most car accidents are due to driving, and that flying should be preferred."  Inheritance isn't the "cause" of Liskov violations except insofar as that it is what makes the Liskov substitution principle possible in the first place.  People using inheritance badly is the cause of Liskov violations, and the solution isn't to avoid inheritance, but to use it right, and to only use it when appropriate.

    "Favor composition over inheritance" makes about as much a sense as "favor saws over drills."  They're different tools which are each appropriate for different purposes, and talking like you can replace one with another is just silly.



  • @morbiuswilters said:

    @Mason Wheeler said:
    What can you do with the prototype model that you can't trivially emulate in C?

    What the fuck does that have to do with anything?

     

    Because I'm talking about what differentiates OOP from procedural programming.  If you can trivially accomplish everything that an OO language brings to the table in a non-OO language, then you don't have a different paradigm, you just have procedural programming with funny syntax.  As I said several posts ago.

     



  • @Mason Wheeler said:

    @morbiuswilters said:

    And there are plenty of people (like the GoF) who think that most Liskov violations are due to inheritance and that composition should be preferred.

    That's a ridiculous statement.  What would you think if someone said, "there are plenty of people who think that most car accidents are due to driving, and that flying should be preferred."  Inheritance isn't the "cause" of Liskov violations except insofar as that it is what makes the Liskov substitution principle possible in the first place.  People using inheritance badly is the cause of Liskov violations, and the solution isn't to avoid inheritance, but to use it right, and to only use it when appropriate.

    "Favor composition over inheritance" makes about as much a sense as "favor saws over drills."  They're different tools which are each appropriate for different purposes, and talking like you can replace one with another is just silly.

    Many of the "big thinkers" think inheritance causes more harm than good. Even James Gosling once said that the one thing he'd change if he did Java over again would be to not support inheritance, only interfaces.



  • @boomzilla said:

    @Mason Wheeler said:

    That's just an implementation detail.  Any object method can be rewritten as a procedural routine that takes an extra parameter for the object reference, and it will do exactly the same thing.  You can even do that (trivially) in C, just with structs instead of objects.  But you can't do Liskov substitution in C.  It's something that you can only do with compiler support, and it's what makes OO languages different from non-OO languages, and even from non-OO languages that adopt object syntax because someone thought it looks cool.  (Like Javascript.)

    I'm not interested in a pedantic dickweed contest about programming paradigms, but to show that you are ignorant of javascript, here's an article about Liskov Substitution in Javascript. Oops.

     

    Only if you really stretch things, as this author did.

    He even quoted the LSP up at the top: Subtypes must be substitutable for their base types.  And then he goes and gives an answer that has nothing to do with base types and subtypes, and calls it Liskov Substitution?  And then to justify it, he makes the completely unfounded assertion that it's not really about inheritance, it's about "behavior."  Caroll's Humpty Dumpty comes to mind...

     



  • @Mason Wheeler said:

    @morbiuswilters said:

    @Mason Wheeler said:
    What can you do with the prototype model that you can't trivially emulate in C?

    What the fuck does that have to do with anything?

     

    Because I'm talking about what differentiates OOP from procedural programming.  If you can trivially accomplish everything that an OO language brings to the table in a non-OO language, then you don't have a different paradigm, you just have procedural programming with funny syntax.  As I said several posts ago.

     

    That's a silly conclusion to draw. First off, I take issue with your use of "trivial"; I would hardly consider most aspects of OOP (prototype or class) to be trivial to implement in C. And since any OOP language can be represented in C (after all, most of the runtimes are written in C) it seems like a meaningless metric. Regardless, C++ was implemented for a while in the C preprocessor and I doubt most people would consider it a non-OOP language.


Log in to reply