Jon works for a small company that sells electronic biofeedback monitors and provides a website that allows customers (mainly health professionals) to upload and interpret the collected data. Not too long ago, they hired an "experienced web developer" named Nigel to help on the web-end of things. After a few weeks of minor site maintenance tasks, Nigel was given his first real feature to implement: a notification system.
The Spec
The idea behind the notifications system was to allow management to communicate with customers about new products, system outages, industry news, and so on. The new feature had to accomplish the following:
- Provide a means for management to display notices to customers.
- A given notice may be intended for just one user, or for multiple users.
- On the notices page, the customer should see all notices that they haven’t yet acknowledged.
- The customer should be able to acknowledge notices so that they’re no longer displayed.
The Design
Spec in hand, Nigel got cracking on his design. The first change on his list involved the database. He wanted to add two tables into the database: "notices" and "notices_user."
notices | notices_user --------------------------+------------------------- > ID: identity(1, 1), pk | >user: varchar(100), pk > noticeDate: datetime | >ID1: int > notice: text | >ID2: int | >ID3: int | >ID4: int | >ID5: int | >ID6: int | >ID7: int | >ID8: int | >ID9: int | >ID10: int | >ID11: int | >ID12: int | >ID13: int | >ID14: int | >ID15: int | >ID16: int | >ID17: int | >ID18: int | >ID19: int | >ID20: int | >ID21: int | >ID22: int | >ID23: int | >ID24: int | >ID25: int | >ID26: int | >ID27: int | >ID28: int | >ID29: int | >ID30: int
While Jon was examining this design, he assumed that it must mean that a user can have a maximum of 30 active notices at a time. A lousy way to do it and there was probably some nasty code to support it, but whatever, it should work.
On closer inspection, though, the IDXX columns didn't contain references to the ID column on notices – the IDXX columns were TINYINT(1)s, and they were used as boolean flags to identify which notices a user could see.
So that means that each user didn't have a thirty-notice limit, but rather the entire system could have a maximum of thirty notices. And as such, existing notices would have to be reused whenever a new notice was added.
Making things even more complicated was that there would be times when very important notices had to be added while there were still notices left unread, either because the customer wanted to save it for future reference or because it was actually unread. Management would either have to delete customers' unread notices or not display important new notices.
How it All Worked
Jon's curiosity was too much to ignore, so he opened up the code file expecting some incredibly clever code to map user notices to the notices table and do all the filtering and sorting. To his dismay, there wasn't much in the notices.asp page.
First, there was a GetNotices function, which fetched all of the data in the notices table into an array. Second, GetUserNotices, which (as you could probably guess) fetched all of the data in the notices_user table into an array.
But the display logic with code all interspersed in the HTML had to be a sight to behold, right? Jon scrolled down the file and revealed the rest of the page:
<table> <tr> <td colspan="5"> <h2>There are no unread messages/notices in your inbox </td> </tr> </table>
And thus the 30-notice limit was effectively reduced to zero. The admin side had some of the functionality complete, but the "view notices" page said there were no notices, no matter what.
Nigel is no longer with the company, which Jon had heard was because he found the work too stressful. Or, maybe he thought it'd be a good idea to make himself scarce before they started publishing too many notices...