![]() |
by Remy Porter on (#3Z5T7)
You have a web application, written in Spring. Some pages live at endpoints where they’re accessible to the world. Other pages require authentication, and yet others require users belong to specific roles. Fortunately for you, Spring has features and mechanisms to handle all of those details, down to making it extremely easy to return the appropriate HTTP error.Unfortunately for you, one of the developers on your team is a Rockstar™ who is Officially Very Smart and absolutely refuses to use the tools your platform provides. When that Certified Super Genius leaves the organization, you inherit their code.That’s what happened to Emmer. And that’s how they found this:
|
The Daily WTF
Link | http://thedailywtf.com/ |
Feed | http://syndication.thedailywtf.com/TheDailyWtf |
Updated | 2025-10-16 20:46 |
![]() |
by Ellis Morning on (#3Z3CY)
Roman K. once helped to maintain a company website that served a large customer base mainly within the United Kingdom. Each customer was itself a business offering a range of services. The website displayed these businesses on a map so that potential customers could find them. This was done by geocoding the business' addresses to get their longitude and latitude coordinates, then creating points on the map at those locations.Simple enough—except that over time, some of the businesses began creeping west through the Atlantic Ocean, toward the east coast of North America.Roman had no idea where to start with troubleshooting. It was only happening with a subset of businesses, and only intermittently. He was certain the initial geocoded coordinates were correct. Those longitude and latitude values were stored in a database table of customer data with strict permissions in place. Even if he wanted to change them himself, he couldn't. Whatever the problem was, it was powerful, and oddly selective: it only ever changed longitude values. Latitude values were never touched.Were they being hacked by their competitors? Were their customers migrating west en masse? Were goblins messing with the database every night when no one was looking?Roman dug through reams of code and log files, searching desperately for any whiff of "longitude." He questioned his fellow developers. He blamed his fellow developers. It was all for naught, for the problem was no bug or hack. The problem was a "feature" of the database access layer. Roman discovered that the user class had a simple destructor method that saved all the currently loaded data back to the database:
|
![]() |
by Remy Porter on (#3Z0ZC)
Krista noticed our article explaining that switches were replacements for ifs. She sent in a version she found in her codebase, around the same idea:
|
![]() |
by Remy Porter on (#3YYGK)
Melinda's organization has purchased a cloud-based storage system. Like any such system, it has a lovely API which lets you manage quotas and login tokens. It also had a lovely CLI, which was helpful for administrators to modify the cloud environment. Melinda's team built a PHP front-end that could not only manage files, but also allowed administrators to manage those quotas.Melinda was managing those quotas, and when she clicked the link to view the quotas, she noticed the URL contained ?token=RO-cmV1c2luZyBrZXlzIGlzIFRSV1RG. When she went to modify the quota, the URL parameter became ?token=RW-cmV1c2luZyBrZXlzIGlzIFRSV1RG. That looked like a security key for their cloud API, transmitted in the open. The RW and RO looked like they had something to do with readwrite and readonly, but that wasn't the security model their storage provider used. When Melinda had another co-worker log in, they saw the same tokens. What was going on?Melinda took a look at the authorization code.
|
by Mark Bowytz on (#3YS50)
"Deep down, I knew this was one of the most honest labels I've ever seen," wrote Bob E.
![]() |
by Remy Porter on (#3YPPP)
“Database portability†is one of the key things that modern data access frameworks try and ensure for your application. If you’re using an RDBMS, the same data access layer can hopefully work across any RDBMS. Of course, since every RDBMS has its own slightly different idiom of SQL, and since you might depend on stored procedures, triggers, or views, you’re often tied to a specific database vendor, and sometimes a version.And really, for your enterprise applications, how often do you really change out your underlying database layer?Well, for Eion Robb, it’s a pretty common occurrence. Their software, even their SaaS offering of it, allows their customers a great deal of flexibility in choosing a database. As a result, their PHP-based data access layer tries to abstract out the ugly details, they restrict themselves to a subset of SQL, and have a lot of late nights fighting through the surprising bugs.The databases they support are the big ones- Oracle, SQL Server, MySQL, and FoxPro. Oh, there are others that Eion’s team supports, but it’s FoxPro that’s the big one. Visual FoxPro’s last version was released in 2004, and the last service pack it received was in 2007. Not many vendors support FoxPro, and that’s one of Eion’s company’s selling points to their customers.The system worked, mostly. Until one day, when it absolutely didn’t. Their hosted SaaS offering crashed hard. So hard that the webserver spinlocked and nothing got logged. Eion had another late night, trying to trace through and figure out: which customer was causing the crash, and what were they doing?Many hours of debugging and crying later, Eion tracked down the problem to some code which tracked sales or exchanges of product- transactions which might not have a price when they occur.
|
![]() |
by Remy Porter on (#3YM4Y)
Today will be a simple one, and it’s arguably low-hanging fruit, because once again, it’s date handling code. But it’s not handling dates where it falls down. It falls down on something much more advanced: conditionals. Supplied by “_ek1nâ€.
|
![]() |
by Remy Porter on (#3YHSJ)
In the Python community, one buzzword you’ll find thrown around is whether or not an approach is “pythonicâ€. It’s a flexible term, and something you can just throw out in code reviews, even if you’ve never written a line of Python in your life: “Is that Pythonic?â€The general rubric for what truly is “pythonic†is generally code that is simple and code that operates explicitly. There shouldn’t be any “magicâ€. But Python doesn’t force you to write “pythonic†code, and it provides loads of tools like decorators and metaclasses that let you get as complex and implicit as you like.One bit of magic is the “dunder†methods, which are Python’s vague approach to operator overloading. If you want your class to support the [] operator, implement __getitem__. If you want your class to support the + operator, implement __add__. If you want your class to support access to any arbitrary property, implement __getattr__.Yes, __getattr__ allows you to execute code on any property access, so a simple statement like this…
|
![]() |
by Remy Porter on (#3YFE0)
About a decade ago, I attended a talk. The speaker made the argument that "legacy code" may have many possible interpretations, but the practical view was to simply think of legacy code as "code without unit tests". Thus, the solution to modernizing your legacy code was to simply write unit tests. Refactoring the code to make it testable would have the side effect of modernizing the code base, and writing tests would act as documentation. It's that easy.Andrew is struggling with some legacy code right now. Worse, they're trying to integrate a large mountain of legacy code into a custom, in-house CI/CD pipeline. This particular pile of legacy code dates back to the mid-2000s, so everything in it is glued together via XML. It was some of that XML code which started failing when Andrew threw some unit tests at it.It doesn't start that bad:
|
by Mark Bowytz on (#3Y9XW)
"Found this in the School of IT. 404: Women not found. Fairly accurate," wrote Maddie J.
![]() |
by Remy Porter on (#3Y7CD)
In terms of elegance, I think the bitmask has a unique beauty. The compactness of your expression, the simple power of bitwise operators, and the way you can see the underlying implementation of numbers laid bare just speaks to me. Of course, bitmasks can be a bit opaque, and you may have to spend some time thinking about what foo &= 0xFF0000 is actually doing, but there’s also something alluring about it.Of course, bitmasks are surprisingly hard. For example, let’s look at some code submitted anonymously. This code is meant to run on a line of coin-operated dryers. Depending on the particular install, how many coins a patron puts in, what modes have been enabled by the owner, and so on, different “extra†features might be disabled or not disabled.Since bitmasks are hard, we’re not going to use one. Instead, let’s have a pile of constants, like so:
|
![]() |
by Remy Porter on (#3Y4WX)
Gregor needed to download a network driver. Upon clicking the link, a "captcha" appeared, presumably to prevent hotlinking to the driver files. It wasn't a real, image-based captcha, but a simple "here's some characters, type them into the box".The code which popped up was "S i u x q F b j NaN 4". He hit the "new code" button, and got "T o A 0 J V s L NaN a". In fact, "NaN" showed up in the penultimate position in every code.Curious, Gregor pulled up the debugger to see how the captcha was generated.
|
![]() |
by Charles Robinson on (#3Y2GF)
A Service-Level Agreement (SLA) is meant to ensure customer issues receive the attention they deserve based on severity. It also protects the support company from having customers breathing down their neck for frivolous issues. All of the parameters are agreed upon in writing ahead of time and both sides know the expectations. That is, until a salesman starts to meddle and mess things up, as happened at the place Dominick worked for.Dominick was a simple remote support tech who fixed things for clients well ahead of the SLA. On the rare occasion there was a priority 1 issue - something stopping anyone in the company from doing work - they had 24 hours to fix it before large monetary penalties would start to rack up. One Friday a priority 4 issue (5 business day SLA) came in from the CFO of a new client. The ticket was assigned to Dominick, who had higher priority work to do for other clients, so he decided it could wait until the following week.Dominick came in Monday morning to find Benjamin, a senior salesman who happened to be a personal friend of the CFO, sitting on his desk with his huge arms crossed. Benjamin glanced at his watch to see it was 7:59 AM. "About time you showed up, Dom. I found out you didn't do the ticket that came in Friday and I want an explanation!"Still in a pre-coffee Monday morning haze, Dominick had to think for a second to figure out what he was talking about. "Oh... that thing about ordering a new printer? That was only priority 4 and it literally said 'no rush' in it. I have 4 more days to get it done."Benjamin sprang up off Dom's desk and used his beefy arms to forcefully shove an index finger into his chest. "You don't get it do you, bro?? When I made this deal with them, I assured them anything would be treated with the highest priority!" Ben shouted while spraying an unsanitary amount of saliva droplets. "I don't care what your silly numbering system says, it needs to get done today!"Ok... well let me sit down and look at it," Dominick said timidly while rubbing the spot on his chest that received a mean poking. Benjamin stormed off to presumably consume another protein shake. He pulled up the ticket about ordering a new printer for the CFO's office. It seemed he'd read about this top of the line printer in some tech magazine and really wanted it. The problem was the printer wasn't even on the market yet - it would be released at the end of the month. Since there was literally nothing Dominick could do to get the printer, he closed the ticket and asked that a new one be submitted when the printer was available.Later that afternoon, Dominick heard stomping behind him and before he could turn around, Benjamin spun him around in his chair and got in his face. "Hey there, bro. Where is my guy's printer?? He told me you closed his submission without ordering it!"Dominick stood up to defend himself and weakly poked Ben in the chest. "Listen, bro! He wants a printer that isn't out yet. The best I can do is pre-order it and have it shipped to him in a couple weeks. I closed the ticket so we don't get dinged on the SLA to get this done in 5 days."Benjamin furrowed his brow and got back within saliva-spraying distance, "You'll have to do better than that, Dom! While you were screwing around not resolving this I made an addendum to their SLA. Any ticket submitted by a CxO level executive will be treated as priority 1 by us. So you better pull whatever techie nerd strings you have to get that printer ordered in the next 24 hours!"After Benjamin stormed off yet again, the reality of what he had done set in. Since the SLA for the printer was now 24 hours, they would start getting charged penalties by tomorrow. Dominick quickly began crafting an email to senior management to explain the situation and how the request wasn't able to be met. He wasn't sure what sort of "techie nerd" resources Benjamin thought he had, but it wasn't going to happen.Predictably, the situation didn't end well. The financial penalties started adding up the following day, and the next day, and so on. It became so expensive that it was more cost-effective to pay the client to modify the addendum to the SLA that Benjamin made (they couldn't be compelled to do so otherwise) than to continue to rack up fines.The end of the month came and the world's most expensive printer finally shipped, which was a relief to everyone. But that also meant the end-of-month financial statements showed the huge deficit caused by it. To compensate, the company decided to lay off 20% of the support staff including Dominick. Benjamin, of course, got to keep his job where he always put customer needs first. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
|
![]() |
by Jake Vinson on (#3Y0QZ)
|
![]() |
by Mark Bowytz on (#3XW0H)
Hey everyone - I'm at a conference this week I'd like to cover a WTF that I've been seeing this week - VENDOR SWAG.Ok, if you are one of those poor souls who are always heads down in code and never attend workshops or conferences, this won't make much sense to you, but here's the deal - companies will set up a booth or a table and will pass out swag in exchange for your contact info and (possibly) a lead. To me, this is easily the dirtiest transaction one can make and rife with inequalities. Your information is super valuable - as in possibly generating thousands or millions of sales dollars. The 'gift' will be SUPER cheap by comparison.How cheap? WELL, here are some examples:
|
![]() |
by snoofle on (#3XSHJ)
Just because a tool is available doesn't mean people will use it correctly. People have abusedbooleans,dates,enums,databases,Go-To's,PHP,reinventing the wheel and even Excel to the point that this forum will never run out of material!Bug and issue trackers are Good Thingsâ„¢. They let you keep track of multiple projects, feature requests, and open and closed problems. They let you classify the issues by severity/urgency. They let you specify which items are going into which release. They even let you track who did the work, as well as all sorts of additional information.Every project, no matter how big or small, should make use of them.Ideally, they would be used correctly.Ideally.Matt had just released the project that he'd been working on for the past few years. As always happens, some "issues" cropped up. Some were genuine defects. Some were sort-of-enhancements based on the fact that a particular input screen was unwieldy and needed to be improved. At least one was a major restructuring of a part of the project that did not flow too well. In all, Matt had seven issues that needed to be addressed. Before he could deliver them, he needed defect tickets in the bug tracking system. He wasn't authorized to raise such tickets; only the Test team could do that.It took a while, but he finally received a ticket to do the work to... but everything had been bundled up into one ticket. This made it very difficult to work with, because now he couldn't just clear each issue as he went. Instead, he had to package them up in abeyance, so to speak, and only release them when they were all complete. This also meant that the test documentation, providing instructions to the Test team as to how to ensure that the fix was working as required, all had to be bundled up into one big messy document, making it more difficult for Testers to do their job as well.So he questioned them: If we can raise a single defect ticket, then what stops us from raising all 7 needed tickets so that the issues can be addressed separately? The answer was: Because these defects appear post-release, it is clear that they weren't caught at the pre-release stage, which means that Somebody Wasn't Doing Their Job Properly in the Test team, which makes them Look Bad; it brings their failure to catch the issues to the attention of Management.In other words, in order to keep the Test team from looking bad, they would only ever raise a single ticket (encompassing all detected issues) for any given release.Imagine if all of the bugs from your last major release were assigned to you personally, in a single ticket. Good luck estimating, scheduling, coding, debugging and documenting how to test the single logical bug!Matt raised this bad practice with management, and explained that while the reason for why they do this is to hide their inadequacy, it also prevents any meaningful way to control work distribution, changes and subsequent testing. It also obscures the actual number of issues (Why is it taking you seven weeks to fix one issue?).Management was not amused at having been misled. [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
|
![]() |
by Ellis Morning on (#3XQ5C)
If you need your user's country of origin, there are many ways you can go about obtaining it programmatically. Some may opt for a simple drop-down that prompts the user to specify his/her country. If you don't want to burden your user this way, you might look at their session data and return their country of origin, time zone, or some other useful information. If you have fancy enough APIs at your disposal, you could even reverse geocode the user's longitude/latitude position and obtain an address.Or, you can start with their location and perform the code equivalent of throwing a dart at a map littered with creepy-looking post-it notes:
|
![]() |
by Remy Porter on (#3XMT7)
I'm an old person. It's the sort of thing that happens when you aren't looking. All the kids these days are writing Slack and Discord bots in JavaScript, and I remember writing my first chatbots in Perl and hooking them into IRC. Fortunately, all the WTFs in my Perl chatbots have been lost to time."P" has a peer who wants to scrape all the image URLs out of a Discord chat channel. Those URLs will be fetched, then passed through an image processing pipeline to organize and catalog frequently used images, regardless of their origin.Our intrepid scraper, however, doesn't want to run the risk of trying to request a URL that might be invalid. So they need a way to accurately validate every URL.Now, the trick to URLs, and URIs in general, is that they have a grammar that seems simple but is deceptively complex and doesn't lend itself to precise validation via regular expressions. If you were a sane person, you'd generally just ballpark it into the neighborhood and handle exceptions, or maybe copy/paste from StackOverflow and call it a day.This developer spent 7 hours developing their own regular expression to validate a URL. They tested it with every URL they could think of, and it passed with 100% accuracy, which sounds like the kind of robust testing we'd expect from the person who wrote this:
|
![]() |
by Remy Porter on (#3XJMP)
Defensive programming is an important tool in any developer's toolbox. In strictly typed languages, types themselves provide a natural defense against certain classes of bugs, but in loosely typed languages, you may have to be more clear about your assumptions.For example, in Python, you might choose to use the assert keyword to, well, assert that something is true. It's often used in debugging, but it's also a good way to ensure that the state of the parameters passed to a function, or some other state of your system is correct before doing anything else. If it's not, the code raises an exception.Dima R found this "interesting" riff on that concept.
|
by Mark Bowytz on (#3XDPZ)
"I think I'm missing some precision in my Dell customer number," writes Steve B.
![]() |
by Remy Porter on (#3XBGT)
Optional parameters are a great tool for building flexible APIs. In most languages, they're not strictly necessary- if you have function overloading, the difference between optional parameters and an overloaded function is just the quantity of boilerplate- but they're certainly a nice to have.Well, they're a nice to have in the right hands.Scattered through their code base, Ian P saw many, many calls to dutData.GetMessages(). As they explored the code base, they used Visual Studio's "go to definition" feature to jump to the implementation- and found they were sometimes ending up in different spots.
|
![]() |
by Remy Porter on (#3X99E)
Sean's ongoing career as a consultant keeps supplying him with amazing code.Let's talk about encapsulation. We put getters and setters around our objects internalsto help keep our code modular. Given an object, we call something like getUsername to extract a piece of that object safely.In the same codebase as IsTableEmpty, Sean found this short-but-sweet gem:
|
![]() |
by Remy Porter on (#3X6YH)
Bad date handling code is like litter: offensive, annoying, but omnipresent. Nobody is specifically responsible for it, nobody wants to clean it up, and we end up ignoring it.Murtaza K offers up a particularly malodorous example, though, that's worthy of note. It's got everything: string mangling, assumptions that ignore locale, bad ternaries, and it's completely unnecessary.
|
![]() |
by snoofle on (#3X4QE)
Those of us that had the luxury of learning to program in C or other non-auto-gc'd langauges, learned early on the habit of writing the allocation and deallocation of a block of memory at the same time, and only then filling in the code in between afterward. This prevented those nasty I-forgot-to-free-it memory leaks.Of course, that doesn't guarantee that memory can't ever leak; it just eliminates the more obvious sources of leakage.Daniel worked on an installation for a theme park attraction sometime back. The task was to use a computer vision system to track the movement of a number of moving projection screens, and then send the tracking data to a video system in order to move the image around within the projection raster to keep it static on the screen.He was using a specialised product designed for industrial machine-vision applications. It was essentially a camera with a small Windows XP machine inside, which ran a custom application developed using a commercial machine vision programming toolkit. The software looked for the position of 4 infra-red LEDs using the camera and then output their coordinates via ethernet to the video system.After the installation was complete, Daniel was back in the home office when he got a call from the park. Apparently the camera software was crashing after around 10 days of uptime. He remoted in and saw the cause was an out of memory failure. This was his worst nightmare.A nice feature of these boxes was that they had a mechanism to essentially 'lock out' changes from the hard drive. After the system was setup and working, an option was enabled which diverted all hard drive writes to RAM, discarding them on a reboot or power down. This had the advantage the camera system didn't require any software maintenance as it would be 'fresh' every time you turned it on, which is great for an installation that could be in place for over 10 years. However he was concerned about what this might mean for uptime as any process which repeatedly wrote any significant amount of data to the drive would quickly fill up the 1GB of RAM available on the cameras. Around 60% of this was used by the running process anyway, so there wasn't a huge amount of headroom.This wasn't a large source of concern when developing the installation as there was an understanding that the system would be powered down every night when the park was closed (which would have been the easy solution to this problem). He'd noticed that the RAM was filling up slowly as the camera ran, but not at a rate which would be dangerous for the target uptime of 24 hours.Unfortunately, the daily power cycle didn't happen, and any kind of system failure caused the on-site techs to get nervous; clearly this was an issue that would have to be fixed the hard way. He was convinced that the drive lock-out feature was the cause of this issue.From then on, every 10 days, when the park was closed, Daniel remoted in and tried various steps on the cameras to find the process that was writing to "disk". The complete installation had 6 cameras so he would try different steps on each system to try and diagnose the issue, enabling/disabling various system processes and options within the machine vision development toolkit used to write the application. He would leave it for 10 days and then wait to hear from the onsite techs if the changes had been successful. These failures went on for around 2 months.Finally in desperation, Daniel sent off the custom machine vision application to the company who developed the programming toolkit for their developers to analyze and see if they could point to the process causing the hard drive write.Around a week later, they emailed back saying We couldn't find any hard drive write, but we did locate a small memory leak in one of your routines, around 8 bytes per image frame. The routine in question was in the main image analysis path. The cameras ran at 60 fps, so some quick arithmetic yields:
|
by Mark Bowytz on (#3WZTQ)
"So I can keep my current language setting or switch to Pakistani English. THERE IS NO IN-BETWEEN," Robert K. writes.
![]() |
by Remy Porter on (#3WXHF)
When looking for representative lines, ternaries are almost easy mode. While there’s nothing wrong with a good ternary expression, they have a bad reputation because they can quickly drift out towards “utterly unreadableâ€.Or, sometimes, they can drift towards “incredibly stupidâ€. This anonymous submission is a pretty brazen example of the latter:
|
![]() |
by Remy Porter on (#3WVAR)
Alex F is suffering from a disease. No, it’s not disfiguring, it’s not fatal. It’s something much worse than that.It’s MUMPS.MUMPS is a little bit infamous. MUMPS is its own WTF.Alex is a support tech, which in their organization means that they sometimes write up tickets, or for simple problems even fix the code themselves. For this issue, Alex wrote up a ticket, explaining that the users was submitting a background job to run a report, but instead got an error.Alex sent it to the developer, and the developer replied with a one line code fix:
|
![]() |
by snoofle on (#3WS3H)
When the big banks and brokerages on Wall Street first got the idea that UNIX systems could replace mainframes, one of them decided to take the plunge - Big Bang style. They had hundreds of programmers cranking out as much of the mainframe functionality as they could. Copy-paste was all the rage; anything to save time. It could be fixed later.Senior management decreed that the plan was to get all the software as ready as it could be by the deadline, then turn off and remove the mainframe terminals on Friday night, swap in the pre-configured UNIX boxes over the weekend, and turn it all on for Monday morning. Everyone was to be there 24 hours a day from Friday forward, for as long as it took. Air mattresses, munchies, etc. were brought in for when people would inevitably need to crash.While the first few hours were rough, the plan worked. Come Monday, all hands were in place on the production floor and whatever didn't work caused a flurry of activity to get the issue fixed in very short order. All bureaucracy was abandoned in favor of: everyone has root in order to do whatever it takes on-the-fly, no approvals required. Business was conducted. There was a huge sigh of relief.Then began the inevitable onslaught of add this and that for all the features that couldn't be implemented by the hard cutoff. This went on for 3-4 years until the software was relatively complete, but in desperate need of a full rewrite. The tech people reminded management of their warning about all the shortcuts to save time up front, and that it was time to pay the bill.To their credit, management gave them the time and money to do it. Unfortunately, copy-paste was still ingrained in the culture, so nine different trading systems had about 90% of their code identical to their peers, but all in separate repositories, each with slightly different modification histories to the core code.It was about this time that I joined one of the teams. The first thing they had me do was learn how to verify that all 87 (yes, eighty seven) of the nightly batch jobs had completed correctly. For this task, both the team manager and lead dev worked non-stop from 6AM to 10AM - every single day - to verify the results of the nightly jobs. I made a list of all of the jobs to check, and what to verify for each job. It took me from 6AM to 3:00PM, which was kind of pointless as the markets close at 4PM.After doing it for one day, I said no way and asked them to continue doing it so as to give me time to automate it. They graciously agreed.It took a while, but I wound up with a rude-n-crude 5K LOC ksh script that reduced the task to checking a text file for a list of OK/NG statuses. But this still didn't help if something had failed. I kept scripting more sub-checks for each task to implement what to do on failure (look up what document had the name of the job to run, figure out what arguments to pass, etc., get the status of the fix-it job, and notify someone on the upstream system if it still failed, etc). Either way, the result was recorded.In the end, the ksh script had grown to more than 15K LOC, but it reduced the entire 8+ hour task to checking a 20 digit (bit-mask) page once a day. Some jobs failed every day for known reasons, but that was OK. As long as the bit-mask of the page was the expected value, you could ignore it; you only had to get involved if an automated repair of something was attempted but failed (this only happened about once every six months).In retrospect, there were better ways to write that shell script, but it worked. Not only did all that nightly batch job validation and repair logic get encoded in the script (with lots of documentation of the what/how/why variety), but having rid ourselves of the need to deal with this daily mess freed up one man-day per day, and more importantly, allowed my boss to sleep later.One day, my boss was bragging to the managers of the other trading systems (that were 90% copy-pasted) that he no longer had to deal with this issue. Since they were still dealing with the daily batch-check, they wanted my script. Helping peer teams was considered a Good Thingâ„¢, so we gave them the script and showed them how it worked, along with a detailed list of things to change so that it would work with the specifics of their individual systems.About a week later, the support people on my team (including my boss) started getting nine different status pages in the morning - within seconds of each other - all with different status codes.It turns out the other teams only modified the program and data file paths for the monitored batch jobs that were relevant to their teams, but didn't bother to delete the sections for the batch jobs they didn't need, and didn't update the notification pager list with info for their own teams. Not only did we get the pages for all of them, but this happened on the one day in six months that something in our system really broke and required manual intervention. Unfortunately, all of the shell scripts attempted to auto correct our failed job. Without. Any. Synchronization. By the time we cleared the confusion of the multiple pages, figured out the status of our own system, realized something required manual fixing and started to fix the mess created by the multiple parallel repair attempts, there wasn't enough time to get it running before the start of business. The financial users were not amused that they couldn't conduct business for several hours.Once everyone changed the notification lists and deleted all the sections that didn't apply to their specific systems, the problems ceased and those batch-check scripts ran daily until the systems they monitored were finally retired. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
|
![]() |
by Remy Porter on (#3WPYK)
A project is planned. Gantt charts are drawn up. Timelines are set. They're tight up against the critical path, because including any slack time in the project plan is like planning for failure. PMs have meetings. Timelines slip. Something must be done, and the PMs form a nugget of a plan.That nugget squeezes out of their meeting, and rolls downhill until it lands on some poor developer's desk.That poor developer was Alona."Rex is the lead architect on this," her manager said. "And the project is about 90% complete… but even with that, they're never going to hit their timeline. So we're going to kinda do an 'all hands' thing to make sure that the project completes on time."Alona was a junior developer, but even with that, she'd seen enough projects to know: slamming new resources onto a project in its final days never speeds up its completion. Even so, she had her orders.Alona grabbed the code, checked the project backlog, confirmed her build environment, and then talked to the other developers. They had some warnings."It uses a lot of threads, and… well, the thread model is kinda weird, but Rex says it's the right way to do this.""I don't understand what's going on with these threads, but I'm sure Rex could explain it to you.""It's heavily CPU bound, but we're using more threads than we have cores, but Rex says we have to do it that way in order to get the performance we need."Alona had never met Rex, but none of that sounded good. The first tasks Alona needed to grab off the backlog didn't have anything to do with the threads, so she spent a few days just writing code, until she picked up a bug which was obviously caused by a race condition.From what she'd seen in the documentation and the code, that meant the problem had to be somewhere in MainComputationThread. She wasn't sure where it was defined, so she just did a quick search for the term class MainComputationThread.It returned twenty hits. There was no class called MainComputationThread, though there was an interface. There were also classes which implemented that interface, named things like MainComputationThread1 and MainComputationThread17. A quick diff showed that all twenty of the MainComputationThreadn classes were 1,243 lines of perfectly identical code.They were also all implemented as singletons.Alona had never met Rex, and didn't want to, but she needed to send him an email and ask: "Why?"
|
by Mark Bowytz on (#3WJ2Y)
Jakub writes, "I'm not sure restarting will make IE 'normal', but yeah, I guess it's worth a shot."
![]() |
by Remy Porter on (#3WFNR)
Lucio Crusca is a consultant with a nice little portfolio of customers he works with. One of those customers was also a consultancy, and their end customer had a problem. The end customer's only in-house developer, Tyrell, was leaving. He’d worked there for 8 years, and nobody else knew anything about his job, his code, or really what exactly he’d been doing for 8 years.They had two weeks to do a knowledge transfer before Tyrell was out the door. There was no chance of on-boarding someone in that time, so they wanted a consultant who could essentially act as a walking, talking USB drive, simply holding all of Tyrell’s knowledge until they could have a full-time developer.As you can imagine, the two week brain-dump turned into a two week “documentation crunch†as pretty much nothing had any real documentation. That lead to comments like:
|
![]() |
by Remy Porter on (#3WDBR)
If there’s one big problem with XML, it’s arguably that XML is overspecified. That’s not all bad- it means that every behavior, every option, every approach is documented, schematized, and defined. That might result in something like SOAP, which creates huge, bloated payloads, involves multiple layers of wrapping tags, integrates with discovery schemas, has additional federation and in-built security mechanisms, each of which are themselves defined in XML. And let’s not even start on XSLT and XQuery.It also means that if you have a common task, like embedding arbitrary content in a safe fashion, there’s a well-specified and well-documented way to do it. If you did want to embed arbitrary content in a safe fashion, you could use the <![CDATA [Here is some arbitrary content]]> directive. It’s not a pretty way of doing it, but it means you don’t have to escape anything but ]]>, which is only a problem in certain esoteric programming languages with rude names.So, there’s an ugly, but perfectly well specified and simple to use method of safely escaping content to store in XML. You know why we’re here. Carl W was going through some of the many, many gigs of XML data files his organization uses, and found:
|
![]() |
by Remy Porter on (#3WB3E)
There are merits and disadvantages to including any sort of programming challenge in your interview process. The argument for something like a FizzBuzz challenge is that a surprising number of programmers can’t actually do that, and it weeds out the worst candidates and the liars.Gareth was interviewing someone who purported to be a senior developer with loads of Java experience. As a standard part of their interview process, they do a little TDD based exercise: “here’s a test, here’s how to run it, now write some code which passes the test.â€The candidate had no idea what to make of this exercise. After about 45 minutes which resulted in three lines of code (one of which was just a closing curly bracket) Gareth gave the candidate some mercy. Interviews are stressful, the candidate might not be comfortable with the tools, everybody has a bad brainfart from time to time. He offered a different, simpler task.“Heres’s some code which generates a list of numbers. I’d like you to write a method which finds the number which appears in the list most frequently.â€
|
![]() |
by Remy Porter on (#3W8V1)
An anonymous reader had something to share."I came across this code in a 13,000 line file called Constants.cs."
|
by Mark Bowytz on (#3W40W)
"I think I'll order the big-busted truck," writes Alicia.
![]() |
by Remy Porter on (#3W1SJ)
The Joel Test is about to turn 18 this year. Folks have attempted to “update†it, but even after graduating high school, the test remains a good starting point for identifying a “good†team.Mike was impressed to discover a PHP script which manages to fail a number of points on the Joel Test in only 8 lines.
|
![]() |
by Remy Porter on (#3VZGF)
There are certain languages which are still in use, are still changing and maturing, and yet are also frozen in time. Fortran is a perfect example- over the past 40–60 years, huge piles of code, mostly for scientific and engineering applications, was written. It may be hard to believe, but modern Fortran supports object-oriented programming and has a focus on concurrency.Most of the people using Fortran, it seems, learned it in the 70s. And no matter what happens to the language, they still write code like it’s the 70s. Fortran’s own seeming immortality has imbued its users with necromantic energy, turning them into undying, and unchanging Liches.Which brings us to Greg. Greg works with an engineer. This engineer, the Dark Lich Thraubagh, has a personal “spellbook†containing snippets of Fortran they’ve picked up over the past 40 years. For example, there’s this block, which creates an array of every number from 1–999, padded out to three characters.I don’t know Fortran, so I give credit to this engineer/lich for writing code which even I can understand why it’s wrong and bad.
|
![]() |
by snoofle on (#3VX87)
During the browser wars of the late 90's, I worked for a company that believed that security had to consist of something you have and something you know. As an example, you must have a valid site certificate, and know your login and password. If all three are valid, you get in. Limiting retry attempts would preclude automated hack attempts. The security (mainframe) team officially deemed this good enough to thwart any threat that might come from outside our firewall.As people moved away from working on mainframes to working on PCs, it became more difficult to get current site certificates to every user every three months (security team mandate). The security team decreed that e/snail-mail was not considered secure enough, so a representative of our company had to fly to every client company, go to every user PC and insert a disk to install the latest site certificate. Every three months. Ad infinitum.You might imagine that this quickly became a rather significant expense for the business (and you'd be right), so they asked our department to come up with something less costly.After a month of designing, our crack engineers came up with something that would cost several million dollars and take more than a year to build. I tried, but failed to stifle a chuckle. I told them that I could do it for $1500 (software license) and about two days of work. Naturally, this caused a wave of laughter, but the boss+1 in charge asked me to explain.I said that we could put an old PC running a web server outside the firewall and manually dump all the site certificate installer programs on it. Then we could give the help desk a simple web page to create a DB entry that would allow our users to go to that PC, load the single available page to enter the unique code provided by the help desk, and get back a link to download a self-installing program to install the site certificate.To preempt the inevitable concerns, I pointed out that while I had some knowledge of how to secure PCs and databases, that I was not by any means an expert, but that our Security Analysts (SAs) and DBAs were. We could have the SA's strip out all but the most necessary services, and clamp down the firewall rules to only let it access a dedicated DB on an internal machine on a specific port. The DBA's could lock down the dedicated DB with a single table to only allow read access from the web page; to pass in the magic phrase and optionally spit back a link to download the file.Of course, everyone complained that the PC in-the-wild would be subject to hacking.Since I believe in hoping for the best but planning for the worst, I suggested that we look at the worst possible case. I take out a full page ad in Hacker's Weekly saying "Free site certificates on exposed PC at IP a.b.c.d. They can be used at http://www.OurCompany.com. Enjoy!" After all, it can't get worse than that, right? So Mr. Hacker goes to the page and downloads the site certificate installation programs for every user and then goes to our website. What's the first thing he faces? Something he has and something he knows. He has the certificates, but doesn't know any login/passwords. Since the security people have already blessed this as "Good Enough", we should be safe.After much discussion, everyone agreed that this made sense, but that they (reasonably) wanted to verify it. It was agreed that the SA's and DBA's had the needed expertise to strip and lock down the PC, firewall and DB. I took an old PC out of one of the closets, did a fresh install, put on the latest web server and relevant software, and then installed the few things we needed. Then I handed it to the SA's and told them to strip it and lock it down. I created a tiny DB with a single table and two stored procedures; one for the help desk to add a new time-limited entry for a user and the other to check to see if an unexpired entry existed and return a link to the installer on the exposed PC. Then I handed it to the DBA's and told them to restrict it so the table could only be accessed via the two stored procs, and to only allow the Help desk to call the proc that created the time limited entry for the user, and the external IP to call the proc to query the table. Since all of our users already had credentials to call the help desk, this was only a minimal additional cost.We threw a couple of test certificate installers on it and put it outside the firewall. After I tested the "good" paths, I had the SA's and DBA's try to hack around their restrictions. When they couldn't, it was deemed safe and loaded up with all the certificates. I wrote up a very short how-to manual and had it installed in production.This reduced the certificate installations to one trip per quarter to our data center.The user was pleased at having saved millions of dollars on an ongoing basis.I found out later that I inadvertently pissed off the boss+1 because he was planning on hiring more people for this project and I negated the need for him to expand his empire.Whoops. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
|
![]() |
by Charles Robinson on (#3VV1M)
Gustav's tech support job became a whole lot easier when remote support technology took off. Instead of having to slowly describe the remedy for a problem to a computer-illiterate twit, he could connect to their PC and fix it himself. The magical application known as TeamViewer was his new best friend.Through Gustav's employer's support contract with CAD+, a small engineering design firm, he came to know Roger. The higher-ups at CAD+ decided to outsource most of their IT work and laid off everyone except Roger, who was to stay on as liaison to Gustav and Co. Roger was the type whose confidence in his work did not come close to matching the quality of it. He still felt like he could accomplish projects on his own without any outside help. Thanks to that, Gustav had to get him out of a jam several times early in their contract.Roger's latest folly was upgrading all of the office workstations from the disaster that was Windows Vista to the much more reliable Windows 7. "I had such a smooth rollout to Windows 7, I tell ya," Roger bragged over the phone. "I brilliantly used this cloning process to avoid installing the same things repeatedly!" Gustav rolled his eyes while wondering if this was a support call or if Roger just needed someone to talk to. "Well anywho, I had two system images - one with the basic software everyone gets, and one that included SolidWorks for our CAD designers. Seems they don't have SolidWorks even though I installed it. Can you do your support wizardry and take a look?"Gustav agreed and was transferred to Dave, their lead CAD designer. He figured Dave just didn't know where to find SolidWorks on the new OS and it would be a quick call. He got Dave's TeamViewer ID and connected to his PC in no time. He decided to ignore the fact that Dave had a browser open to an article about the twenty greatest Michael Bolton songs of all time."Thanks Dave, I'm in. Are you able to see me moving your mouse?" Gustav asked. He wasn't. "Ok then, there must be some lag here. I'm going to look around to find where you have SolidWorks and make a shortcut for you." Gustav spent the next few minutes looking at the places any sane person would install SolidWorks. Since Roger wasn't sane, he didn't find it in a logical directory. He then went to Programs and Features and noticed that it wasn't installed anywhere."Hey Dave, bad news," Gustav informed. "It seems like your PC got the wrong image from Roger and your CAD software isn't on there.""Bummer. I didn't know if you were doing anything, on my side the computer screen was just sitting there," Dave replied, just as an incredible ruckus broke out behind him. Gustav could hear doors slamming and someone cursing at Roger in the background. Dave chuckled quietly into the phone."... is everything ok there?" Gustav asked, concerned."Oh, that's just Old Lennart throwing a fit. He's our cranky old Vice President. He's super pissed because Roger keeps hacking his computer and messing around on it."Gustav suddenly had a suspicion. "Dave, don't take this the wrong way, but were you reading an article about Michael Bolton's greatest hits?" he asked cautiously."Hell no, why would I be doing that?" Dave shot back, almost sounding insulted. Gustav apologized and quickly ended their call.Once Roger was done getting chewed out by Old Lennart, Gustav gave him a call. In their discussion, Roger revealed how he'd installed TeamViewer before making his system clones to save time. Gustav explained how that caused every system image to have the same TeamViewer ID, which was bad. Since Old Lennart was always the first one in the office each morning, any remote connection through TeamViewer would connect to his PC. Thus, whenever Gustav or one of his cohorts connected for remote support, it seemed like someone was hacking in to Lennart's computer.Roger remedied the problem over the next couple days by reinstalling TeamViewer and bringing in a series of "I'm sorry" baked goods for Old Lennart; but it wasn't enough to save his hide. By the end of the week, he was informed that their IT department would be further reduced from one employee to zero. With his computer and Roger problems addressed, Old Lennart could return to researching his favorite performing artist. [Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.
|
by Mark Bowytz on (#3VP8S)
"I suppose the ropes were there to keep the infection from spreading to other screens," Stan I. wrote.
![]() |
by Remy Porter on (#3VM0M)
Sandra’s ongoing battles continue. She currently works for Initrovent, and is doing her best to clean Karl’s dirty fingerprints off their event-planning codebase.Now, as it turns out, Karl wasn’t their only developer. Another previous developer was a physicist who knew their way around APL and Fortran, then decided to follow the early 2000s money and became a self-taught web developer.This Einstein decided to solve some problems, common problems, utility problems, the kind of things you might want to put in your central library and reuse in every project.For example, do you hate comparisons? Does writing if ($x == $y)… make your skin crawl? Don’t you just wish you could write something like, compareValues($x, $y, '==') instead?Well, have I got news for you.
|
![]() |
by snoofle on (#3VHNE)
Anyone with more than a few years of experience has been called upon to interview candidates for a newly opened/vacated position. There are many different approaches to conducting an interview, including guessing games, gauntlets and barrages of rapid-fire questions to see how much of the internet the candidate has memorized.
|
![]() |
by Alex Papadimoulis on (#3VFS7)
The "Enterprise DevOps" tools market has really been taking off lately, and so has Inedo! We build market-leading tools for package management, deployment automation, and configuration automation space that aids some of the world's best companies in delivering their applications to users faster than ever.We're looking for some great people to help us continue to grow:
|
![]() |
by Remy Porter on (#3VF8T)
Documentation is difficult in the best of situations. I've encountered lots of bad documentation. Bad because it's unclear, inaccurate, or incomprehensible. Bad because it's non-existent. Bad because it insists on strictly using the vendor's own in-house terms, carefully chosen to be the most twee little metaphors they could imagine, but never explains those terms, thus being both incomprehensible and infuriating. "Enterprise" packages bring their own quirks and foibles, and tend to be some combination of unclear, inaccurate, or incomprehensible. Unless, sometimes, what we attribute to incompetence probably is actual malice.I've brushed up against a lot of ERP systems in may day, ranging from the home-(over)-grown Excel spreadsheet on the network drive all the way to gigundous SAP build-outs.On such project involved migrating 12 business units from a mixture of home-grown systems, legacy mainframe systems, and home-grown systems running on legacy mainframes into one, single, cohesive ERP. The product chosen was an offering from a company we'll call "Augur". Augur took one look at our insanely ambitious project, knew it was doomed to failure, and muttered to themselves, "Think about the consulting fees we can rack up!"Of course, my employer didn't want to pay the consulting fees. They already had Augur domain experts hired in from a much cheaper consultancy, and our in-house developers knew how to read documentation. What could go wrong?Plenty, but one of the smaller, simpler tasks I tackled delivered the biggest WTF. In a factory, there was a flow meter hooked up to a pipe that could tell us how much raw material flowed through that pipe. That flow meter was hooked up to a proprietary database with a very picky and flaky ODBC driver. I needed to get data out of the proprietary database and pass it off, after a little massaging, to Augur's ERP. Based on whatever product the ERP believed was being made at the time, it would then calculate raw material consumption, cost-of-goods-sold (COGS), losses, and all sorts of other wonderful production statistics.Talking to the proprietary database involved some DLL hell, but once I was getting the data, it was time to feed it into Augur. The documentation for their consumption APIs said that I should call a method called RM_CONS_IN_FRMLU_FPT. It told me how to structure the data. It told me what other parameters needed to be set. I followed the instructions and checked the results: consumption got updated, but not COGS.I checked my work. I rechecked the documentation. I skimmed through the underlying tables to understand the schema hiding beneath the API. I cried a little when I saw it, and then I went back to the docs. I twiddled a few parameters, and tried again. This time COGS was right, but consumption wasn't. Tried again, and now it refused to recognize the current production formula, and assumed I was just disposing of material, and only incremented my losses.Eventually, I discover that RM_CONS_IN_FRMLU_FPT is actually a wrapper method for RM_FPT_CONS_BY_UT. I have to bootstrap a few more complex parameters myself, but I try again. Still doesn't works. Back to the docs, and then I notice a tiny little footnote: "To calculate COGS accurately, the parameter rec_cons_config must have its cogs_behavior property set to 57". So I tried that.It crashed. It didn't just crash, though, it managed to go romping off down a bad code branch, mangled a bunch of records, committed the changes, and then crashed. I reset my dev environment and went back to the docs.This time, I trace through a few references, discover another footnote which is itself reference to a white paper, which itself contains a footnote. "If cogs_behavior is set,RM_CONS_BY_UT,RM_CONS_IN_FRMLU_FPT,RM_CALC_FRMLUandCOGS_RM_CALC_USAGE may alter data in an unrecoverable fashion."Now, Augur's database technology separates the header for a code package from the body. This is great for Augur, as they can distribute the compiled versions of their proprietary stored procedures, but not the code. That was less great for me, as I couldn't just read the code to see what it was doing, but I could read the headers.And there were so many undocumented parameters, each using undocumented record data types- Augur's equivalent of a struct. Tracing through the headers, I eventually found that there was a flag which was, for all intents and purposes, the secret_make_cogs_work_flag. I flipped that to true, and voila, suddenly everything was calculating.I can't say, beyond a shadow of a doubt, that the documentation lied to me. It could have been wrong, outdated, or I could have just misread things. But given the problem- a major feature doesn't work or even destroys data- and given the simplicity of the fix, I can't see it as anything but an active attempt to mislead."Never attribute to malice what could be explained by incompetence- unless it's a major enterprise product vendor, in which case they really just want to sell you consulting." [Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
|
![]() |
by Jane Bailey on (#3VD3V)
"Have you had a chance to look at that JIRA ticket yet?"Marge debated pretending she hadn't seen the Slack message yet—but, if she did, she knew Gary would just walk over to her desk and badger her further. In truth, she didn't want to look at the ticket: it was a low priority ticket, and worse, it only affected a small fraction of one client's customers, meaning it was likely to be some weird edge case bug nobody would ever run into again. Maybe if I ignore it long enough, it'll go away on its own, she thought.The client was a bookseller with a small but signifigant-to-them online presence; the software they used to sell books, including your standard e-commerce account functionality, was made by Marge's company. The bug was somewhere in the password reset feature: some customers, seemingly at random, were unable to use the password reset link the software emailed out.Marge pulled up the ticket, looking over the half-hearted triage work that had been done before it landed on her desk to solve. The previous guy had pulled logs and figured out that all the customers who were complaining were using the same ISP based out of Germany. He'd recommended reaching out to them, but had been transferred to another division before he'd gotten around to it.When Marge realized that the contact information was all in German, she almost gave up then and there. But with the magic of Google Translate, she managed to get in touch with a representative via email. After a bit of back and forth, she noticed this gem in one of his (translated) replies:
|
by Mark Bowytz on (#3V86K)
"Evidently, once you hit 55, LinkedIn thinks you'll age until your buffer overflows," writes Jonathan L.
![]() |
by Ellis Morning on (#3V5VT)
|
by Mark Bowytz on (#3V3J1)
![]() |
by Alex Papadimoulis on (#3V17G)
|
by Alex Papadimoulis on (#3TYXC)