|
|
|
| Non-WTF Job: C++ Developer at Good Grievance (Ronkonkoma, NY) |
| « The Lesser Date | 2.12: Surrounded » |
After sharing so many of your interview stories, I thought it was finally time that I’d share a couple of my own…
Back in the .NET 1.0 days, I interviewed for a contract position at a certain large insurance company around here. It was a technical interview with two senior-level developers. After I finished answering a softball question about how Try-Catch blocks work, one of the interviewers followed up with a question about Finally blocks.
“A Finally is placed after a Try or Try-Catch block,” I answered, “and will execute, in most circumstances, regardless of any executions that occ–”
“Actually,” the interviewer interrupted, “code within a Finally block is guaranteed to execute.”
“Err,” I replied, “yes – but, there are some situations that cause that code to not be—”
“Nope,” the other interviewer quipped, “that’s the whole point of Finally blocks!”
“Well,” I tried to explain further, “not always. A simple example is a stack overflow exception, but it can happen other times, especially in multi-threaded appli—”
“Alex,” the interviewer sternly jumped in, “read the documentation. You’re wrong here.”
“Okay… but, let’s say something catastrophic happens, like the process is terminated.”
“Uh-uh,” he smirked, “actually, the CLR handles that through process marshalling. Can we move on now?”
“All right,” I sighed. As tempting as it was to ask him to describe the just-made-up concept of process marshaling, I decided to concede. And just at that moment, I thought of the perfect rebuttal. “But what if you just, say, pull the plug? A Finally block won’t execute when the computer is turned off!”
I expected the developers to jump back and chastise me for an “unreasonable scenario.” But instead, their faces turned bright white. They slowly turned to look at each other. It was clear that they made the same mistake that many before them had made: believing Try-Finally to be as infallible as things like database transactions.
“And… umm…” I said slowly, breaking the awkward silence, “that’s why… you should… never put critical… business transaction code in finally blocks.”
The interview ended shortly after that. They did end up offering me the job, but I decided to pursue another opportunity.
Several years back, I was responsible for interviewing all of the “qualified” candidates that had applied for an opening in my group. “Qualified” was the status given by human resources and indicated that an individual had applied for the position in the “open application” period, had been pre-screened by an HR generalist, and had all of the “minimum qualifications” as set forth in the job description. For the opening, we had a total of one “qualified” candidate. Her name was Min.
Min’s resume looked fairly decent, aside from a few minor typos (DCMO instead of DCOM, Visual Basics 6, etc) and a few minor impossibilities (Oracle T-SQL and Microsoft Solaris). I had seen far worse and figured, with the language barrier and all, I’d give her the benefit of the doubt.
“I see on your résumé that you were a VB6 programmer at your last job,” I asked in the interview, “can you give me an idea of your day-to-day?”
“Mostly,” Min replied, “I tested, and make sure our program did not crash.”
“Oh,” I said, “so, like unit-testing with VB?”
“Actually,” she clarified, “I did not use VB. Just our program. But, program was written in VB.”
It didn’t take me too long after that to figure out that Min had never actually used Visual Basic. Or C++. Or, really, any other programming language.
“Min,” I questioned, “why would put all these skills and technologies on your résumé if you’ve never used them?”
“I figure,” she responded, “I would get interview this way. Then, maybe, job.”
Human Resources was a bit peeved that my group was so “picky” with our candidates ad rejected all of the qualified candidates (read: one) that they had sent over. After a bit of cajoling, they opened the position back up for applications.
A couple months later, on a visit to a meeting in an entirely different department, I ran into Min again. Apparently, she had been hired as a VB programmer for another group.
|
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) |
That's actually a genious idea. I propose this as an addition to the next version of the .NET framework.
|
|
It depends on the language evidently because it doesn't with C#.
class Program { public static void Main(string[] args) { try { Console.WriteLine("Attempting to access property"); int x = Number; } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { Console.WriteLine("Finally block run"); } } private static int Number { get { return Number; } } } Output C:\>TestApp.Console.exe Attempting to access property Process is terminated due to StackOverflowException. C:\> |
This is part of the answer, other posters have also given partial answers. For a more complete (and low-level, while still remaining generic) answer: A good database will arrange its write operations such that the difference between having not entered the data and having fully and correctly entered the data is a single, atomic (meaning, it can't be interrupted by anything short of a hardware failure - and generally, even a power failure will allow it to complete) operation. This is normally a very difficult task, especially if the database supports 'transactions'. Most modern databases use journalling, which makes it *much* easier (note: the below skips locking and parallelization, which would needlessly (because this isn't actual code) complicate the answer): 1. You write what you are going to do. 2. You update the journal end marker (a single, atomic update) to cover the new data. 3. You update the database data for all of the operations involved. 4. You update all the database indexes for the new data. 5. You update the journal start marker to not include that entry (a single, atomic update) Now, there's two atomic updates there that have critical effects, rather than just one for a pre-journaling version. However, there's no need to dance around making dozens to hundreds of changes such that they don't take immediate effect until some later update occurs, because if it fails at any point after the journal is extended to cover the new update, the database will know exactly what it was trying to do, so can finish it up on restart. If it occurs before step two, then the operation never happened at all. Of course, on error, there's also rollback, as others have mentioned. I think that's been adequately covered in other posts, however. |
| « The Lesser Date | 2.12: Surrounded » |