Mittwoch, 19. Februar 2014

HAML, HTML, Ruby, and Marketing

I just took a look at HAML, having been linked there from Mark Hansen's blog posting @ http://www.markhansen.co.nz/autocompiling-haml/.

After about 2 minutes, I had two questions on my mind:

1.
Why, oh why, do ruby projects tend towards this massive, obtrusive self-marketing? "templating haiku", "Simplify. Enjoy. Laugh. 20 minutes later, you will never go back." To me, this just seems silly. Most of your users are technically-minded coders who will evaluate your project based on exactly one question: Will it make their lives easier?

When I look at, for example, www.vim.org, www.php.net, or, heck, even www.microsoft.com, I don't see that. Ain't nobody as can claim those are unpopular, failed sidenotes of IT history.

2.
Which leads me to my second question: In what way exactly is HAML more beautiful, elegant, or expressive than HTML? I mean, yeah, it has nifty "=" and "%" signs all over the place, and it doesn't duplicate code in closing tags, so that's an advantage I guess. On all the other hands, it seems to use semantic whitespace, which I loathe. I want my code surrondedwith fancy "{"s! I get to decide how to indent, and what, and why!!!!!111one!!

Maybe it integrates nicely into ruby/rails. I wouldn't know, I'm just a lowly PHP hacker. (It feeds me and my cats, so don't ask.) Maybe it's just a matter of taste. Maybe I'm gettin' too old for this sh*t. Or I'm not good enough.

Seriously, I just don't know.

Samstag, 5. Oktober 2013

Optional Parameters in PHP, and NULL

Consider the following PHP5 code:

<?php
class A{
      function foo() {}
}
function f(A $a = NULL) { var_dump($a); }
function g(A $a) { var_dump($a); }
f(new A());
f(NULL);
g(new A());
g(NULL);


Now, consider its output:

class A#1 (0) {
}
NULL
class A#1 (0) {
}

Catchable fatal error: Argument 1 passed to g() must be an instance of A, null given, called in a.php on line 13 and defined in a.php on line 8

Okay. So, a parameter, with or without a type hint, whether required or optional, receives an A if given an A. No surprise there.

An optional, type-hinted parameter, when given a NULL, results in a NULL. I guess that's fine, too.

However, a required parameter can not ever be set to NULL.

You're right: Setting something to NULL in the parameter list means something totally different than setting something to NULL anywhere else in your code.

I guess what they were trying to do was force the = NULL, passing NULL "idiom" to represent the fact that the parameter is optional, and is not set. I guess the reason is that you can not default a type-hinted parameter to anything besides NULL. The function body can not distinguish between a NULL stemming from the default in the parameter list, and an actual NULL, and NULL is the only indication that the optional parameter was left out, so passing a NULL is disallowed in the case of a required parameter.

Or something like that. (If you omit the type hint, passing the NULL works perfectly fine, by the way, thus making it even more confusing...)

Regardless of how long, or how hard I think about it, it keeps making no sense at all. It is neither consistent, nor is it useful. It is, at best, an attempt of the language to be clever - an attempt, I should say, that went terribly terribly wrong. At worst, it is a result of some obscurity in the parser that nobody ever really thought through.

In any case, it makes me even more sad to be forced every working day to work with tools as broken as that.

Dienstag, 24. September 2013

Magento and Getters

From the Magento core code (in class Magento_Core_Model_App):

    /**
     * Retrieve request object
     *
     * @return Mage_Core_Controller_Request_Http
     */
    public function getRequest()
    {
        if (empty($this->_request)) {
            $this->_request = new Mage_Core_Controller_Request_Http();
        }
        return $this->_request;
    }


Folks... puleaze!!!?

I just wasted about an hour on finding out where $this->_request was initialized. I debugged over $this->getRequest() about a gazillion times. This is just not the way to write code, for crying out loud! The phpdoc block actually states this, right up there: Retrieve request object. Retrieve!!!!!!!!1112. It doesn't say anything about initializing it.

