Nothing more, and nothing less
Dear CMS writers:
I think I hate all of you. Including me. Will you take it personally if I take your code and fling it against the nearest wall, screaming and cursing, until your code either a) bleeds or b) apologizes and fixes itself? It would really make me feel better if I could just do that and get it out of my system.
See, I'm just trying to write a portal script here, and every CMS I've tackled keeps making me madder and madder. At this rate, in approximately another ten minutes I will have puffed up to the size and shape of that enormous Sta-Puf marshmallow guy from Ghostbusters. Since I suspect that swelling to that size and shape will not be good for my longterm health, I am currently beating on my keyboard and creating words that are quickly taking on the form and shape of a rant.
Part I: what time is it?
Could someone, somewhere, please wake up to the realization that storing dates in local time is stupid, stupid, stupid? I mean, sure, saving things in local time is the quickest way in the short run, but not only are you shooting yourself in the foot, you are guaranteeing that aftermarket script writers like myself are dreaming of your ultimately gory demise.
Why, you say?
Take the script that I'm currently writing. You know what I need for each post? A GMT/UTC timestamp. Bless you, Gareth, for threatening to shoot me a year ago if I didn't store dates/times in GMT. You know what it takes in Quarto to get a nice happy seconds-from-epoch timestamp for a post? 'SELECT unix_timestamp(entry_date) AS timestamp FROM qt_entries.' Boom. That's it. You're set. Move on to something more interesting.
You know what it takes everywhere else? Finding out on a CMS-by-CMS basis how they're saving offsets from "server time" (and no, server time does not necessarily equate to GMT). In greymatter it's saved as a [+/-]decimal in the 9th (8th, to PHP) line of gm-config.cgi. In MovableType it's saved as [+/-]hh:mm and is accessible as the variable . b2 appears to save it as a [+/-]decimal under the column time_difference in the settings table of the database. (I dread finding out what PMachine's specs are; I'm sure they will somehow manage to be different from everything else that has come before.)
Once you've got that information - jolly! - you can eventually reconstruct a unix timestamp after a few jogs and giggles. Yay for PHP's gmmktime() function.
It should not be this way. Timezones are completely bloody irrelevant to a server; they're human constructs to help us equate time of day across the globe. Times should be saved as GMT, so that things are consistent across the globe, and only formatted into timezones when they are presented to a user, who, unlike the server, thinks in terms of timezones.
(In addition, this provides for the possibility of allowing users to set their own timezone, which is classy. Not everyone lives in your timezone - there are people reading domesticat who live in Hawaii, Australia, and England. It's nice to be able to provide each of them times that make sense … to them.)
Part II: give me only what I ask for
What, you thought timezones were all I wanted to rant about today? Ha.
When I request information from a CMS - database or otherwise - do not give me more than what I ask for. Don't return extraneous carriage returns. If I set up a file that, on the first line, requests data to be placed on that line, don't insert carriage returns before it without my permission. I beat on the wonderPortal data file for one of the data files for well over an hour before I realized that I was doing nothing wrong - that, indeed, it was always going to insert an unrequested carriage return at the beginning of the document.****
Why does this matter? wonderPortal expects one bit of information per line. For now, line[0] equates to the author's name, line[1] to the entry's URL, line[2] to the entry's title. An unasked-for carriage return shifts all information down a line and would, if I hadn't caught it, force wonderPortal to try to use the author's name as the URL, and the entry's URL as the entry's title.
Don't return extra crap when I query your CMS for information. Give me what I ask for. Nothing more, and nothing less. Otherwise every other data file has to be changed to work around your issues, and forcing others to work around your issues is tacky, even by my standards.
Part III: database design
So, I've made it this far. Now we reach the point where my head actually exploded (cleanup crews will arrive shortly). So I've figured out how to make greymatter and MovableType cough up timestamps in GMT. Works for me. It was a pain in the ass, but I figured out how to do it in a way that should cause the minimum amount of annoyance on the part of the end-user.
It was b2 that very nearly made me hurl my monitor against the wall. I thought, "Hey! It's based off of PHP and mySQL, so perhaps I won't have to do too much work on this one. Maybe they got it right…" Nope. Local timestamps. Grr. I can work with that, though I don't like to - so I started working through the conversion.
(I'm cranky - I refuse to look at the source code or install scripts of any other CMS while I'm working on my own, because I want my code to be wholly my own. Luckily, Chris was kind enough to help generate mySQL descriptions of all the tables in the b2 schema. Dancing virgins and pounds of Ben & Jerry's to you, sir.)
I started comparing table schemas, and began to piece together a query. Then I realized what I was looking at: fields in different tables with exactly the same names. Lovely. So, let me get this straight… the unique id for each entry in the posts table is called id, the unique id for each site in the settings table is called id, and the unique id for each user in the users table is called id?
So what happens when you join two tables together, and they both have fields named id for different things? Yep - every time, you must rename each instance of id to something that is more obvious, like entry_id, site_id, or user_id. True, it's not difficult to rename these fields in your queries, but do I really have to point out how excruciatingly annoying it is to have to type things like "SELECT j_users(id) AS user_id, j_posts(id) AS entry_id…" for every multi-table query when it should have been something like "SELECT user_id, entry_id…" in the first place?
Once upon a time, Gareth chastised me for feeling bad about how long it was taking me to get a Quarto database schema finalized, telling me that extra time spent on streamlining and bulletproofing my database schema would pay for itself in ease of use (and customization) later.
I'm starting to see that once again, he was right. In this sort of thing, he usually is.
Part IV: all those apologies
I have to be careful. Am I a professional coder? No. I am an experienced and patient amateur—but I am an amateur that has written her own CMS, and can speak firsthand of the thousands of arbitrary decisions that have to be made in the design and coding stages. I make absolutely no pretensions whatsoever about any supremacy of what I wrote; I can guarantee you that Quarto undoubtedly fails on tests of efficiency and usability.
I spent a lot of time questioning why I was even bothering to write a CMS of my own, when other CMSes, written by far more skilled coders, already existed. Initially, I believed those CMSes to be so far ahead of my own ability that anything I wrote would exist as nothing but a paler, less-functional copy of those better originals.
I spent a lot of time asking myself why the hell I bothered, when it would have been easier to pay $30, get a fully-functioning version of another CMS, convert my files to their database format of choice, and be done with it. At first my answer was sheer obstinacy. Then it was the native ability to save posts in multiple-and-equal categories (not primary and secondary categories). Then it was the ability to send notification emails on new posts/comments/user signups. Then it was providing extra privileges to email-verified users, such as being able to subscribe to new comments on posts.
I never, ever expected it to be something so basic as GMT timestamps - a concept so simple that I had it drilled into me during my one measly semester of database theory in college. This was basic stuff, the stuff I took for granted from day one and never thought about again.
There are plenty of 'compatibility' things out there now that are de rigueur bits for various CMSes, like supporting a Blogger API. Forgive me, but I'm having just a wee bit of trouble not rolling my eyes on that point - people championing 'cross-compatibility' features like that when, if you ask me, there are existing problems far deeper and basic than figuring out how to let some web wonk have the instant gratification of posting from their cell phone.
With that said, I think it unlikely now that I'm going to kill anyone or go Sta-Puf on the populace. I'll get back to working on the data file for b2. I realize that I can't change how others will code their own CMSes. All I can do is make mine the best it can be with my [admittedly, limited] coding ability, and do my best to make my scripts, like the wonderPortal script I'm working on, be as cross-CMS-compatible as possible.
Just don't expect me to always be cheery about it. Here's to stubborn independence.
**** I may have finally found a way around this. One issue down, eighty-four to go.
Comments