Most active commenters

    ←back to thread

    294 points ulrischa | 19 comments | | HN request time: 1.889s | source | bottom
    Show context
    nozzlegear ◴[] No.42174177[source]
    For anyone who didn't click through to the WebKit bug report the author submitted, a WebKit dev asked him to clarify why the BBC finds it beneficial to be able to detect that the event was sent from a keyboard. This is the author's response:

    > Ironically, I want interoperability on this to help with use cases relating to accessibility.

    > I work at the BBC and, on our UK website, our navigation bar menu button behaves slightly differently depending on if it is opened with a pointer or keyboard. The click event will always open the menu, but:

    > - when opening with a pointer, the focus moves to the menu container.

    > - when opening with a keyboard, there is no animation to open the menu and the focus moves to the first link in the menu.

    > Often when opening a menu, we don't want a slightly different behaviour around focus and animations depending on if the user 'clicks' with a pointer or keyboard.

    > The 'click' event is great when creating user experiences for keyboard users because it is device independent. On keyboards, it is only invoked by Space or Enter key presses. If we were to use the keydown event, we would have to check whether only the the Space or Enter keys were pressed.

    Source: https://bugs.webkit.org/show_bug.cgi?id=281430

    replies(5): >>42174432 #>>42174435 #>>42174511 #>>42174692 #>>42175176 #
    1. amluto ◴[] No.42175176[source]
    This is fascinating, because the naive English interpretation of the code and the comment on that WebKit bug don't match the actual structure of the code. Here's the relevant code:

        const isInvokedByMouse = event => event.screenX > 0 || event.screenY > 0;
        const isInvokedByKeyboard = event => isEnterKey(event) || isSpaceKey(event);
    
    Ignoring the actual conditions entirely, this code seems to be trying to categorize the event into one of two categories: mouse or keyboard. But what it actually does is to categorize into one of four categories: (mouse and not keyboard), (keyboard and not mouse), (keyboard and mouse), and (neither keyboard nor mouse). And, as the original bug shows, (neither keyboard nor mouse) is handled inappropriately. One might wonder whether (keyboard and mouse) works well.

    Either the code should be deliberate about the fact that (is it a keyboard) and (is it a mouse) are separate booleans, or the code should be structured so that the actual categories are mutually exclusive. For example:

        const isInvokedByMouse = ...
    
    and use !isInvokedByMouse to check for keyboardiness, or:

        const eventSource = ... (returns "keyboard" or "mouse")
    
    or, perhaps even better:

        const eventSource = ... (returns "keyboard", "mouse", or "not sure")
    replies(4): >>42176623 #>>42177520 #>>42179647 #>>42186662 #
    2. nightpool ◴[] No.42176623[source]
    This is a great comment ^ whenever you use two booleans like this, you're opening yourself up to "unrepresentable state" logic errors. Finding and noticing this in code can be tricky, but it's a great example of something that should be caught during code review.
    replies(1): >>42177164 #
    3. politelemon ◴[] No.42177164[source]
    Not sure if exactly the same thing but reminds me of "Booleans are a trap"

    https://katafrakt.me/2024/11/09/booleans-are-a-trap/

    replies(3): >>42178236 #>>42179492 #>>42182882 #
    4. robocat ◴[] No.42177520[source]
    And just to add an extra corner case, Mobile Safari changes the click behavior if an onclick handler is registered - even if the click handler is an empty function that does nothing. The onclick handler itself acts as another Boolean that affects the browser's behavior. I don't remember the exact details because it was a corner case (I think to do with scrolling or popovers or touchcancel - I know it was surprisingly nasty). This page mentions something else http://www.quirksmode.org/blog/archives/2010/09/click_event_... "Fortunately it’s pretty easy to solve: you have to make the element clickable by giving it an onclick event handler of its very own. That handler can be empty; as long as it’s present it will make any element clickable.".
    5. iwontberude ◴[] No.42178236{3}[source]
    Yet another article prematurely optimizing. It’s like these people have nothing better to do. I’ll wait for my code to get into stupid edge cases first and then fix it. Even if you spend your time avoiding booleans you will still find yourself with some new contradictory state and have to fix it differently anyways.
    replies(3): >>42178418 #>>42178795 #>>42179765 #
    6. amluto ◴[] No.42178418{4}[source]
    Huh? This isn’t premature optimization unless you consider trying to write correct code “optimizing”.
    7. lmm ◴[] No.42178795{4}[source]
    Coming up with proper representation for your state is almost always worth it. If anything it's the opposite of premature optimisation - normalise first, only denormalise after you've proven that it's needed.
    8. lvturner ◴[] No.42179492{3}[source]
    Wait—that last state doesn't make sense. With a real door, you can technically turn the key while it's open, but does that meaningfully change its state? Yet our model allows this impossible combination.

    Funnily enough, I have a physical door & lock that OFTEN gets in to this state - it's exactly as irritating as it sounds, and it has very meaningful impact on it's state (it then can't be closed without first unlocking the lock!)

    replies(1): >>42185470 #
    9. taneq ◴[] No.42179647[source]
    Well said. I usually go through several phases when dealing with this kind of thing, I start with "flags for different conditions" type logic, then when things get too complex I refine this into "set of explicitly defined states", and then as the state code evolves from 'ideal happy path' to 'production-tested code' I gradually realise that most of the original combinations represented by the original flags actually CAN happen in weird edge-cases.
    replies(1): >>42180092 #
    10. liontwist ◴[] No.42179765{4}[source]
    The issue isn’t booleans the issue is that the code doesn’t handle all the states described by the two booleans, when all are possible.
    replies(1): >>42180130 #
    11. chii ◴[] No.42180092[source]
    > "set of explicitly defined states"

    this is called algebraic data type (https://en.wikipedia.org/wiki/Algebraic_data_type), and it is the best way, imho, to reduce bugs in code.

    By making it easy to pattern match, it reduces the possiblity of producing an invalid state, because at the time of definition, you have to figure out how to get that type (and checked by compiler).

    12. cma ◴[] No.42180130{5}[source]
    Make the impossible states unrepresentable using an enum of only the possible boolean combinations.
    replies(2): >>42181949 #>>42184086 #
    13. dpig_ ◴[] No.42181949{6}[source]
    Isn't that exactly what the article prescribes?
    14. enugu ◴[] No.42182882{3}[source]
    This is a good account of a software modelling process. But, this is not specific to booleans. Database constraints involve the same issue. One motivation for encapsulation in software was to preserve constraints in the data (or in other words, disallow improper states). Encapsulation allows only internal functions to manipulate the data, and the developer just needs to checks that these functions are doing it correctly.

    Or, as pointed out in the post where multiple booleans are merged into a single enum, encode the constraints into the data itself ie. use the constraints of the host programming language.

    But this wont be possible in general - for instance if your language doesn't have sets/dictionaries, how would you encode uniqueness of values directly using arrays and lists? It would have to be done using interface functions.

    15. liontwist ◴[] No.42184086{6}[source]
    Did you read the context?
    replies(1): >>42186035 #
    16. pryelluw ◴[] No.42185470{4}[source]
    I’ve come to the conclusion that most programming problems like this can be solved my having programmers work as building superintendents for 3 months. Practical experience will open their eyes to how the world really works.
    replies(1): >>42190126 #
    17. cma ◴[] No.42186035{7}[source]
    No I read wrong and missed it. If all four states are actually possible an enum can still be a win if you have a compiler that can check for exhaustive switch case statements. Or especially if updating a system where it used to be only three were valid and now something changed so that all four are.
    18. klysm ◴[] No.42186662[source]
    I frequently use algebraic thinking to verify my sanity with types. Bool times bool is 4. We have two states we want to represent so bool times bool so the wrong thing.
    19. lvturner ◴[] No.42190126{5}[source]
    This leads to another wonderful gap, where programmers are expected to understand the world[0], but the world isn't expected to understand programming[1]

    [0] Business, etc

    [1] System design, security, database management, cost vs speed trade-offs, SCM, etc etc etc