ThreadSleep webservice


  • I survived the hour long Uno hand

    I used to quite like checked exceptions because they make you plan for edge cases, but I'm slowly changing my mind. I mean, I KNOW a file could be not found. If it's not found I have jack all I can do about it at this point, because I just wrote it myself, and I did an exists check. If the file system's actively hostile, my program should just give up and die. So I don't want to catch the exception at all.


  • Discourse touched me in a no-no place

    @tarunik said:

    although vexing exceptions are a sign of a library design flaw

    Not always. You cannot prevent users from giving you shitty input, and sometimes you can't tell that the input is bad until you're deep inside the program (e.g., by the time you've got the information, you're about at the point where you'd act on it anyway).

    @Jaime said:

    It sounds like you are talking about Java's "checked exceptions". The .Net design team isn't terribly impressed with the idea.

    I was only tangentially talking about that, and in fact it's not closely related to what I was really talking about. (The manner in which an exception should be reported to the user is really orthogonal to whether it is a checked failure.) The biggest problem with the .NET approach is that it leaves you with “anything could go wrong at any point lol” which makes working out what you want to actually handle rather vexing; failures should always be handled at the point that is best equipped to decide what to do about it. (Sometimes that's throw it in the user's face, sometimes not.)

    It's a bit of an empty debate though, as both sides tend to start out with “haha look at those morons over there”, and it's difficult to advance beyond that as everyone is already not listening.

    I do wish that InterruptedException had been unchecked though. Hardly anything ever really wants to deal with it sensibly…



  • @dkf said:

    Not always. You cannot prevent users from giving you shitty input, and sometimes you can't tell that the input is bad until you're deep inside the program (e.g., by the time you've got the information, you're about at the point where you'd act on it anyway).

    Indeed you cannot -- but reporting bad input by way of an exception is what gives you vexing exceptions, as "the user passed me rubbish" is a good example of a non-exceptional error condition. You may use exceptions to deal with this internally as an implementation detail (for instance, a ParseError object being thrown from deep within a recursive descent parser), but letting that ParseError fly out the door of your parser API as an exception simply frustrates folks who go to use your API. In that case, tools like Maybe and Either are your best friends...



  • @tarunik said:

    "the user passed me rubbish" is a good example of a non-exceptional error condition.

    There's a C++ YAML library out there somewhere which throws an exception if it tries to parse an input file which isn't correctly formatted. That was the straw which motivated me to switch to a C library instead. Suck it up, sunshine, there ain't anything exceptional about bad input data—that's just business as usual...


  • Discourse touched me in a no-no place

    @tarunik said:

    letting that ParseError fly out the door of your parser API as an exception simply frustrates folks who go to use your API

    I prefer to let the exception go out and have the framework map it to the error case that is reported to the user (it's a web app, so an HTTP 400 or 500 is the right sort of thing to do). The alternative, returning success but requiring the client to parse the response document to find out if it was a real success or a failure, is really criminally nasty.

    I understand what you're saying about Maybe/Either types, but I explicitly reject it. 😄 I take the view that normal clients of an API should get strong guarantees about what is returned, especially if they're unlikely to trigger a failure mode. I thus make the exception part of the API; it strengthens the normal-case result (e.g., by letting you guarantee that an object is correctly constructed, and that the result is never null).

    As I said before, this appears to be an area where C++, C# and Java really don't agree at all.


  • :belt_onion:

    @dkf said:

    returning success but requiring the client to parse the response document to find out if it was a real success or a failure, is really criminally nasty.

    Ick. Ick ick ick. Do not want.

    200 should indicate that... well... you were successful. NOTHING MORE. EVER.



  • @dkf said:

    I prefer to let the exception go out and have the framework map it to the error case that is reported to the user (it's a web app, so an HTTP 400 or 500 is the right sort of thing to do).

    That's an interesting case, because it's a reverse situation -- instead of you calling library code and getting an error back, you have a framework calling you with expectations about how you report errors to it. The only sane way to deal with this is to do as the Romans do when you arrive in Rome.

    @dkf said:

    I understand what you're saying about Maybe/Either types, but I explicitly reject it. I take the view that normal clients of an API should get strong guarantees about what is returned, especially if they're unlikely to trigger a failure mode. I thus make the exception part of the API; it strengthens the normal-case result (e.g., by letting you guarantee that an object is correctly constructed, and that the result is never null).

    How is a Maybe/Either type any less contractual than making the exception part of the API? (Then again, I'm thinking from a strong statically-typed perspective, such as Haskell ;) )

    @dkf said:

    The alternative, returning success but requiring the client to parse the response document to find out if it was a real success or a failure, is really criminally nasty.

    This is grounds for being DDoSed by the entire Internet for all eternity ;)



  • @dkf said:

    It's a bit of an empty debate though, as both sides tend
    to start out with “haha look at those morons over there”, and it's difficult to advance

    Yeah, I think you nailed it here: Error handling is something that requires balance, yet the debate appears to be polarized.

    Specifically, the C# team's decision to omit checked exceptions altogether was an overreaction to the annoyance of Java's checked exceptions, and they are something that I really miss when working in C# (not that I've been handling a lot of exceptions lately, but the fact that I don't have empty catch blocks everywhere there could be an exception—just everywhere that I've caught one so far—feels like an order of magnitude more technical debt than what I'm used to).

    What would be nice is if they had throws Exception be the default, like C# currently, but also allowed you to add exception specifications, which if added guarantee that exceptions will only be of the specified types. Also it might be nice to have some kind of syntax for autowrapping un handled exceptions in a generic SomethingWentWrongException, for situations like @Yamikuronue described, or where there might be one type of checked exception that you're able to handle and the rest are fatal.


  • Discourse touched me in a no-no place

    @Buddy said:

    Error handling is something that requires balance

    QFT.

    I think it's reasonable to be able to state that you've got a certain set of failures that it is advisable for callers to be able to deal with. Doing I/O? Better be prepared for it to go wrong (as it is inevitably inclined to do from time to time).

    But I also think that too many exceptions in Java are checked when they ought to not be. Oh well.

    (The C++ approach, which might be summed up as “Exceptions? 🙀”, really irritates.)


  • Discourse touched me in a no-no place

    @tarunik said:

    This is grounds for being DDoSed by the entire Internet for all eternity

    I've seen it way too often in services developed by scientists. They've even managed to write their own specifications to require the behaviour, as well as requiring the ability to do SQL injection if you can figure out how to trick your way past the awful argument syntax, and then they wonder why I want to lock their damn services down hard…

    :facepalm:

    Fortunately, this isn't the current crew I'm working with.



  • So why do you need the userID and mandantID to sleep. They're not used for anything other than logging, but who really cares that some action that they figured justified a call to sleep was required by that user doing whatever?

    Of course it would be brillant if it was called something like this:

    // Optimized to maker code faster.
    public async void CallThreadSleep()
    { 
        await Task.Run(() => ThreadSleep("1", "2", "idiot"));
    }
    

    I'm still new here. Can't get my lame code joke to paste properly. It is indented by 4 spaces. So what must I do to get this discoshit to format correctly? I fucking hate markdown. (Edit: Oh, never mind. It was just the fucking preview not shading the code.)



  • @Buddy said:

    Specifically, the C# team's decision to omit checked exceptions altogether was an overreaction to the annoyance of Java's checked exceptions

    No it wasn't. They recognized that checked exceptions make the contract fragile and they didn't think that fragility was worth the benefit. The contract fragility comes from the fact that if any framework method you call ever declares a new checked exception, then your already deployed binaries either become invalid or magically sprout a new checked exception.


  • FoxDev

    @Jaime said:

    They recognized that checked exceptions make the contract fragile and they didn't think that fragility was worth the benefit.

    Plus checked exceptions make it all too easy to litter your code with catch (Exception e) instead of catching only what you should catch, because developers are lazy and/or work to deadlines, and just want to get the code working so they can go home and play games or something.


  • Discourse touched me in a no-no place

    @Jaime said:

    The contract fragility comes from the fact that if any framework method you call ever declares a new checked exception, then your already deployed binaries either become invalid or magically sprout a new checked exception.

    You get the fragility if you increase the range of the exception set anyway. With unchecked exceptions, you just get that fragility expressed as the code blowing up unexpectedly in production.

    @RaceProUK said:

    Plus checked exceptions make it all too easy to litter your code with catch (Exception e) instead of catching only what you should catch

    The only way you don't get that sort of problem is if you don't have a common superclass of exceptions (and that has unpleasant consequences, such as problems tracking what the hell just happened when things do blow up).

    tl;dr: Terrible developers are terrible. News at 11.



  • @dkf said:

    You get the fragility if you increase the range of the exception set anyway. With unchecked exceptions, you just get that fragility expressed as the code blowing up unexpectedly in production.

    Agreed, the fragility already exists. The problem is that the fragility is promoted from a general programming problem to a contract problem. .Net has real generics, so it becomes a very complex problem to determine what exceptions List<T>.Sort may throw since it calls ((IComparable)T).CompareTo. Java gets around this by demoting generics to a compiler feature rather than a runtime feature.

    Also, checked exceptions really don't solve the problem. Example:

    • Framework method Foo throws checked exception ImOnFireException.
    • Application method Bar calls Foo.

    Of course, the compiler will require you to catch or re-throw ImOnFireException when you write and compile your application. However, if a new version of the framework adds checked exception HolyCrapABadgerException, there are several possibilities:

    • This is not allowed. This isn't terribly reliable since you can't enforce it with technology and it prevents evolution of components.
    • The caller becomes invalid. This creates the same "unexpectedly blows up in production problem". Even worse, it creates the problem even when no badgers are present.
    • The caller implicitly re-throws it. This invalidates the entire point of checked exceptions and gets you back to the exact same "unexpectedly blows up in production problem" as if checked exception didn't exist.

    The only option that actually works is the first and it's pretty restrictive. In Java, it might work due to the lack of runtime generics. In .Net, it's totally infeasible since a generic can never know a priori what "T" might do.



  • @Jerome_Viveiros said:

    So what must I do to get this discoshit to format correctly? I fucking hate markdown.

    I think you should fit right in here!

    Filed under: shmarkdown, amirite?



  • @dkf said:

    The C++ approach, which might be summed up as “Exceptions? ”, really irritates.

    try {
        throw new int(100);
    
    } catch(...) {
        printf("what do you want me to do about it?");
    }
    

  • BINNED

    @tar said:

    ```c++
    try {
    throw new int(100);
    } catch(...) {
    printf("Fuck it, have a core dump!");
    int *p = NULL;
    *p = 1;
    }

    
    FTFY


  • @Onyx said:

    @tar said:
    ```
    #include <signal.h>

    static void fuckitall(int sig, siginfo_t *info, void *context) {
    printf("Fuck it, have a core dump!");
    int *p = NULL;
    *p = 1;
    }

    int main() {
    try {
    struct sigaction old_action;
    struct sigaction new_action = {{0}};
    new_action.sa_sigaction = fuckitall;
    new_action.sa_flags = SA_SIGINFO;
    sigaction(SIGILL, &new_action, &old_action);
    sigaction(SIGBUS, &new_action, &old_action);
    sigaction(SIGSEGV, &new_action, &old_action);

        throw new int(100);
    } catch(...) {
        printf("Fuck it, have a core dump!");
        fuckitall();
    }
    

    }

    FTFY</blockquote>
    
    I made it into a thing of beauty...
    
    Also, blank lines in code blocks don't... work... U_U
    
    **EDIT:** Replaced <code>\`\`\`c++</code> with <code>\`\`\`</code> as that seems to 'fix' the indented code in quotes business... (and the syntax highlighting is unaffected by that anyway...)

  • BINNED

    @tar said:

    Also, blank lines in code blocks don't... work... U_U

    Not in quotes, no.

    I'd complain about it in my last post. But I'm tired of complaining about Discourse. I'm even tired of complaining about others complaining.



  • @Onyx said:

    Not in quotes, no.

    And yet:

    ``` void some function() { indented stuff;
    indented stuff;
    
    
    I think it's the c++ language selection that upsets it....
    
    <blockquote>```c++
    void some function() {
        indented stuff;
    
        indented stuff;
    
    ```</blockquote>
    
    Boom!

  • BINNED

    @tar said:

    I think it's the c++ language selection that upsets it....

    I won't lie, there are times when I agree with Discourse.


  • Discourse touched me in a no-no place

    I'd probably go for calling abort() with a backup of sending a SIGKILL to the process. [spoiler]Bonus for holding open connections to an Oracle DB in that case…[/spoiler]


  • BINNED

    That sounds suspiciously like having some kind of competence and/or knowledge. We don't take kindly to that here.



  • @tar said:

    I made it into a thing of beauty...

    Or not.

    Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x64
    Copyright (C) Microsoft Corporation. All rights reserved.

    x.cpp
    x.cpp(3) : error C2061: syntax error : identifier 'siginfo_t'
    x.cpp(4) : error C3861: 'printf': identifier not found
    x.cpp(5) : error C2065: 'NULL' : undeclared identifier
    x.cpp(10) : warning C4530: C++ exception handler used, but unwind semantics are
    not enabled. Specify /EHsc
    x.cpp(11) : error C2079: 'old_action' uses undefined struct 'main::sigaction'
    x.cpp(12) : error C2079: 'new_action' uses undefined struct 'main::sigaction'
    x.cpp(12) : error C2440: 'initializing' : cannot convert from 'initializer-list'
    to 'int'
    Only an initializer-list with zero or one elements can be converted to t
    his type
    x.cpp(13) : error C2228: left of '.sa_sigaction' must have class/struct/union
    type is 'int'
    x.cpp(14) : error C2228: left of '.sa_flags' must have class/struct/union
    type is 'int'
    x.cpp(14) : error C2065: 'SA_SIGINFO' : undeclared identifier
    x.cpp(15) : error C2514: 'main::sigaction' : class has no constructors
    x.cpp(11) : see declaration of 'main::sigaction'
    x.cpp(16) : error C2065: 'SIGBUS' : undeclared identifier
    x.cpp(17) : error C2514: 'main::sigaction' : class has no constructors
    x.cpp(11) : see declaration of 'main::sigaction'
    x.cpp(21) : error C3861: 'printf': identifier not found
    x.cpp(22) : error C2660: 'fuckitall' : function does not take 0 arguments



  • PRs accepted!



  • @Jerome_Viveiros said:

    what must I do to get this discoshit to format correctly?

    Type everything in html, just like you had to with Community Server.



  • @flabdablet said:

    Type everything in html, just like you had to with Community Server.

    Except this time, half of the HTML silently won't work.



  • Also, the half that doesn't work overlaps only somewhat with the half that didn't work in Community Server. And sometimes you have to malform your closing tags to make quoting work right.



  • Ooh, I missed this by a month.

    A properly designed API would have its own generic exception then have specific exceptions as children of that.

    That way, if my app tosses a ImOnFireException, catching a FooException would also catch an ImOnFireException and (likely) log it.

    If your app was new enough to know about the ImOnFireException, then you could have a handler that automatically calls 0 118 999 881 999 119 725... 3.



  • You said this in response to my comments on checked exceptions. Having a parent exception does nothing to make checked exceptions more useful.

    If you meant to respond to my use of ApplicationException, then you are correct, but it really doesn't make that much difference. When I call your API and you throw an exception, the only clarification having a parent exception would do is to distinguish a rethrown exception that is not yours from a framework exception. The likelihood that my code could do anything meaningful with that information is vanishingly small.


  • Discourse touched me in a no-no place

    @Jaime said:

    Having a parent exception does nothing to make checked exceptions more useful.

    Parent exceptions make exceptions useful (in the limit, consider C++ where you can — but probably shouldn't — throw an int or a double). Checked exceptions make failure modes a stated, guaranteed part of the API. They're different things, orthogonal to each other.



  • @dkf said:

    They're different things, orthogonal to each other.

    Yes, a thought that can be otherwise stated as...

    @Jaime said:

    Having a parent exception does nothing to make checked exceptions more useful.

    On the other topic, parent exceptions are useful when you have is-a type relationships between exceptions. Declaring one parent exception for an entire API doesn't fall into the category of useful.


  • Discourse touched me in a no-no place

    @Jaime said:

    Declaring one parent exception for an entire API doesn't fall into the category of useful.

    If I'm only using a couple of functions of yours in a much larger application, your having a single parent exception for everything custom you throw is quite convenient for me. I don't care much for the details of why your frobnicator failed, I just know that it isn't DOING ITS JOB.



  • ...until my code calls a library it's dependent on, which throws an exception not inheriting from my parent exception. So, if you rely on the fact that all exceptions I throw will have the same parent, you will be burned.



  • Rely on it for code behavior, sure. But nice to be able, during debugging, to work out easily which vendor I need to be swearing at.



  • @flabdablet said:

    Rely on it for code behavior, sure. But nice to be able, during debugging, to work out easily which vendor I need to be swearing at.

    Then the parent exception class is still of minimal use. For example, suppose the people you need to be swearing at use a standard cast instead of an as-and-a-null-check. Guess what it will throw? Hint, it won't be one of their exceptions.

    But, the stack trace will tell you who to swear at no matter what exception is thrown. So not only is relying on the parent exception not terribly useful, it's also not necessary.


Log in to reply