Everyone knows that "Magic Numbers" are bad, Bad, BAD! Take, for example, dividing something into quarters. Because including the literal "4" in your code would be a Magic Number, many developers agree that it's best to define a constant named "FOUR", and then use that constant instead. Makes sense, right?
Wrong! The problem with using "FOUR" is that, like "4", it's a Magic Constant. While not nearly as bad as Magic Numbers, Magic Constants certainly aren't elegant. Fortunately, Allen's colleague has provided us all with a valuable lesson the proper use of Magic and Non-Magic constants. Read it, and learn.
public class Constants {
...
public static final int FOUR = 4;
public static final int THREE = 3;
public static final int INTEGER_FOUR = 4;
public static final int INTEGER_FIVE = 5;
public static final int INTEGER_ONE = 1;
public static final int LENGTH_FOUR = 4;
public static final int LENGTH_FIVE = 5;
public static final int LENGTH_SEVEN = 7;
public static final int LENGTH_EIGHT = 8;
public static final int LENGTH_NINE = 9;
public static final int LENGTH_ELEVEN = 11;
public static final int LENGTH_TWELVE = 12;
public static final int LENGTH_EIGHTEEN = 18;
public static final int LENGTH_FIFTEEN = 15;
public static final int ONE = 1;
public static final int INTEGER_FIVE = 5;
public static final int INTEGER_ONE = 1;
public static final int PLUS_ONE = 1;
public static final int INTEGER_THREE = 3;
public static final Long LONG_VALUE_TEN = Long.valueOf(10);
public static final Long LONG_VALUE_ZEARO = Long.valueOf(0);
public static final BigDecimal BIGDECIMAL_ZERO = new BigDecimal(0);
public static final BigDecimal BIGDECIMAL_ONE = new BigDecimal(1);
public static final BigDecimal NEGATIVE_NUMBER_ONE = new BigDecimal(-1);
public static final int COMPARE_RESULT_ZERO = 0 ;
public static final int COMPARE_RESULT_ONE = 1 ;
public static final int COMPARE_RESULT_NEGATIVE = -1 ;
...
public static final String NINE_STRING = "9";
public static final String ONE_STRING = "9";
}
Bob was in the process of shutting down a software company that he had built over the past seven years. He had found a buyer for all of the software that he'd developed, collected his "eff you money" and was now retiring.
In fact, things were at the point where Bob had already closed the building and redirected the phones to his home phone with a distinctive ring so that he could tie up loose ends while the building was up for sale.
Bob woke one morning at 8:00am to the phone ringing, crawled out of bed and picked up the ‘Bat Phone,' as he called it, in the living room.
"Hello?" Bob said, and gave the name of the company.
Without preamble or introduction, Bob was informed by a woman's voice, "Hi this is Sally Brumbaker, my user id is smb1985. My computer's frozen."
Bob didn't recognize the voice and certainly not the name. Also, it was before coffee. "Your computer's frozen?" Bob affirmed.
"Yes."
"Is the side cold?" Bob asked matter of factly.
"Wait a minute," replied Sally, and then after a pause, "No not at all."
"Ok, then," Bob assured her. "Your computer's not frozen, then, it's probably just running a program. Give it a minute."
"I don't understand, what do…" the woman began, and then, "Oh, ok. There is goes." and that, she hung up the phone and Bob did the same, thinking about how much cream to put into his coffee.
THREE MONTHS LATER
The ‘Bat Phone’ rings. Though the company had long been put to bed, Bob was suddenly reminded of was that he’d forgotten to stop the phone service.
"Hello?" Bob asked, and with a little hesitation, gave the name of his (now non-existent) company.
"Hello,” introduced the caller in a very serious tone, “I need to speak to someone in charge of your technical support."
"Well, that's pretty much me,” replied Bob, “What do you need?"
"Did you or someone working for you tell Sally So-And-So that she could tell if a computer was frozen by feeling the side?"
"What?"
"Sally says she called this number three months ago, and was informed by a support tech that she could tell if a PC was frozen by feeling for the side being cold. Since then, she's been feeling the sides of people's computers, and she's completely humiliated."
"Sally works in your IT department?" Bob asked.
"No, Sally is the Director of our human resources department," Bob was informed.
"And this is...?"
"I sit on the board for Plainston-Princeboro Teaching Hospital."
"I see. So, Sally hires doctors and nurses."
"She does - and now she's been humiliated by you or someone at your company,” huffed the voice on the phone,” What do you have to say for yourself?"
"Well, first," Bob answered, "I'd like to say that, if I get seriously hurt, I'll drag myself right past YOUR hospital."
"WHAT!?"
"Sir," Bob said, with great sincerely, "you have to admit, that's pretty dumb."
Suddenly, the man on the other end of the line was at a sudden loss for words.
"Ok," he said finally, a little deflated, "Sally isn't the most computer savvy person we have, but that doesn't give you the right to prey on her..."
"Sir," Bob said, "I took that call, Sally didn't identify herself, and as soon as she thought she had an answer from me, she hung up the phone before I could explain that I was kidding. I'm sorry if I humiliated her, but I have no idea how she got my number and this isn't a computer technical support company."
"Oh, I see," the person informed Bob. "We’ll, just be more careful, next time,” and with that, hung up the phone.
Since then, Bob disconnected the ‘Bat Phone’ for good, officially severing himself from his old life, but still gets a chuckle thinking of a smartly dressed executive going through the hospital, troubleshooting issues by feeling the sides of PC's and telling their users whether they were frozen of not.
The Best (from Chris)
A while back, I helped interview for a programmer position on the web team. After talking to a number of candidates, we finally settled on an older gentlemen, probably in his late 50s. It wasn't an easy decision. Not only were his salary requirements above what we planned to pay, he had a few personality quirks. For example, a large part of his interview entailed him describing how he was a master composer of music, and had published songs in nearly every genre, including country, rap, pop, etc. But no matter, his experience and technical skills were top-notch.
After making an offer that met his salary requirements, the candidate made a counter offer: fifteen-thousand dollars more annually plus a signing bonus. Unfortunately, our budget couldn't accommodate that, and we declined. Negotiations after that failed, so we formally rescinded the offer for employment so we could talk to more candidates.
Later that day, the CEO of company received a rather childish email from the gentleman. He rambled on about age discrimination, made other accusations, and stated that he "knew" that we were hiring the "other" man that he had met when leaving his interview. His closing words were: "you could have had the best, now you'll just have the rest!"
The "other" man he referred to was in his early 30s, and was interviewing for an entirely different position (business analyst) in an entirely different department. Looking back, we were all pretty happy that he didn't accept the position.
The TDWTF Interview (from Christian Riesen)
Two years ago, I was on the job hunt, and one company that looked interesting was a university spinoff. At the interview, I learned that they dealt with some specialization software that had to talk to a few different systems. Most of the code was in PHP, but there also were some .NET and Java components that were used to interface with the hardware's proprietary drivers.
One thing they were particularly proud of was the fact that the system was recently rewritten from Perl into PHP. Their pride came from the fact that none of them had coded PHP before that, but they had a strong theoretical knowledge, being university guys and all.
Next, they told me about the environment that they work in. As it turned out, the five-man crew worked all in the same room we were interviewing in: a factory attic converted loft style, with one wall made of glass in it so the conference "room" we sat in wouldn't disturb the others. Each employee had their own desk that was about twenty feet from another, which meant there was a lot of yelling going on. In addition, everyone used whatever the hell they wanted to code on whatever operating system they wanted: Windows, Linux, Mac OSX and one even swore on FreeBSD.
Then came the general technical part of the interview: how I would setup a class, what I would do with a certain language construct, how I would solve a certain problem or assess a situation, all the fun things. Then they showed me two half pages of code in PHP. They told me to look at the code carefully and, if I wanted to change anything, write on the paper what I would change and why. As that would take some time, they left me to it for about twenty minutes. I was certain that they had set me up with a TDWTF-style interview, where they'd pick out a fun code WTF (actually, it looked like this one) and have me turn a convoluted two-page mess into a two lines of code.
When they came back, I complimented them on the clever examples of bad code and presented them with my rewrite. One of interviewers — the chattier of the two — didn't say another word; he was clearly upset, and I was half-concerned it might get physical. The other guy was a bit better, but he also wore a rather large frown on his face. "This is from our production code", was the reply.
I left the interview shortly after that, with a short bye from the one guy, and just a short nod with some nasty stares from the once-chatty guy.
The Storm-out (from Joshua Armstrong)
I've always dreamed of storming out of an interview, but I've never actually realized that goal. That is, until my interview with a certain "tech recruiting" firm.
First things first, I was lured in under the guise that I'd be actually interviewing for a job, not being primped for another interview. The firm's client was, as the technical recruiter put it, "an ISP like Yahoo! or Google." I thought to myself, neither of those companies are ISPs, but I didn't say anything.
When we moved on to the technical portion of the interview, his first question was "do you had any experience working at a server." And just to be extra clear, those were his actual words: "working at a server."
"Well, yeah of course," I diplomatically responded, "I am a network admin, after all... and I'm physically at servers all the time. That's what you meant, right?"
"No no," he clarified, "were any of the businesses you've worked at servers? That is, would you consider them to be a server?"
I said, "Err, uhh.... I don't know," and things went downhill from there.
"Have you ever connected to the database?" he asked next.
"Huh? Do you mean in code? Admin tools? Which database platform do you mean?"
He paused for a moment and said, "sounds good to me. Do you have experience working at an ISP?"
"I think you're using a different definition of ISP than me," I responded, "what I mean is... I wouldn't have considered Google to be an ISP, but a search engine. Can you clarify?"
"No, no. They're actually both ISPs, as they allow people to access websites. Would you consider any of the companies you worked at to be an ISP?"
"Uhh... I guess not."
He scribbled something down on his paper mumbling something about how a bank is probably an ISP and added, "have you troubleshot IIS?"
"Not, but I have maintained several Apache servers."
"Oh good, then you have since Apache is IIS. Moving on, what's the diff—"
"Err," I cut him off, "they're both web servers, but Apache is not IIS."
"No, no. It is. Apache is actually a kind of IIS, so yes, you have troubleshot IIS. Anyway, what's the difference between layer 7 routing and layer 4 routing?"
Finally, an answer I was prepared for. "Layer 7 is the Application Layer, and routing focuses on requests to resources that will be fulfilled in the shortest time. Layer 4, the Transport Layer, routing focuses on ensuring that all paths to a host are utilized proportionally to their bandwidth and response"
"Actually," he gave a confused look, "I was looking for an answer involving, uh, DNS pools and host headers. Shall we just say that was your answer?"
I was pretty frustrated by that point, as I knew this interview was going nowhere, and the "technical recruiter" was grasping at straws and hoping to get me in front of thier "ISP" client. I said, "actually, I was just looking for the door," and got up and left.
Later that day, I just got an e-mail from him thanking me for his time, and asking me to forward two references from each job. He also said that he'd taken the liberty of rewriting my resume to include a couple of things about my experience troubleshooting IIS, and that he was planning on submitting it to his client as soon as I got the references. I ignored the email.
Have tales from your own interview? Then be pal and share them!
"While digging through some inherited code," writes Joe "M2tM" Smith, "I encountered a conditional masquerading as a loop."
"Thankfully, the fellow responsible is 'no longer with us', and I suppose this type of code stands as silent testament to why. This interesting loop is only created so the break keyword can be used as an elaborate GOTO."
bool bCreateModel = false;
for (;;)
{
if (!pModel)
{
bCreateModel = true;
break;
}
if (asModelParts.GetSize() != asModelPartsToLoad.GetSize())
{
bCreateModel = true;
break;
}
for (UINT32 i = 0; i < asModelPartsToLoad.GetSize(); ++i)
{
if (asModelPartsToLoad[i] != asModelParts[i])
{
bCreateModel = true;
break;
}
}
break;
}
"I was recently assigned to work on a team that maintains a fairly large product," writes Aaron, "at first, I was a bit overwhelmed by the complexity of the architecture. There were countless layers of abstraction, thousands and thousands of classes, and design patterns galore. Since it was such a large project – and my first large project – I figured that the architectural complexity was simply par for the course."
“Then I started looking at the code a little more closely. If I had two words to describe it, they’d be ‘unnecessary complexity.’ And if I had one snippet to describe it, it would be this.”
private void SetAccount(RequisitionData.RequisitionItem requisitionItem,
AccountData.Account account, bool automation)
{
bool allowSetAccount = false;
if(account != null)
{
// if the account entry is being set by automation, ensure that
// the user hasn't already set a value
if (automation)
{
if (!requisitionItem.IsAccountCodeNull())
{
if (requisitionItem.AccountCode == string.Empty)
allowSetAccount = true;
else
allowSetAccount = true;
}
else
allowSetAccount = true;
}
else
allowSetAccount = true;
if (allowSetAccount)
{
requisitionItem.AccountID = account.ID;
requisitionItem.AccountCode = account.Code;
}
}
}
Aaron continued, "the beauty of it is that the method is private within the class, and has an 'automation' boolean parameter. This parameter is always passed as true."
Andrew Carpenter writes, "I guess this is like turn-oning off a switch?"
"While trying to signup for a Windows Live account, I found myself without my best friend Neil," wrote Rob, "unfortunately, my second-best friend Ray, third-best friend Jane, and fourth-best friend Tom are also excluded."
"I got this rather odd message when trying to install the Evo Java client," wrote Nick Edwards, "I clicked OK and it worked... even though I wasn't SURE_IT_WORKS!"
"I'm not sure why Google would omit entries and return zero results," Michael noted, "clicking on the link, I received 0 omitted results which were indeed very similar."
"YUM!! Blank Insert bear claws," wrote Matthew Sowders
"This came up while configuring Neverwinter Nights on my PC," Ville Rastas writes, "I was worried the game might not support today's high resolution screens, but I guess it's quite the opposite."
"I knew IKEA has some funny names on it's furniture," writes Patrik, "but who knew they were into the new fashion trend of nerd chic?
"According to Virgin Mobile," writes Glenn Jones, "Unlimited is twice as big as 10G (so maybe around 20G), except for videos where Unlimited is only 1.3 times 10G."
Think of all those old applications you’ve had to maintain. You know the type: the ones written by long-forgotten developers in long-lost languages. The ones that, after spending days searching for that one line of code that needs to be changed, you frustratingly decree “this f%*#@ thing needs to be rewritten.” And, naturally, the ones that never are, nor never will be rewritten.
Call it luck or persistence, but after dozens and dozens of maintenance requests over the years, Israel Brewster finally was given the opportunity to rewrite an application. From scratch. And the right way, this time. No shoddy VB6 front-end; no horribly-designed SQL Server 2000 (only) database; and certainly no Microsoft Access-based administration tool.
Though, after his third straight week of digging through form validation logic requirements – many of which were quadruplicated (or more), inconsistent, and often incorrect –he’s started to question if a rewrite is even possible. Consider, for example, Command 696: a method named that simply because Command1 through Command695 were already taken.
Private Sub Command696_Click()
On Error GoTo Err_Command696_Click
Dim stDocName As String
Dim Response As Integer
If Frame500 = 1 And pax > 37 Then
MsgBox "CHECK PAX DASH 8 LIMIT 37 SEATS", vbOKOnly
Else
End If
If Frame500 = 2 And pax > 29 Then
MsgBox "CHECK PAX DASH 8 LIMIT 29 SEATS", vbOKOnly
Else
End If
If totalload1 > 2000 Then
MsgBox "OVERWEIGHT Fwd Shelf ", vbOKOnly
Else
End If
If ttshelf > 1000 Then
MsgBox "OVERWEIGHT Aft Shelf ", vbOKOnly
Else
End If
If totalload1 + ttshelf > 2000 Then
MsgBox "OVERWEIGHT Aft Compartment max 2000 lbs ", vbOKOnly
Else
End If
If Frame500 = 1 And totalloadsecd > 0 Then
MsgBox "DASH 8 WITHOUT SECTION D ", vbOKOnly
Else
End If
If Frame500 = 2 And totalloadsecd > 2150 Then
MsgBox "OVERWEIGHT SECTION D ", vbOKOnly
Else
End If
If Remaining < 0 Then
MsgBox "DASH 8 OVERWEIGHT REDUCE LOAD !!!!", vbOKOnly
Else
End If
If ttload <= 0 Then
Response = MsgBox("ARE YOU SURE AFT CARGO COMPARTMENT IS EMPTY!!!!", vbYesNo)
Else
Response = 6
End If
If Frame500 = 1 And pax <= 37 And totalload1 <= 2000 And _
ttshelf <= 1000 And totalloadsecd = 0 And _
Remaining >= 0 And totalload1 + ttshelf <= 2000 And Response = 6 Then
stDocName = "csaprintinfo37seats"
DoCmd.OpenReport stDocName, acPreview
Else
End If
If Frame500 = 2 And pax <= 29 And totalload1 <= 2000 And _
ttshelf <= 1000 And totalloadsecd <= 2150 And _
Remaining >= 0 And totalload1 + ttshelf <= 2000 And Response = 6 Then
stDocName = "csaprintinfo29seats"
DoCmd.OpenReport stDocName, acPreview
Else
End If
Role-based security requires, at a minimum, two key elements: users and roles. Roles (such as Administrator, Clerk, and ViewOnlyUser) are defined by the application code and then assigned to users to restrict which functions of the application they may use. It's a pretty simple concept that involves all of two database tables, or one if the user names come from some external source like Active Directory.
In Adam's case, the Role-based security feature served as a coalmine canary in the application he was tasked with reviewing. Although it passed all of the test cases — employees could only do certain things, customers could do other things, etc. — there was one fundamental flaw with the system. See if you can spot it.
public bool IsInRole(string roleName)
{
return UserName.StartsWith(roleName.Substring(0, 3));
}
The roleName parameter is a string ("Employee") that's is passed in from a method to check security, and UserName is just that: it's the user's name. So, users with a name that started with "Emp" would be granted access to Employee functions, while no one else would. And why "Emp"? As it turned out, the user names created for testing were "Employee1", "Employee2", "Employee3", and so on.
As for the rest of the system, it's development was similar: it passed the test cases and little more.
The words "Enterprise Integration" strike fear into the most stalwart of developers. When coupled with "in-house developed" and "B2B", one is almost guaranteed to find complex code, arcane requirements, and a thicket of poorly understood file formats. Dan was made of sterner stuff. When the contract was explained to him, he didn't flinch. There were between 40 and 80 partners that used a web app to extract data about multimedia assets? Gigantic recordsets of them? In formats ranging from Excel to iTunes-compatible databases? No problem.
Steve, the project manager, explained: "Our original lead developer was one of those rockstar types. Real cutting edge, pushing the envelope type guy. He's since moved on to bigger and better things, so we've just muddled on the best we could. We really need you to step up and take on that rockstar role for us, because there are a few problems we'd like you to fix. And we need a real quick turn-around on this."
"What sort of problems?" Dan asked.
"Well, these exports take hours. That's expected- it's a huge pile of data- but some of our partners are complaining that it crashes on them near the end of the job. So they have to start all over. Hours wasted. That's the big thing, but some of our other developers suggest that you try and do a little 'refactoring'?" Steve used air-quotes and a look of incomprehension to convey the question. "They said it should help make maintenance cheaper. Is that right?"
"It could," Dan said. "Let me see your documentation and the code, and I'll see what I can do."
They only had code. Dan opened the solution up in Visual Studio and started poking around. He looked for any classes that were responsible for exporting. He expected to see a whole family of them tied together through inheritance, probably named something like "XMLExport", "ITunesExport", or something equally transparent.
He didn't find a family of classes. In fact, he didn't find any classes. The entire project was lacking in any code or code behind files- not a single ".cs" in sight. Not even a ".vb". The only likely candidate was "Export.aspx".
"Do I have the right code?" Dan wondered, thinking there must be some class library he was missing. Dan double-clicked on "Export.aspx" and waited for the file to open. And waited. The HDD rattled away; its noise covered up the faint sound of Visual Studio sobbing to itself. By the time Dan finished his cup of coffee, the file appeared on the screen. Dan skipped down to the postback event handler, which was wedged in-line between the opening <body> and the page heading. It took Visual Studio over a minute to repaint the screen.
At four levels of indentation under the event handler, there was a switch statement. This statement simply checked which button was clicked. The first case, for "__exportButton" contained a twenty-five thousand line block of if/else statements.
"Oh, this can't be right," Dan wished. "This must be old code. Or some obscure branch used for… for… for hazing the new guy." He checked SVN. There was only one branch and the most recent check-in was from the day before, with the comment, "changed XML date format for iTunes export."
Dan patted Visual Studio's shoulder and tried to console it by closing every other application running, to free up some RAM. He and Visual Studio, both on the verge or crashing, struggled to read through the document together.
At the start of the event handler was this:
//Server.ScriptTimeout = 3600;
//Server.ScriptTimeout = 10800;
Server.ScriptTimeout = 21600; //six hours should probably be enough. If it keeps crashing, raise this.
The code went downhill from there. The actual export logic in the twenty-five thousand line block contained batches of hard-coded SQL queries- they all varied slightly, but not much, and it was hard to spot the differences. For each SQL query executed, a new database connection was opened. The block responsible for closing them all, was near the end, and looked something like this:
Once a connection was opened, it stayed opened until the export job completed. There were copy/pasted blocks that repeated the same code again and again, although over time, they had drifted apart so they weren't exactly the same anymore, but mostly. The web page itself handled all of the file I/O, the communication with Excel Interop libraries. One of the XML formats was generated, not by using the XmlWriter object, but by concatenating a pile of strings together. The entire pile was topped off with a bow- the "bow" meaning "only one exception handler for the entire block". The single catch(Exception ex) responded to any error that could possibly happen in that 25,000 line thicket. Its response was to simply print out the informative, "An error has occured(sic). Please correct your request and try again."
Dan wasn't even sure where to start. For the heck of it, he upped the script timeout from 21600 to 43200. He checked that minor change in with the comment, "This should fix timeouts for the foreseeable future," and then started trying to get a grip on how to pry this pile of spaghetti apart and turn it into supportable code.
The next day, he was elbow deep in "Export.aspx"'s entrails when Steve interrupted. "Hey, Dan!" Steve beamed. "Great work on fixing that bug. I saw your check-in, gave it a spin, and promoted it to production. Fantastic turn-around time on that. Look, since you're done, we've got a lot of other projects that could use some TLC- can I move you onto one of those?"
Paul was having a good morning. It was a beautiful day outside, he managed to shave 15 minutes off his commute, and even the local coffee shop had his favorite donut in stock. All of that changed when he got his first support call of the day. It was from a client running "the beast" product. "The beast", as Paul and his coworkers nicknamed it, was a legacy version of their application developed somewhere overseas years before Paul was hired, by hundreds of poorly trained, and probably poorly paid, developers. The company's sales team actively encouraged clients to upgrade from the legacy application, but a select few had resisted.
"The beast" had a reputation for containing some of the worst code Paul had ever seen and every time he had to support it, he felt like he needed a shower afterwards. It was during his fourth hour of debugging that Paul came across a previously unvisited function shown below.
public boolean isWidgetReferenced(int widgetId) {
boolean available = false;
try {
String query;
ResultSet rs = null;
int count = 0;
Connection connection = getConnection();
query = "SELECT COUNT(*) FROM WIDGET_REGION WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_OFFERING WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_ORDERS WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_NEW WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_HISTORY WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_STATS_RECORDED WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_VIEWED WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_SETS WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_INSTALLED WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_PENDING WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
query = "SELECT COUNT(*) FROM WIDGET_JOURNAL WHERE widgetId=" + widgetId;
rs = connection.createStatement().executeQuery(query);
for (; rs.next();) {
count = rs.getInt(1);
break;
}
if (0 < count) return false;
available = true;
} catch (Exception e) {
logger.error("isWidgetAvailable", e);
}
return available;
}
Paul wasn't sure what bothered him the most: that the developer had used a strangely formed for() loop on a structure that always returned exactly one record; that the integer count could have been implemented as a boolean; or that the pattern had been repeated 10 times in this file and dozens of times in other files. As it turns out, the root cause of the issue was unrelated to the sheer amount of repetitive code. Had the developer taken the time to clean up this function, they might have noticed that they never closed any of the JDBC connection resources defined in the method.
"I got this while doing my online homework for a calculus class I am taking," wrote Chase P., "I mean, it's freaking 42 of all numbers - how could it NOT be correct??."
In order to take over the earth, the Brain hatched a plan where he would sieze control of the world's banking system. The plan was true genius, but like all big plans, he had to start somewhere which, in this case, was to take control of OneWest Bank's QuickPricer.
"I know that folks in Texas have strong feelings about where they live," wrote Reinier, "but I had NO idea that people in South Africa did too!"
"I wasn't exactly sure what to do here so," writes Johann, "I figured it safest to click on the "X" to close the window, manually restart, and pray for the best"
"The text translates roughly "Some tray icons can't be shown. There isn't enough space to show all objects in system tray. Uninstall some programs or try to use larger display resolution.," writes Maar, "I guess that I'll be able to justify that larger monitor purchase after all!"
"I think I'm going to take my chances and say 'no' the extended warranty," writes Stewart.
When Greg was shopping for jobs at his college’s career fair, there was a whole lot of business as usual.
The larger banks were on-hand looking to swoon the upcoming Financial grads. Several representatives from a few big name manufacturing corporations were there to interview the Chemistry majors and a few IT firms were on the lookout for the soon-to-be CS grads, like Greg, to add to their ranks. However, amid the ocean of pamphlets and suits there was one aerospace corporation with one particular position that caught Greg’s attention. The position that he applied and was ultimately hired for could be summed up in one sentence:
“You’ll be testing laser tag games for the military.”
A Dream Come True!...kind of
Actually, Greg’s official title was “QA Analyst for Battlefield Training Simulation Systems” but the idea of the system being a great big laser tag game really wasn’t all that far off the mark.
The way the existing setup worked was that sensors on a soldier’s body vest would detect a “hit” during the simulation, and would then set off an annoying alarm that could only be turned off with a special key. Once deactivated, the solder was ‘dead’ for the rest of the training scenario. It all worked, but one big problem with the whole setup was that, to the displeasure of many, a few enterprising soldiers managed to get their hands on and started selling tester keys (also known as “God Keys”) that allowed soldiers to resurrect themselves and get back into the battle.
After a number of years of trying to prevent soldiers from exploiting the system and a host of other technical headaches, the military was finally able to replace their system with something a little newer.
New features like the addition of GPS tracking units, RF data modules reporting hits and their locations and a slew of backend upgrades meant that military trainers could execute more extensive and complex training scenarios and, over time, recoup the costs because the new system was designed to rely on “off the shelf” 3rd party solutions, but first, these solutions would need to be vetted by QA guys like Greg.
Getting Stoned
Like any new hire, Greg was completely pumped and ready to contribute and shake things up his first week, but as time went by, Greg’s excitement dwindled when he found that doing QA analysis didn’t really involve shooting co-workers with laser guns, but instead was a lot of tedious, hard work with project managers and piled on bureaucracy for good measure.
In one particular situation they received a firmware update for one of the GPS systems being used in the Player Unit modules.
While trying to figure out why the latest hardware revision was failing immediately after the first test he noticed that the GPS receiver would send out a burst of garbage every few seconds.
Puzzled by this he checked and re-checked the connections and tried one of the spare units only to find the same result. Everything seemed like it should fine and the supplier swore there was nothing wrong with their system. Not able to let something like this go, Greg spent many late-night hours pouring through raw dumps of the results and along the way, he began to notice a pattern of the same Hex data repeating in the noise. As he painstakingly translated the hexadecimal into ASCII, he was genuinely surprised upon being greeted with a curious snippet of text.
Your PC is now Stoned!
After a quick search on the message, it all made sense. Somehow, the firmware upgrade for the GPS system had become infected with a disk boot sector virus, which ran perfectly fine on the embedded processor. Since this virus couldn't write itself to a disk, as there were no floppy drives on the GPS card, it instead sent itself out through the RS-232 port once every 5 seconds in hopes of infecting another computer.
Greg wrote up his analysis and forwarded it off to the vendor, who quickly (and quietly) issued another update to their firmware, identical to the last except without the virus.
Upon loading of the updated firmware, Greg noticed the difference immediately and was pleased to see that the vendor's "fix" resolved the "data issue" that he'd reported, however, there was a small catch to this tiny update. You see, preliminary testing for military equipment is a long and detailed process that makes the most draconian corporate processes look positively streamlined. Also, since the magic keyword "virus" had been uttered, QA testing couldn't just pick up where it left off, and couldn't just be for the GPS module. In fact, Greg had to start over at step 1 with added "anti-virus" steps add in for good measure just to be sure.
"Do you think it's wise to have consultants running our IT department?" Holger asked. It was an honest question, worded as diplomatically as possible. Holger's company had more consultants on hand than actual IT staff.
"Holger, these folks are experts," his manager replied. "It isn't cost effective to hire-on this level of expertise full time. We may pay a little more up front, but when we don't need the consultants anymore, we can hand it off to our internal people."
Holger left that discussion pretty sure he had just been called incompetent. Maybe I should ask the consultants if they're hiring, Holger wondered to himself, thinking of the big money they pulled down relative to his salary. The thought was still percolating in his head when he sat down with the two newest consultants, Zack and Jack for their status meeting.
Holger hooked his laptop up to the projector and ran through a few recent changes in the configuration database, discussed the implications, and then moved onto other topics. He stopped paying attention to the computer, and it eventually dropped to its screensaver. Moments later, there was some snickering from Zack.
"Having some computer trouble?" Jack asked, mockery in his tone.
Holger glanced at the projection screen and saw that his screensaver was was running merrily. It merrily painted a BSOD to the screen, with plausible driver dumps, merrily churned the disk a little, like it was saving the contents of RAM, and merrily ran through a simulated reboot sequence. After which, the process repeated itself, merrily. "Oh," Holger said, "that happens sometimes. I've got it under control. No worries."
"Yeah, whatever," Jack said. The meeting continued.
The product of the meeting, like too many other meetings with consultants, resulted in the need for another meeting. "Let's see what my calendar looks like," Holger said. He grabbed the mouse, killed the screensaver, and called up his email client.
Zack gasped. "How did you do that?" Jack marveled.
"Oh, that?" Holger said. With his best deadpan, he said, "I got tired of waiting for the reboots to complete. I put together a tool that does an automatic fix and restart, letting me just continue right from where I left off."
Holger waited a beat. After a moment, he was certain that these consultants would realize he was pulling their leg.
Zack was up in a flash and quietly closed the door. Jack leaned across the table towards Holger and asked, "Did you make that on company time? And does anyone here know if you did? Because before we go back into that hallway, I want to buy this off of you."
"You don't have that kind of cash," Holger said.
"No, but I can put it on the expense account and then pay it off when I get VC funding," Jack said.
Holger spent the next fifteen minutes declining their offers to buy his tool. In the process, he discovered that the consultants had creative and unethical ideas about how to quickly get funding, and that one of them had a trophy wife that would do anything for the kinds of profits they were talking about. "And I do mean anything," Zack said with a leer.
Finally, Holger "confessed". "Look, you guys are generous and all, but I've already signed a contract with another company. Even if you could beat their offer, I can't break a contract."
"Sure you can!"
Holger left the meeting without any interest in finding out if their company had any openings.
What's that, you say? We should have an entire Error'd dedicated to CAPTCHA images? Sure, why not!
Alex van Herwijnen spotted this interesting problem presented...
... which, of course Dan Ferrante noticed that ESPN provided a solution for.
You're right though, spousal abuse is not funny. But I know what is! Bathroom humor, like what Scott Lewis found at Ticketmaster!
See? Even Avast! anti-virus software is getting a peece of that action (from Viront).
"Really?" Justin Self wrote, "I have to type this? I just needed some help with Java!"
Well Justin, help was out there... but not for your Java. Matt found this combo, which seems to help with the previous pain in the butt.
I guess I'll take the advice that Tim Gourley saw, at keep it clean from now on.
Moving on, Andy wondered if Bloglines really wanted their CAPTCHA to be linked to the KKK.
"Admittedly, this took me a lot longer to solve than usual," wrote Dan Thompson, "but when I finally got to upload my image, I felt a real sense of achievement."
Everything went dark and a chill wind went up Simon's back. A deep rumble rattled his brain in his skull. He glanced behind him to see Noel looming over him. "Simon, can you ping the Exchange server?"
When the trained bear that doubles as your IT manager asks that question, it's a bad thing. Simon tried to ping Exchange and failed. He then tried to ping an app server. And a database. And the outside world. All dead.
About a thousand users were about to discover that the only IT asset they could access were their desktop computers. Shortly thereafter, the phone next to them was going to ring. The person at the other end would likely scream. And then it would ring again. The ringing and screaming would continue until the network was back up.
They hustled to the server room, with Noel's bulk clearing a path through the corridor. It was hectic, and he may have trampled an intern. In one corner of the server room, a jump-suited man with a tool-belt bobbed his head to the music in his earphones. The server room was so quiet that the two could actually hear his music from across the room.
"What have you done?" Noel rumbled. The ominous wave of fury failed to penetrate the shield of Lady Gaga songs the electrician had surrounded himself with. Noel closed on him and repeated the question, with more volume and a heavy hand on the shoulder.
Once he had the electrician's attention, he didn't wait for an answer. "I will tell you what you have done," Noel said, "since you obviously do not understand. You are drilling away into a little metal box that is labeled 'Uninterruptible Power Supply', rendering it quite interruptible and cutting power to the room."
"I… I'll fix it…" the electrician managed to croak out.
He set to work. Noel set to work as well by providing a profanity laden commentary on the level of failure the electrician had just wreaked, how many tens of thousands of dollars of equipment the electrician had probably damaged, how many users were useless at the moment.
The electrician worked through the tirade, which says good things about his saving throw versus intimidation, even if his saving throw against stupidity left something to be desired. With a sigh of relief, he flipped the circuit breaker. Green blinking lights and the sounds of whirring disks filled the room.
Then the breaker clunked back into position. The servers rattled back to silence. An expensive sounding clunk came from a hard drive somewhere in the room.
"I'll fix it!" the electrician squeaked. After a frantic adjustment, he flipped the breaker again. The show repeated itself, although the encore added some sparks in the UPS. The third time the electrician reached for the breaker, Noel nearly broke his hand off.
"I think that's enough of that for the day," Noel warned.
"The… the breaker can't handle the load?"
Noel ignored the electrician and turned to Simon. "Do you think I can heave him up to the ceiling?" Simon looked up, and fifteen feet away, he saw the spare pin-and-sleeve-plugs that had been installed to power future expansion.
Since the electrician didn't have a ladder -- and since Noel's throwing arm wasn't up to the task -- Simon clambered on his back. One egregious violation of the health-and-safety policy later, the server room was on a different circuit. A round of cajoling, screaming and cursing brought the servers back online, although a few HDDs were trashed. Noel's blood-pressure receded to something slightly less than the water pressure in the Challenger Deep, and Simon drafted a thoroughly plausible explanation as to why there were shoe prints above head level.
The root-cause for the debacle was traced back to Building Facilities. The server room, normally accessible only to sever admins and the facilities manager, contained an emergency power-off switch. Despite the fact that all of those people were quite clear about the purpose of the switch, and that it was clearly marked, someone with pointy-hair had deemed it an "unacceptable" risk, and decided to do an end-run past change-control to "fix" it. After all, if left unfixed, someone might cut off power to the server room and damage the equipment.