• (cs) in reply to Contractor Khan
    Contractor Khan:
    Min is the reason why you should keep files on people that applied, as you are allowed to, for 6 months, with NOTES on what they admitted lying about.

    VB isn't that hard I suppose, what's the worst that could happen.

    VB life support machines. Shudder.

    Min isn't that bad - she admitted fairly quickly that she'd lied on the resume. The ones I like to keep notes on are the ones who fail even the most basic language questions, yet insist that they're masters of it. Like the 'unix guru' who supposedly doesn't know any unix commands because he's aliased them to their dos equivalent and promptly forgotten about it - but he also doesn't know 'fdisk'. (Of course, if the guy otherwise knew how unix worked, he could recover even from that - I tend to be fairly thorough before I decide to try to ban someone from working in my company.)

    However, that having been said, the real problem is that the people who do interviews assuming all of the assertions on the resume are true (or, worse, assuming that the fact that HR approved the interview means that the candidate's resume matches the requirements one sent to HR) are the same people who don't check the list of candidates to never hire.

    That having been said, I'm still chuckling about the time one of these managers hired a guy who had put '20 years experience with Java' on his resume (and this was years ago, even!) For the curious, said individual apparently did not know Java - unless there's a dialect that looks strangely like poorly written BASIC. I know because I'd asked him write a Java function to do some silly task. Oh, and for what it's worth, when I interviewed him, his resume said '25 years experience with Java', but I'd advised him Java wasn't quite that old.

    Note: chuckling was all I ever had to do about it, because the guy managed to totally wash out, very quickly, in a manner that made said manager look rather incompetent, and created no work for myself.

  • Jeff Grigg (unregistered) in reply to morry

    Re: "never put critical business transaction code in finally blocks."

    Well, yes... I would suggest that really important code is better placed in the "try" block. And really important business code should probably be within the scope of a database transaction too.

    (As a practical matter, exceptions thrown /from/ a finally block can be problematic. Be Careful!)

  • Euler Enthusiast (unregistered) in reply to WhiskeyJack
    WhiskeyJack:
    I'm not grokking this. Is there an explanation somewhere of how that would work?

    There.

  • (cs) in reply to anon
    anon:
    My Tales:
    Easy now. If that's how it works when the library re-throws, they're not really re-throwing, they're creating a new exception.

    It sounds like you're using .NET, so you should use: try {...} catch (Exception) { ...; throw; }

    Not: try {...} catch (Exception e) { ...; throw e; }

    You are correct that it's bad form to throw (instead of rethrow) a caught exception, but you're incorrect in assuming that would change the exception type. The "custom" library must be doing:

    try {...} catch (Exception e) { ...; throw new Exception(); }

    I'd question, however, if the InnerException is properly set from the "custom" library. If so, I'd say they picked the wrong exception type to throw, but the original poster is making a mountain out of a molehill. If not, then yeah, that library should be dropped immediately.

    Heh. The problem is that the method itself is defined as, say

    public void setConnection(String dataSourceName) throws Exception { ... }

    so even if I know the inner exception might be an SQLException, I still have to check for the general java.lang.Exception case (ok, I'm also answering which language I'm using). Given the state of other code I've found, I almost expect the "re-throw" to be something like this:

    catch (Exception e) { throw new Exception("Couldn't connect to the DB! :("); }

    Some calls are nice enough to include e.getMessage(), but no stack trace at all. My solution? I give that function its own try/catch block, then re-throw it as a new SQLException.

  • Edward Royce (unregistered) in reply to Sutherlands
    Sutherlands:
    WhiskeyJack:
    Sutherlands:
    The correct answer to the question you were asked is: Create 2 pointers, one that traverses the list one at a time, and one that traverses the list two at a time. If they are ever equal, you have a circular reference. If you encounter the end, you don't. However... that only works when you're not trying to find the beginning of the list... which my interviewer decided to add on to the question. (The actual question is from what Google made up for one of their interviews when they were hiring, btw)

    I'm not grokking this. Is there an explanation somewhere of how that would work?

    Someone posted a solution already, but here's a simplified one.

    boolean isCycle(*head) { slow = fast = head; try { do { slow = slow->next; fast = fast->next->next; }while(slow != fast) return true } catch(NPE) { return false } }

    so if the fast one gets to the end of the list, there's no cycle. If the slow one meets the fast one, you know the fast one looped around at least once.

    But if there's no circular reference isn't that an infinite loop?

    Uhhh. Forget me. I'm on beer #3 so I'm probably talking out my rear end.

  • Chris (unregistered) in reply to Martin

    Actual the reason it doesn't work in java is that there are no guarantees when the finalize will be run. It could take quite a long time for it to run and for all that time the database connect, file, or whatever is still open.

    Finalizers are still useful for a failsafe but the prefered way should be explicit methods for closing (or rollback/commit, etc) in a final block.

    You can solve the problem you mentioned by calling System.runFinalizersOnExit(true) someplace in the program.

  • Optimus Prime (unregistered) in reply to shadowman

    Maybe she finally fixed her resume (no more Microsoft Solaris). And that might be the reason why she was hired by the other company XD

  • ysth (unregistered) in reply to morry
    morry:
    where are you supposed to put the code? Magic fairy blocks?
    Well, in Perl, you could put it in the DESTROY method of an object stored in a positronic variable, and it would execute when the object goes out of scope at the beginning of your program, before the plug was pulled.
  • Noel (unregistered) in reply to kswanton
    kswanton:
    I've only had one bad interview experience. The lead was called in to handle the technical portion of the interview, which was made up of a few questions.

    One of the questions was 'How would you detect if you had a circular reference in a linked list?' I responded that you'd have to use some type of a hash table and iterate over the list - at each element, you'd need to check the hash table to see if you'd ever seen that element before - if you had, there is a circular reference, if not, add it to the hash and continue.

    The interviewer kinda smirked at me and said something along the lines of 'Well that is not efficient - is there a more efficient way to do it' to which I responded 'Not that I can think of...'

    In a condescending way he suggested that there was a much better way to check, that was quicker, less memory intensive, etc etc, and gave me the hint 'What about the first item in the list??? - what can you do with it that would make this easier?' I should have seen that the solution he was driving at, even though I thought it was wrong. After a while he gave me his answer which was to just compare the first element to each additional element in the list, if you ever get back to it you have a circular reference, still smirking like he was the smartest guy that I'd ever meet.

    At this point, I suggested that his solution was flawed - what if the circular reference did not point back to the first element, it would fail to detect it, such as:

    A points to B which Points to C which points back to B. In this case you'll never get back to 'A'.

    He ended the interview at this point and I never heard from them. Not sure if this was the reason why they did not call back or if it was just due to other reasons... or my solution was shitty... I guess I don't really care, the job was downtown, which I try to avoid like the plague.

    I was asked this same question at the interview for my current job. The answer I thought up was to have a compare the size of traversing the list with the known number of elements, if you can traverse through more elements than you have something is obviously wrong.

    They found that acceptable, but then described their own answer (which was pretty obvious as soon as they said it - I guess thats the pressure of interviews) which is to have a flag indicating whether an element has been visited or not, if you are traversing the list and come to which which has already been visited then it has a circular reference. (this technique is known as colouring)

  • Noel (unregistered) in reply to bcharr2

    [quote user="bcharr2"][quote user="shepd"] There is no hard and fast rule to the "Who is better, the college taught or self taught programmer?", because no 2 job candidates are exactly alike.

    I've seen individuals with degrees and without who could program. I've seen individuals with degrees and without who couldn't program. [/quote]

    Stupid people will be bad programmers whether they are self taught or have gone through thorough training, and likewise smart people will be good whether they have gone through training or are self taught.

    In my experience, there are a lot of people who fall somewhere in between the stupid & smart boundaries, and where these people are self taught they usually know all the different libraries and API well, they know technical details to the most intricate detail, yet they will still use bubble sort to organise a list of 1million elements.

    languages and technologies are very easy to learn, theory not so much.

  • Noel (unregistered) in reply to real_aardvark
    real_aardvark:
    There is no finally in C++. This doesn't make me think that C++ is an inherently better language than any other (far from it) -- but it does make me wonder what the fuck other languages really need a finally clause for.

    Fortran is not object oriented. This doesn't make me think that Fortran is an inherently better language than any other (far from it) -- but it does make me wonder what the fuck other languages really need to be object oriented for.

    Q.E.D.

    See.. here's how the proof works. If an old language doesn't have the exact same features as a newer language, then the newer language is wrong. Right? Right?

  • PhysicsPhil (unregistered) in reply to Saaid
    Saaid:
    Franz Kafka:
    real_aardvark:
    In a more realistic scenario, you'are asking an awful lot of the disk hardware. Let's assume that the db/OS in question conscientiously flushes through cache and RAM and paging system to the actual storage. What guarantee do you have that bits of your transaction log aren't stuck in the disk controller logic, and haven't yet reached metal oxide?

    Flush() guarantees this. Of course, in the catastrophic case, that fails and you use backups. You can't be perfect, but you can get close.

    Flush() is broken, then what do you do?
    Call a plumber.

  • sirGustav (unregistered) in reply to anon
    anon:
    try
    {
      result = a/b
    }
    catch (exception)
    {
      //handle divide by 0
    }
    finally
    {
      return result
    }
    What's wrong with
    if( IsZero(b) ) // handle divide by 0
    else return a/b
  • (cs) in reply to diaphanein
    diaphanein:
    Ok:
    System.Diagnostics.Process.GetCurrentProcess().Kill();
    

    Is that 1.0 enough for ya? Point is, unless you write it, you can't be sure what your call will do.

    And special case(s) or not, it still invalidates the assertion that the final block always executes.

    Process.Kill() came with .NET 1.1, afaict. It also requires full trust, which by design you should never give to code you haven't written yourself (and probably shouldn't even give it to all your own code as well.)

    While it does invalidate the assertion that the finally block always executes, it does so on the same level as all the variations on 'pulling the plug' do. Actually, it's an even weaker statment: An outage (if you're not using a UPS on a critical system, which is a WTF in and of itself) is atleast unpredictable, but killing a process through code has to be done explicitly.

    Btw. for all the people discussing what the proper 'form' of a try-catch-finally is, in C# it's something like this:

    using (Transaction t = new Transaction())
    {
      DoStuff();
      t.Commit();
    }
    

    Dispose() will be called on the transaction object as soon as the running program leaves the scope of the using clause (which includes situations where an exception occurs). Dispose() then takes care of rolling back the transaction, etc. if it wasn't committed.

    The IDisposable interface in combination with the using() statement is C#'s version of RAII. Use it!

  • Casey (unregistered)

    The real WTF is people using Java for anything critical enough where you would even need a finally to ensure something was done.

  • (cs)

    For the linked list question, I would just itterate forward through the list, and checking if the back pointer really points at the node we came from. If it doesn't, we got a loop. It is an O(n) complex algorithm that is guaranteed to stop.

  • (cs) in reply to real_aardvark
    real_aardvark:
    (2a) A better alternative to finally is almost always available. (2b) In severely restricted and well-controlled circumstances, finally is still the best solution. (2c) In 99.999% of circumstances where finally is used, it is a mistake. It may represent bad design, sloppy code, lack of attention to future maintenance issues, general ignorance, or simply a desire to sabotage the project. In summary, in the vast preponderance of usages, using finally is a mistake.

    Counter-propositions welcome.

    Use RAII instead. This even works, in the usual half-assed way, with languages that have garbage collectors.

    However, in languages without garbage collection, I find the use of 'finally' especially well suited for cleaning up in the presence of exceptions. Take this Delphi / Object Pascal example:
      foo := TFoo.Create();
    try
    foo.doStuff(); //may throw an exception
    foo.doSomeMoreStuff(); // may throw an exception as well
    finally
    FreeAndNil(foo);
    end;
    Voila! Exception gets propagated while foo is still disposed off. Surely you don't suggest catching the exception, cleaning up both in there as well as in the main flow (violating DRY!) and rethrowing? This example is such a common practice in Delphi that I wouldn't call that "severely restricted" or "0.001%".

    In summary, "finally" is just a regular construct to ensure some piece of code always runs in the presence of exceptions. RAII has its place, but in some languages you have no control over when a destructor runs, which may leave you tying up a resource for too long.

    Disclaimer: I'm well aware of the fact that using Delphi is TRWTF. Get over it.

  • (cs) in reply to anon
    anon:
    (2a) A better alternative to finally is almost always available.

    Such as? The only one that comes to mind doesn't exist in most languages: desctructors and RAII.

    Any object-oriented language which lacks destructors is pure FAIL. Use it, and you FAIL, sooner or later.

    The reason for this is that object cleanup is fundamentally necessary for certain types of objects. One must ensure that they get cleaned up when they go out of scope, or the program may not be able to run twice in succession.

    When the program crashes, these sorts of errors are expected - but very annoying, so it's preferred if the solution can do something to minimize the amount of trauma caused by a crash. However, normal executions should never have that issue.

    'Finally' blocks may work most of the time, but there's normal situations where they don't run. Also, using 'finally' blocks to simulate a destructor requires one to remember them for every block in which an object requiring a destructor is used. That's basically the exact same situation which motivated nearly all programmers to seek languages which had some form of automatic garbage collection: people couldn't remember to free all the memory they allocated.

    Incidentally, in my experience, languages which push exception handling rather than error handling also have a certain amount of fundamental fail. None have shown this to me more clearly than Java and Python - supposedly the languages with the best exception handling (at least, according to their adherents), yet over 95% of the Java and Python programs I've run have an incredible propensity to dump with a stack trace on any unexpected input. That stack trace may be useful to a developer, but when a normal user sees it, there's a good chance you're losing a user.

    Note: I have not run any Db programs directly, so I do not know if they have this propensity or not.

    (Just for comparison: using a combination of options intended for developer use, one can get the same behavior out of perl. But it's a simple matter to turn those off before shipping the product, which causes perl to go back to its normal unhandled exception response: attempt to do what the programmer most likely intended. (And it's generally quite successful at doing that.))

    I'm uncertain what RAII means, but the Wikipedia entry to me sounds like it's "programming". If you're using any programming language which doesn't have programming, I think you fail.

  • RQ (unregistered)

    Quite some years ago, my group interviewed a guy for a development position in my group. Despite a good-looking resume, we didn't feel that he all that qualified, and so didn't take him. He eventually was hired in another department, and eventually, I wound up inheriting his position. Looking at his code confirmed that our first group assessment was correct.

  • Hans (unregistered) in reply to Markp
    Markp:
    Does it matter? From my perspective, lying to a potential employer is a show-stopper, hands down.

    And yet... In this situation HR had already filtered out everybody else; presumably that included at least a few people who were sufficiently competent for the job. It appears that the only way to get past that filter is to brazenly lie about everything, and it worked for Min.

  • Doesn't matter (unregistered) in reply to henke37
    henke37:
    For the linked list question, I would just itterate forward through the list, and checking if the back pointer really points at the node we came from. If it doesn't, we got a loop. It is an O(n) complex algorithm that is guaranteed to stop.

    That will only work for a doubly-linked list.

  • PG (unregistered)

    Anyone that accesses the backend files for a real database over NFS is just asking for trouble. And I'm not talking about the performance hit you are going to take.

    In terms of the UNIX bufer cache. Well, mount that file system with the correct options. I also know that Oracle when it opens at least it's redo log files it uses with the DSYNC option, that forces the writes to be flushed and not hang around forever.

    Over the years, going back to version 5.1, I've seen people do tons of stupid things to machines running Oracle. Killing processes at random, hard power fails, disk storage going down, etc. I can count only two cases where the normal startup recovery in teh database didn't fix things. One was when some moved files around from E: to F: while the database was running. The other was many disk failures, not noticing that the RAID set had been degraded, and also no types of backups, ever.

  • (cs) in reply to Technical Thug
    Technical Thug:
    Flush() guarantees that you've pushed the data as far out as the OS can push it, but you still don't know where it's sitting. Is this an NFS connection? Are you inside a blade machine where all the blades are using each other's hard drives?

    It's really hard to really make sure the bits are on metal without violating a whole big pile of abstraction barriers.

    If the transaction log indicates an incomplete transaction, roll it back. If the transaction log is damaged, roll it back. If there's anything wrong at all, roll back. Only if everything is peachy do you not do anything. This means that the data could be consistent and complete, but the transaction log still says it's incomplete, or it's damaged and so it gets rolled back, but that's ok. The only scenario where I can see this fail is where the hard drive spreads random bits all over the place just before losing power.

  • anon (unregistered) in reply to real_aardvark

    Wow, you're an arrogant S.O.B.

    RAII is nearly 100% equivalent to try/finally. The difference is that RAII relies on rules of the C++ language to implicitly release the resources IN THE DEFAULT CASE, while try/finally requires explicit code. That's nice and all, but hardly a necessity, and certainly not enough to make RAII so vastly superior as to warrant a "try/finally considered harmful" proclamation.

    Worse, you seem to not understand your own beloved C++ and RAII. Destructors are NOT guaranteed to run. I can list numerous scenarios in which they won't. Yes, these are mostly the same scenarios in which finally blocks won't run either, but you sure seemed to think destructors were superior in this arena ("'Finally' blocks may work most of the time, but there's normal situations where they don't run.").

    You also go on and on about "RAII" just being programming, and how every language has it. This shows your ignorance. "RAII" isn't "just programming", it's a specific pattern. And like all patterns, it has different implications in different languages. In this case, the pattern CAN'T be applied in all languages. If you think that RAII just means (from Wikipedia) "The technique combines acquisition and release of resources with initialization and uninitialization of objects", then what I just said sounds ludicrous. But that's only PART of RAII. RAII relies upon the scoped nature of the initialization and uninitialization, and not all languages have such support. That's precisely WHY finally (and using, which is syntactic sugar for try/finally) exists in those languages. Looked at from that perspective (the correct one), try/finally IS RAII by your definition, and thus you're arguing in circles (try/finally considered harmful, RAII is the superior solution that proves that, but try/finally is RAII, making the argument fail... my head hurts).

    OK, you've got a preference to C++. Good for you. Don't disguise this religious debate with a mask of superior technical knowledge, because doing so you FAIL.

  • krupa (unregistered) in reply to tgape
    tgape:
    None have shown this to me more clearly than Java and Python - supposedly the languages with the best exception handling (at least, according to their adherents), yet over 95% of the Java and Python programs I've run have an incredible propensity to dump with a stack trace on any unexpected input. That stack trace may be useful to a developer, but when a normal user sees it, there's a good chance you're losing a user.

    Sounds like you're blaming the language for short-comings in the programmer. Unexpected input is not an exceptional case and should not be treated as such. If your program is dumping a stack trace because the user entered a letter where a number was expected (for example), the program was written poorly regardless of the language used.

  • (cs) in reply to henke37
    henke37:
    For the linked list question, I would just itterate forward through the list, and checking if the back pointer really points at the node we came from. If it doesn't, we got a loop. It is an O(n) complex algorithm that is guaranteed to stop.

    This would fail if the back pointer happens to be incorrectly set.

  • (cs) in reply to krupa
    krupa:
    tgape:
    None have shown this to me more clearly than Java and Python - supposedly the languages with the best exception handling (at least, according to their adherents), yet over 95% of the Java and Python programs I've run have an incredible propensity to dump with a stack trace on any unexpected input. That stack trace may be useful to a developer, but when a normal user sees it, there's a good chance you're losing a user.

    Sounds like you're blaming the language for short-comings in the programmer. Unexpected input is not an exceptional case and should not be treated as such. If your program is dumping a stack trace because the user entered a letter where a number was expected (for example), the program was written poorly regardless of the language used.

    I agree that the programmer is more at fault than the language. However, when 95% of the applications in use using one language are this sort of crap, and only 50% of the applications in use using another language are this sort of crap, I'll prefer the second language. It's not the language's fault, but that of the people the language attracts. (I realize 95% of everything is crap. But generally, the crap doesn't get used nearly as much as the 5% that's not necessarily crap.)

    Incidentally, an example of one of these python programs was the Gentoo emerge (it could be fixed now - it's been three years since I used it) program: give it certain combinations of bad options, and it'd stack trace, instead of giving proper usage. Clearly a Gentoo problem - but when you can't find an example to point the said maintainer to of how one does it correctly in Python, because the first 50 examples found by Google all have the same problem, I start wanting to avoid that language.

  • (cs) in reply to Doesn't matter
    Doesn't matter:
    henke37:
    For the linked list question, I would just itterate forward through the list, and checking if the back pointer really points at the node we came from. If it doesn't, we got a loop. It is an O(n) complex algorithm that is guaranteed to stop.

    That will only work for a doubly-linked list.

    ITYM a doubly-linked list which had the a null back pointer for the first link.

  • lillyOfTheValley (unregistered) in reply to sirGustav
    sirGustav:
    anon:
    try
    {
      result = a/b
    }
    catch (exception)
    {
      //handle divide by 0
    }
    finally
    {
      return result
    }
    What's wrong with
    if( IsZero(b) ) // handle divide by 0
    else return a/b

    Nothing. Sure, have you programmed in LIPS all these years? Try simplifying code like this in C++ and go back to your code in 6 months and tell me if you understand what it's doing! (and comments whatsoever)

  • Pfhreak (unregistered) in reply to Edward Royce
    Edward Royce:
    Sutherlands:
    boolean isCycle(*head) { slow = fast = head; try { do { slow = slow->next; fast = fast->next->next; }while(slow != fast) return true } catch(NPE) { return false } }

    But if there's no circular reference isn't that an infinite loop?

    Uhhh. Forget me. I'm on beer #3 so I'm probably talking out my rear end.

    Nope, because eventually fast->next->next will throw a null pointer exception (NPE), which will be caught, and false will be returned. Note, however, that using exceptions in this was is a bad idea, and considerably slower than just checking for null at each step.

  • (cs) in reply to Noel
    Noel:
    kswanton:
    [...] 'How would you detect if you had a circular reference in a linked list?' I responded that you'd have to use some type of a hash table and iterate over the list - at each element, you'd need to check the hash table to see if you'd ever seen that element before - if you had, there is a circular reference, if not, add it to the hash and continue.

    The interviewer kinda smirked at me and said something along the lines of 'Well that is not efficient - is there a more efficient way to do it' to which I responded 'Not that I can think of...' [...]

    [...] The answer I thought up was to have a compare the size of traversing the list with the known number of elements, if you can traverse through more elements than you have something is obviously wrong.

    They found that acceptable, but then described their own answer (which was pretty obvious as soon as they said it - I guess thats the pressure of interviews) which is to have a flag indicating whether an element has been visited or not, if you are traversing the list and come to which which has already been visited then it has a circular reference. (this technique is known as colouring)

    There is a solution which is reasonably fast and doesn't require you to know the size of the list or colour the elements: Use two iterators, one and two. Step one by one element at a time and two by two elements at a time. If the "two" iterator hits the end of the list, no loop. If the one and two iterators ever point at the same element, loop!

    Addendum (2008-07-31 13:24): EDIT: And works on a singly linked list, obviously. For a doubly linked list, just check if ( this->next->prev == this )

    Addendum (2008-07-31 13:33): Obviously testing that this->next isn't NULL first, to avoid crashing the poor thing.

  • Pfhreak (unregistered) in reply to Thief^
    Thief^:
    There is a solution which is reasonably fast and doesn't require you to know the size of the list or colour the elements: Use two iterators, one and two. Step one by one element at a time and two by two elements at a time. If the "two" iterator hits the end of the list, no loop. If the one and two iterators ever point at the same element, loop!

    Addendum (2008-07-31 13:24): EDIT: And works on a singly linked list, obviously. For a doubly linked list, just check if ( this->next->prev == this )

    Addendum (2008-07-31 13:33): Obviously testing that this->next isn't NULL first, to avoid crashing the poor thing.

    Addendum (2008-07-31 13:14 PST): You should read the comments before posting your own, this solution has been posted MANY times already.

  • DKO (unregistered) in reply to Sutherlands
    Sutherlands:
    The correct answer to the question you were asked is: Create 2 pointers, one that traverses the list one at a time, and one that traverses the list two at a time. If they are ever equal, you have a circular reference.

    Google didn't made up that one, it's Floyd's cycle-finding algorithm, a classical one. See [url]http://en.wikipedia.org/wiki/Cycle_detection.[url].

    But it can't find the beginning of the cycle.

  • (cs) in reply to anon
    anon:
    Wow, you're an arrogant S.O.B.
    Arrogant, yes. SOB, no. At least I'm not anonymous.
    anon:
    RAII is nearly 100% equivalent to try/finally. The difference is that RAII relies on rules of the C++ language to implicitly release the resources IN THE DEFAULT CASE, while try/finally requires explicit code.
    If by "nearly 100% equivalent" you mean "diametrically opposed to," you're right. If you mean that both the construct and the pattern tackle the same issue, you are also right. Hardly the same thing though, is it? By "IN THE DEFAULT CASE," I assume you also mean "automatically," which isn't quite the same thing and doesn't feature the same boo-words and capitalisation. And I have no problem with try/catch; only with "finally." Read what I said again, and you'll see that my main issue is that it requires "explicit code." Over and over again. Rather than just once, for RAII. Code can be a pattern too, you know -- in this case a bad one.
    anon:
    Worse, you seem to not understand your own beloved C++ and RAII. Destructors are NOT guaranteed to run. I can list numerous scenarios in which they won't. Yes, these are mostly the same scenarios in which finally blocks won't run either, but you sure seemed to think destructors were superior in this arena ("'Finally' blocks may work most of the time, but there's normal situations where they don't run.").
    I think you'll find that quote under tgape. He's probably arrogant as well. He just isn't, y'know, me.
    anon:
    You also go on and on about "RAII" just being programming, and how every language has it. This shows your ignorance. "RAII" isn't "just programming", it's a specific pattern. And like all patterns, it has different implications in different languages. In this case, the pattern CAN'T be applied in all languages.
    Name one.

    Just because you can't guarantee that automatic destruction happens the moment that an object goes out of scope doesn't mean that you can't apply RAII. (I'd love to know how the use of "finally" helps in this regard.) Perl has DESTROY (it also has Scope::Guard, which I haven't looked into); Python has del; I can't, off-hand, think of another OO language that doesn't have a hook into the underlying mechanism for object destruction.

    It was, once again, tgape who made the tentative assertion that "RAII" <is> "just programming," although I seem to recall that he claimed that he'd never heard of it, had just looked it up, and it "seemed" to be that way.

    Good for you, anon. You're arrogant and guilty both of misattribution and misquotation. I make no comment on your parents, however.

    anon:
    OK, you've got a preference to C++. Good for you. Don't disguise this religious debate with a mask of superior technical knowledge, because doing so you FAIL.
    I've got a preference for C++, yes, but it's hardly religious. I'd be far happier spending the rest of my life programming in Python. (Better libraries, and better organised, too, required; and with a bit of luck the GIL will disappear. I'm looking forward to 3.0 for the first two and checking out alternatives to the third.) Scheme looks fun, too. I'm pretty language-agnostic, with the exception of those that I would expect to act as personal ball-and-chains, such as Java and VB.Net ... but I've got no objection whatsoever to other people using those languages. Just so long as they don't abuse ill-advised language constructs such as "finally."

    Did I mention religion? I might have done once, but I think I got away with it. I suspect that you're confusing my juxtaposition of goto and finally with (non-existent) evidence that I regard both as equivalently evil, or that I have dogmatic views on the subject.

    I don't. Not with regard to either, as it happens.

    I've seen too many projects burned by goto (thankfully in the dim, distant past), and, judging by many comments defending the use of finally, I'm going to see a -- probably smaller -- number of projects burned by the use of finally. Either one is a deceptively powerful tool, and therefore dangerous in the hands of a depressingly large number of programmers.

    Not you, obviously, because you are anonymous and not arrogant and therefore know what you're doing, even if what you do is by definition not attributable.

    Hier steh' ich, Ich kann nicht anders. Finally is the modern goto. Just an observation. Not a gospel. (Sorry, Martin. I'll get around to the other 94 when I have some spare time.)

  • (cs) in reply to Noel
    Noel:
    real_aardvark:
    There is no finally in C++. This doesn't make me think that C++ is an inherently better language than any other (far from it) -- but it does make me wonder what the fuck other languages really need a finally clause for.

    Fortran is not object oriented. This doesn't make me think that Fortran is an inherently better language than any other (far from it) -- but it does make me wonder what the fuck other languages really need to be object oriented for.

    Q.E.D.

    See.. here's how the proof works. If an old language doesn't have the exact same features as a newer language, then the newer language is wrong. Right? Right?

    Let me boil this down for you.

    A (language C++) does not contain WTF' (finally). A (language C++) is not better than a member s of the set S (other languages). A (language C++) is Turing complete. For each s in S (other languages), s is Turing complete. s' (some member of set S) contains WTF' (finally).

    Since A does not contain WTF', what benefit does s' derive from containing WTF'?

    Let O represent <the set of> "object oriented" <languages>. Note, for the purposes of this proof, that neither O nor the term "object oriented" has yet been used or defined. Nor will be.

    Your argument therefore goes as follows:

    F (language Fortran) is not a member of set O. F (language Fortran) is not better than a member o of the set O ("object oriented" languages) I don't need to bother explaining what o' means, because I've just sprinkled pixie dust and used the magic abbreviation "Q.E.D."

    quod, I think, non est demonstrandum.

    Neither "old" nor "new" feature in this abstraction. Your (pitifully cretinous) argument would make C++ the superior language had Stroustrup invented it yesterday, complete with RAII.

    Your (pitifully cretinous) argument also introduces the entirely irrelevant issue of whether a language is "object oriented" or not. As you know, Fortran is not. It is not, therefore, amenable to the RAII pattern. I'm not au courant with the latest Fortran standard, but I'd assume that it's also lacking in support for exceptions -- which makes the use of a "finally" clause a bit problematic.

    We were talking about "finally," weren't we?

    As opposed to some completely random and possibly massively destructive language construct that hasn't been invented yet, but will be in the near future?

  • JJ (unregistered)

    A better example of never executing a finally is when calling System.exit().

  • Rhialto (unregistered) in reply to kswanton
    kswanton:
    One of the questions was 'How would you detect if you had a circular reference in a linked list?'
    A common method to do this is to use two pointers stepping through the list, once at twice the speed as the other. If the fast one ever catches up with the slow one (i.e. ends up pointing at the same list member), you have a loop in your list.http://en.wikipedia.org

    See http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare

  • immibis (unregistered) in reply to Jabmist
    Jabmist:
    stack overflows will STILL call the finally

    package test; public class miscTest { public int loop(int x){ return (loop(x+1)); } public static void main(String[] args) { try{ int x=0;int y=5; miscTest test = new miscTest(); test.loop(1); double t = y/x;

    	}catch(Exception e){
    		System.out.println("catch start");
    		int x=0;int y=5;
    		double t = y/x;
    		System.out.println("catch end");
    	}finally{
    		System.out.println("finally");
    	}
    }
    

    }

    finally java.lang.StackOverflowError at test.miscTest.loop(miscTest.java:8) at test.miscTest.loop(miscTest.java:8) at test.miscTest.loop(miscTest.java:8)

    There's a reason it never reaches the catch statement. StackOverflowError is obviously an Error not an Exception.

  • (cs) in reply to JonC
    JonC:
    Surely TRWTF is giving someone who has 'Oracle T-SQL' and 'Microsoft Solaris' on their CV the benefit of the doubt.

    That would have been setting alarm bells ringing immediately for me.

    You could still hire him/her as a clown or other who keeps company moral up by showing that there is always a person who is doing less good than you.

  • Colin S. Miller (unregistered) in reply to sirGustav
    What's wrong with
    if( IsZero(b) ) // handle divide by 0
    else return a/b

    Except that won't work if a=10^20, b=10^-20

    The result is 10^40 which is out of the range of [+/1] 1 * 10^[+/-] 38 of single-precision floating point numbers.

  • (cs) in reply to Jeff S
    Jeff S:
    real_aardvark:
    Ah yes, the finally block: the goto of the modern world. An impression that many of the comments above reinforce.

    Huh? So what are you saying? You believe that using Finally is a bad practice? I have no idea what correlation you are drawing between finally() and goto...

    In opposite to other readers I can see a correlation between goto and finally:

    int f()
    {
       FILE* f = NULL;
       int   error = 0;
    
       f = fopen("foo", "r");
       /* do stuff */
       if(error) {
          goto cleanup;
       }
       /* do stuff */
       if(error) {
          goto cleanup;
       }
       ...
    cleanup:
       if(f != NULL) {
          fclose(f);
       }
       return error;
    }
    

    Isn't this a poor man's finally?

    I've made this often in my first C programs and I've seen it in programs made by other programmers. And that's the only excusable use of goto I know. Anyway I prefer other ways of error handling (in C) today.

    BTW, what's about a finally for C++?

    #define finally(code) catch(...) {code  throw;} code
    
    f()
    {
       try {
          try {
             // do stuff
          }
          catch(whatever) {
             // exception handling
          }
        }
        finally(fclose(f);); //example cleanup stuff
    }
    

    I assume this would be a source of many WTF's ;)

    ... if it works at all, didn't tried it!

  • (cs) in reply to Noel
    Noel:
    kswanton:
    I've only had one bad interview experience. The lead was called in to handle the technical portion of the interview, which was made up of a few questions.

    One of the questions was 'How would you detect if you had a circular reference in a linked list?'<snip/>

    I was asked this same question at the interview for my current job. The answer I thought up was to have a compare the size of traversing the list with the known number of elements,<snip/> (this technique is known as colouring)

    There may well be better ways, and for all I know they involve the use of "finally," but the simplest effective way I know is to use two iterators: one goes through the list/whatever with an increment of 1 and the other goes through the list/whatever with an increment of 2. If, at any stage, they are comparable, then you have a circular linked list.

    It was the only question that I outright failed on my interview for a Dot Bomb. "Well, you'll remember the answer next time, won't you?" said Michael, the Jewish Ukrainian American who turned out to be an utterly excellent boss.

    Yes, I will. I will also remember to spit poison in the face of some retarded quasi-superior prick of an interviewer who actually takes puzzle-solving seriously, without being prepared to have the same crap thrown back in their face.

    Addendum (2008-08-02 15:59):

    DKO:
    Google didn't made up that one, it's Floyd's cycle-finding algorithm, a classical one. See [url]http://en.wikipedia.org/wiki/Cycle_detection.[url].

    But it can't find the beginning of the cycle.

    Oops, sorry. An interesting Zen question, however: What is the beginning of the cycle?

  • (cs) in reply to atz
    atz:
    BTW, what's about a finally for C++?
    #define finally(code) catch(...) {code  throw;} code
    

    I assume this would be a source of many WTF's ;)

    ... if it works at all, didn't try it!

    Excellent example, and my thanks.

    res ipsa loquitor.

  • George (unregistered)

    It feels awkward when you realize that you know more than your interviewer.

  • shazam (unregistered)

    The code in the following finally is unlikely to ever execute:

    try { while ( true ) ; } finally { veryImportant(); }

  • sirGustav (unregistered) in reply to Colin S. Miller
    sirGustav (me):
    What's wrong with
    if( IsZero(b) ) // handle divide by 0
    else return a/b
    lillyOfTheValley:
    Nothing. Sure, have you programmed in LIPS all these years? Try simplifying code like this in C++ and go back to your code in 6 months and tell me if you understand what it's doing! (and comments whatsoever)
    never heard of LIPS, never used LISP, or any other functional languages for that matter, but I plan to(just gotta find some time). I mostly code in C++ and C# at home/work, and AFAIK C++ doesn't throw divided-by-zero exceptions. Personally I think C# and java throw to many exceptions and if you providing a specialized case on such a low level, you shouldn't be catching exception, you should stop it from being thrown, espesially in C++.
    Colin S. Miller:
    Except that won't work if a=10^20, b=10^-20

    The result is 10^40 which is out of the range of [+/1] 1 * 10^[+/-] 38 of single-precision floating point numbers

    true, but given that the original code only handled divided by zero (catching all exceptions?) I'd say my code didn't introduce any more bugs :)

  • R (unregistered) in reply to sirGustav
    class Program
    {
    	static void Main(string[] args)
    	{
    		Console.WriteLine(Something().ToString());
    	}
    
    	static int Something()
    	{
    		int val = 0;
    
    		try
    		{
    			val = 2;
    			return val;
    		}
    		finally
    		{
    			val = 1;
    		}
    	}
    }
    

    Guys, seriously. Be careful with finally blocks. This shows right here, in a very contrived case, why. This caught a lot of very intelligent developers in various groups here at my company.

    Just because finally executes last, doesn't mean that it's doing what you may intuitively think it should do.

  • Kuba (unregistered) in reply to sirGustav
    sirGustav:
    never used LISP, or any other functional languages for that matter, but I plan to(just gotta find some time). I mostly code in C++ and C# at home/work, and AFAIK C++ doesn't throw divided-by-zero exceptions

    The "exceptions" aren't thrown by C++, they are thrown by the CPU, and on most OSen there are APIs to enable those "exceptions". This applies, then, to almost any language (assembly, C, C++). Some language runtimes (Java, .net) enable those by default.

    It is actually very useful to enable math exceptions in C++ when you write numerical code. This lets you avoid hand-coding (at a HUGE performance penalty) wrappers for almost every operator and math function out there, just to handle those. I know of at least one open source (and somewhat abandoned now) open source project, very numerically-intensive (solves multibody dynamics) where the author had gone that route. You could probably remove 10-20% of the code just by enabling some more exceptions and doing exception handling properly.

    Cheers, Kuba

  • insta (unregistered) in reply to tgape

    A more complete answer (in addition to this) is that proper database servers have batteries slathered all over them (including the drive controllers), and they pick up where they left off when power is restored.

  • Phillip Rhodes (unregistered) in reply to Markp
    From my perspective, lying to a potential employer is a show-stopper, hands down.

    I can't imagine why... after all, employers lie to employees all the time. All's fair in love and war...

Leave a comment on “My Tales”

Log In or post as a guest

Replying to comment #:

« Return to Article