I mean, yeah, by now I should probably be able to anticipate stuff like that, seeing as some of the magento standard models' load() methods have an optional parameter $create that defaults to... you guessed it! True!!

Some. Not all. That would be too consistent (even if it's decidedly wrong).

Duh.

Dienstag, 10. September 2013

realX

I know that this is not a very unique idea, but it's such a common mistake one cannot be reminded of it often enough.

Only recently, I stumbled upon a code fragment that performed something akin to sudo on a webshop. It took a customer_id from the request, checked the logged-in customer's permissions, and then it went about and set a

realCustomer

to the customer from the session... or it set the customer from the request to the realCustomer, while the session customer remained untouched.... or...

See what I'm aiming at?

If you're ever tempted to use something like "real" to distinguish between two objects, please take the time and think about what that object actually represents. The adminCustomer, maybe, the loggedInCustomer, or the effectiveCustomer. But never the realCustomer.

thesaurus.com is a valuable, and deeply underappreciated, resource for coders.

Mittwoch, 5. Juni 2013

Fields a table should always have

These are fields I think should be available in (almost) every database table, everywhere:


  • id
    • A unique identifier. There might be a few exceptions, but almost every time I designed a table without a primary key, I came to regret it afterwards.
  • created_by
    • Almost always, you want to be able to find out who did what, when, where.
  • created_at
    • Almost always, you want to be able to find out who did what, when, where.
  • updated_at
    • Almost always, you want to be able to find out who did what, when, where. Obviously you don't need this field on insert-only tables.
  • is_active
    • Most of the time, you do not actually want to delete data. You want to deativate it, mark it deleted. On rare, VERY rare occasions, it makes sense to move it to another table or database. But that's really the exception. By default, just mark it as unactive or deleted or whatever. Quite often, you might want a status instead of a flag. (But only VERY rarely, methinks, do you want both. It's a smell to have a lot of flags, and it's another smell to have a status field plus flags.)
  • source
    • AT LEAST on tables that you (might at some point) import from another database, you want to mark the source. I can't count the times I've had to create enormous code monsters just to heuristically find out what data came from the last import, just to then delete it and re-start the process. DELETE FROM funny_table WHERE source='my_funny_import' would have made my life so much easier! (There, I said it: Delete. Yep, that's definitely one exception where it actually makes sense.)

Samstag, 6. April 2013

iTunes

Folks... hello??? What the heck is wrong with you guys?

Controls that don't provide visual feedback on activation; a "new" watermark that never seems to vanish; when you're in the midst of the download and then have to switch off the 'puter, after switching it on again, the download doesn't restart. You have to find the mechanism to restart it inside of some obscure non-standard menu. And when you download 2 or more things, you don't get any information about that.

And here I was, thinking that apple was overpriced and arrogant, but at least they knew how to hire usability experts for my money.

Have you eaten fruit that didn't smell good, or something?

Dienstag, 2. April 2013

A Change Of Style

It used to be that I insisted on my conditionals alwaysinghave the positive part in the front, like so:

if (isOkToDoStuff)
    doStuff();
else
    throw new Exception('unable to do stuff');

My logic was that the use of !s should be minimized, that the positive part naturally should come first, and that you should have the actual code for your function on top.

However, in recent times, I find myself liking another idiom better: handling exceptional and error cases first, and then doing what the function is supposed to do, like this:

if (!isOkToDoStuff)
    throw new Exception('unable to do stuff');
if (!otherPrerequisiteINeed)
    throw new Exception('unable to do stuff');

doStuff();


The advantage being no (ugly!) indentations or (unreadable!) &&-ed expressions for additional error conditions. Which will always creep up after the first deployment, or at least after the initial coding session. 

Plus, no occasion to forget adding curly braces to the if clause. ;-)

The other, more important advantage, is that the idiom doesn't change over time. You always have the error conditions first, the code to ultimately run at the end, and the actual code is not buried under 16-indentation-weights forged out of nested ifs.

Somehow, it isn't as elegant. But more practical. Which, mostly, is to be preferred, whether we like it or not.