
PHP Annotations Are a Horrible Idea - theunraveler
http://theunraveler.com/blog/2012/php-annotations-are-a-horrible-idea/
======
jawngee
This is pure horse pucky.

First of all PHP isn't about elegance and I find it a teeth grinding
experience when people complain about it not being so. PHP is about getting
stuff done.

He doesn't offer one good valid technical reason why not to use comments for
meta-programming PHP other than "it just feels wrong" and an "icky feeling"
which is entirely subjective. "Reliance on Yet Another Library"? C'mon.

The fact that you can even parse out comments with the reflection API lends,
to me, that meta-programming is a-ok.

Also, his alternatives are kind of weak. Here's an annotation:

    
    
        /**
         * @Column(type="string", length=32, unique=true, nullable=false)
         */    
        protected $username;
    

And here's his proposed alternative:

    
    
        class User
        {
            public static $mapping = array(
                'username' => array(
                    'type' => 'string',
                    'length' => 32,
                    'unique' => true,
                    'nullable' => function() {
                        // Some logic to determine value.  
                    }
                )
            );  
        }
    

I'll take the first one because I have other shit I need to do.

~~~
bertzzie
I think this is quite a good technical reason:

    
    
        Because code comments should never be necessary for a script to function properly. 
    

In which other language do you see comment is necessary to make the code
function properly?

~~~
chaosfox
Its a syntax problem then ? what if the annotation wasn't inside comments
would that make it ok ?

~~~
astrodust
A lot of this boils down to PHP's feeble "array" declarator. Take a page from
JavaScript and make it easy.

~~~
mark_story
As of PHP 5.4 you can use [] to define arrays. It saves some typing, and is
less noisy on the eyes I guess.

~~~
astrodust
That's exactly the way it should be. Hopefully this will become the standard
before long.

------
LeafStorm
Annotations are not required to use either of those libraries. Doctrine allows
mapping information to be defined in XML or YAML files. For Symfony, the
@Template annotation is not part of the core at all: it is part of the
SensioFrameworkExtraBundle, which can be turned off easily. The normal way to
render a template is:

    
    
        return $this->render("MyBundle:Controller:template.html.php", array(...));
    

That said, it would be easy enough to add the static variable-based mapping
information to Doctrine as a metadata driver, and create a version of
SensioFrameworkExtraBundle that does the same for its annotations.

------
risratorn
> the PHP community is now officially so desperate for better metaprogramming
> capabilities that it is attempting to do so using code comments

This says it all ... and to be honest, from an ease point of view I like using
annotations but as with most parts of PHP it's the implementation that sucks
(or the lack of implementation)

Over 2 years ago a RFC has been filed for native php annotations and I must
say that I like the idea of annotations being part of the actual language and
not relying on Inflection on comments (wtf?) to attach metadata to classes,
propeties or methods. Just too bad nobody can get their act together and get
it implemented in the core. <https://wiki.php.net/rfc/annotations>

~~~
blowski
That somebody could be you!

~~~
risratorn
Problem is not finding someone to implement it, problem is getting the core
devs on one line concerning the syntax/implementations. There have been
numerous suggestions but none were deemed good enough, and maybe for good
enough reasons I might add.

[http://marc.info/?l=php-
internals&m=130496081925265&...](http://marc.info/?l=php-
internals&m=130496081925265&w=2)

------
f1gm3nt
"Without the special @Template comment, Symfony does not know where to find
the template file."

First off, this is completely false. With symfony2 the action needs to return
a Response object. This annotation isn't required and the team I work with, we
rarely use this.

It's very useful for when you are just adding a page that contains no real
business logic.

"Doctrine 2 does the same thing when declaring object properties based on
database table columns1:"

Oh look, there's a footnote.

"Fortunately, Doctrine also allows you to declare property metadata using PHP,
YAML, or XML"

What?

"Because code comments should never be necessary for a script to function
properly"

So your points are that we need @Template annotation to be able to render a
template, which is FALSE, and you state the same with with Doctrine2 which you
point out there are other ways to do it.

All your points for "DX Regressions" are completely wrong.

Unless I am using a special plugin with my IDE it's not going to link
"AcmeBlogBundle:Post" to src/Acme/BlogBundle/Entity/Post.php. Most of what you
point out is complete bullshit. What do I gain to hope by using var_dump() on
an annotation? I know that in a Doctrine Entity that the column type is a
string.

Articles and posts like this drive me banana's with the complete lack of
understanding what you're writing about.

~~~
theunraveler
> First off, this is completely false. With symfony2 the action needs to
> return a Response object. This annotation isn't required and the team I work
> with, we rarely use this.

Correct. But if you want use the form where you just return an array of
variables to use inside your template, and have Symfony smartly located the
template for you, you have to use an annotation. See
[http://stackoverflow.com/questions/12922827/symfony-2-php-
te...](http://stackoverflow.com/questions/12922827/symfony-2-php-templates-
autoloading) for an example.

> and you state the same with with Doctrine2 which you point out there are
> other ways to do it.

Yes, there are other BETTER ways to do it. Making comment-based annotations
available as one of the ways pretty much guarantees that people will use it,
and that seems like a bad idea to me. Just remove them so no one is able to
choose the bad practice.

> All your points for "DX Regressions" are completely wrong.

Uhh, OK? How about comment folding in text editors? Would you, as a developer,
be happy if you encountered some code that made heavy use of annotations for
critical application logic? I wouldn't--this is what I mean by DX.

> What do I gain to hope by using var_dump() on an annotation?

The same thing you gain by var_dump()ing any variable--an understand of what's
happening under the hood.

~~~
f1gm3nt
> Correct. But if you want use the form where you just return an array of
> variables to use inside your template, and have Symfony smartly located the
> template for you, you have to use an annotation. See
> [http://stackoverflow.com/questions/12922827/symfony-2-php-
> te...](http://stackoverflow.com/questions/12922827/symfony-2-php-te..). for
> an example.

Your point is that this is required, it's not. Using annotations is optional.
The user you point to in the example wanted to use the annotations and wanted
to use php templates.

The FACT is that in Symfony2, your Action MUST return a Response object. Using
annotations is an easy way to get around this.

> Yes, there are other BETTER ways to do it. Making comment-based annotations
> available as one of the ways pretty much guarantees that people will use it,
> and that seems like a bad idea to me. Just remove them so no one is able to
> choose the bad practice.

Why is this a bad practice? Everything I need to now is right there in the
annotation. I know that it's a string, integer, or anything else. I don't need
to open up another file to check.

> Uhh, OK? How about comment folding in text editors? Would you, as a
> developer, be happy if you encountered some code that made heavy use of
> annotations for critical application logic? I wouldn't--this is what I mean
> by DX.

... You can't unfold them? You mean to tell me that having an editor that
folds comments is bad design for the software that uses annotations? I'm
trying to figure out this critical application logic you speak of. If I'm
using annotations to describe a column that is a "string" type and has a
length of "32" then what is the difference of it's in a yml or xml file? I
enjoy being able to tell that as well as what relationships there are.

> The same thing you gain by var_dump()ing any variable--an understand of
> what's happening under the hood.

Again, why are you trying to var_dump something that has no value in using a
var_dump on? An example of using var_dump and it being useful is
"var_dump($user->getSomeRandomCrap())". It tells me what is returned by that
method. Is an object or something else returned. WHY DO NEED to var_dump
"@Column(type="string", length=32)"? I know the property should be a string
and should be a max of 32 characters long?

------
yuri41
Closures inside property initializations inside the class body don't work. Not
even in an array.

So this code throws up a "Parse error: syntax error, unexpected 'function'
(T_FUNCTION)"

    
    
        class User
        {
            public static $mapping = array(
                'username' => array(
                    'type' => 'string',
                    'length' => 32,
                    'unique' => true,
                    'nullable' => function() {
                        // Some logic to determine value.  
                    }
                )
            );  
        }

~~~
stevencorona
Came here to post the same thing. I don't know if it has been fixed in 5.4,
though.

~~~
robryan
Nope, the parser seems to be pretty brittle around this. Someone who knows
more about the internals can probably explain why this works:

    
    
      class User
      {
          public $mapping = array(
              'username' => array(
                  'type' => 'string',
                  'length' => 32,
                  'unique' => true,
              )
          );  
    
          public function __construct()
          {
          	$this->mapping['nullable'] = function() { echo "test"; };
          	$this->mapping['nullable']();
          }
      }
    
      $user = new User();
    

And this doesn't:

    
    
      class User
      {
          public static $mapping = array(
              'username' => array(
                  'type' => 'string',
                  'length' => 32,
                  'unique' => true,
              )
          );  
    
          public static function set()
      	{
      		self::$mapping['nullable'] = function() { echo "test"; };
      		self::$mapping['nullable']();
      	}
      }
    
      User::set();

~~~
TazeTSchnitzel
I used to be interested in helping fix PHP, but I gave up.

The reason is because Rasmus and a few others seem to think that using the
syntax definition to do your type checking for you is a good idea, and that
the hundreds of possible cases they didn't think of, don't matter.

------
porker
Couldn't agree more. Every time I use annotations I feel dirty...

Programmers who talk so much about code separation, clean modular structure
etc are the same ones are willing to use annotations. What got into them?

Disclaimer: I like code to be elegant. And practical. This is PHP we're
talking about, but no need to do more bad choices...

------
michaelmior
This could be solved if annotations were supported syntax. This works well in
other languages (e.g. decorators in Python and annotations in Java)

~~~
masklinn
And before annotations were added in java, the exact same hack was used for
annotations. The alternative was to have separate configuration and mapping
files which was _painful_. And then, you had libraries which did not have in-
comment annotations and intermediate ones which compiled in-comment
annotations to the original libraries's mapping files. Oh the fun we had.

------
orangethirty
Agreed. A comment is an explanation about some part of the program. Not the
program itself. Its meant to be ignored by the computer. Putting logic in the
comments is just downright stupid. Its one of those overly "clever" things
"smart" people do to make their code be _cutting edge_. Nope. As good as
Symfony is, my main issue comes down to design decisions as this one. Its just
dumb. Having logic in comments its like putting beer in baby formula, just in
case I run out of beer. Shit doesnt make sense.

------
Joeri
I've just ported java's bean vaidation to PHP using annotations in comments,
and I strongly disagree.

Point by point:

1\. dx regressions

I've designed the annotation system so that if developers misdeclare them an
exception is thrown. Unit tests will fail, and the software will not run.
Someone checking in code that fails to such a degree deserves what's coming to
them. That covers php -l. Var_dump and debug_backtrace are irrelevant to my
use case, and I use proper breakpoints and watches anyway (phpstorm + zend
debugger). I don't even understand the point he's trying to make about IDE
linking. Which leaves the argument about comment folding, which I think has
some merit, if you think comments shouldn't be read, which I don't.

2\. Readability

Nonsense. Learning an API always requires getting used to its idiosyncracies.
His proposal to use static variables looks less readable to me.

3\. Reliance on another library

Yes, that's kind of the point.

4\. Icky feeling

Aha, bingo. The author came in with the opposite bias of myself and drew an
according conclusion.

To conclude: the use of annotations in comments is not better or worse than
alternatives, it's all in the eye of the beholder.

------
willvarfar
Somewhat related, I recently made a simple type annotation library and checker
for Python 3...

<https://github.com/williame/obiwan>

Static type checking for Python yeah!

------
gview
First of all, annotations are nothing new. They have been around in Java for
years, and it was emulated because it had advantages that really don't need to
be regurgitated by me. If they weren't a good idea, they wouldn't have lead to
a formal adoption inside the language.

Secondly, in both Symfony2 and Doctrine2, annotations are an OPTION. You use
them if you want to use them, and if you don't want to, you can use
traditional configuration files. It doesn't seem that the author has done
anything with either Symfony2 or Doctrine2, or he would have understood that.
As someone who used Symfony1, ZF1, Propel and Doctrine, I would not go back to
the old way of doing things, even if I was offered good money to do so (as
happened just last week in fact).

Most people who actively use these components LOVE annotations, because they
allow you to keep the configuration close to the code, and reduce verbosity.

They drive code generation, and reduce the amount of code that has to be
written to get a specific job done. So if there's a problem debugging, is it
really about annotations, or about code generation, and if we can't have code
generation (facepalm) then I suppose we shouldn't have template systems like
smarty or twig, simply because "debugging is harder" and editors have more
work to do.

If it's not the author's cup of tea, nobody is forcing anyone to use these
capabilities. Needless to say, I couldn't disagree with the premise of this
article more. @jawngee already provided a simple salient example.

------
blowski
What's in the annotation is configuration, not application logic. As such
there's no real difference between putting configuration into YML, XML and
annotation comments.

In response to your 4 specific criticisms: 1\. (DX regressions) - in theory
yes, in practice the frameworks are good at this. The annotations compile down
to PHP which you can look at directly, and you get exceptions if there is
something wrong with the annotation. 2\. (Decreased readability) - subjective
POV. I find it easier, because the relevant configuration is next to the code
to which it applies. It also prevents crufty out-of-date comments floating
around. 3\. (Yet another library) - Yep. No answer there. 4\. (Icky feeling) -
I get far more icky feelings out of seeing 30 lines of custom written 'setup
code'. Annotations help to prevent that.

~~~
podperson
It violates the "I don't need to look inside comments for sources of bugs"
rule I'm quite fond of.

I've defended PHP for some time now, but this is getting ridiculous.

Isn't PHP embedded inside markup? Wouldn't it be simpler to do something like:

?> < ... XML GOES HERE ... > <?php

and not violate any expectations?

~~~
ludovicurbain
no that's bad really.

The best way to write PHP for the web is like any language: php echos or
prints shit, that's it.

The way you're showing is that of the total noob trying to implement some php
inside their evil dreamweaver website.

Besides, if you're handling markup (in the web context) on the server side,
you've already failed, as most markup should only be generated client-side,
diminishing server-load and bandwidth consumed while greatly improving
cacheability.

~~~
podperson
I strongly disagree. Echoing well-formated HTML is much harder than simply
tagging around it, and what's the benefit of echoing it? You like escaping
characters?

~~~
ludovicurbain
You didn't read the whole post.

1) your js should be echoing the HTML and getting data through JSON ajax

2) echo and print both work in command line, are explicit and work exactly as
any language, whereas peppering your shit with php tags looks like shit and a
maintenance nightmare.

If you have trouble escaping characters, you should consider the single quote,
it's known to rock the boat.

Additionally, "'.$var.'" is the best, fastest, cleanest no surprise approach
to inserting variables in markup, leaving double quotes just fine and dandy
inside your markup.

And then, I'm pretty sure I'd rather have a string with 100% warranty of no
execution or interpretation (that's single quote versus double quote for me)
than any kind of dirty markup polluting my source code.

On the same subject, there is no valid reason for having naked markup inside
your PHP, or between PHP tags because you're just begging for problems.

And I would expect multiple PHP tags to cause some minimal parsing overhead
too.

Either way this matters not because the only sane way to use PHP in a web
application is echo json_encode($return); or header(file) + readfile

And even then the second example is only there because javascript can't be
arsed to support file creation/download (i.e. server -> blob.gz -> js -> would
you like to dload this shit ?)

------
sandfox
Seriously, what sort of argument is this... (Allow me to paraphrase) "PHP
doesn't have annotations, so instead it has hacked up comments that stand in
for annotations. I find these ugly because it's abusing comments/etc therefore
the idea of having a non-ugly real implementation that removes most of my
objections is a bad idea"

\--EDIT I may have slightly not realised it was just comment annotations that
were the problem here rather than annotations as a whole.... HOLD FIRE.

~~~
theunraveler
I added an update to the article. I wasn't aware of the RFC to make
annotations a language feature when I wrote the article. The article is
specifically referring to annotations implemented as code comments.

Sorry for the confusion, and thanks for your comment.

------
methodin
I fail to see how an array makes debugging say a routing directive easier. The
issue is generally incorrect names or values which will not be aided by a
backtrace or a var_dump - you know the value in either scenario. You will
still have to dive into the parser and understand what it's looking for to
resolve your problem or delve into XDebug.

In the situations when knowing the value of something does not help, I do not
see why annotations wouldn't be superior.

~~~
theunraveler
At least you would know if your array contains a syntax error. With an
annotation, you would have no way of knowing that aside from what the
annotation parser spits out.

------
pmelendez
I found this very ironic.

I see PHP Annotations as a hack for comments. That said, I found very ironic
someone giving a rant of a hack in hacker news. Just saying.. :)

~~~
xentronium
There are hacks and then there are crutches.

------
glazskunrukitis
I completely agree with you, but I would use something like this -
<http://pastebin.com/embed_iframe.php?i=U4Fmm0t6>

I don't think that just an array quite make it as a real alternative but a
definition builder called from a method seems more appropriate. Also I would
seperate model definition from model repository.

------
datasage
Having used both doctrine and used a format of array mappings, I prefer the
doctrine way of using annotations.

However I do also acknowledge that putting important information into comments
can be somewhat dangerous. Doctrine does support storing metadata in yaml and
xml files too, but in that case you need to ensure that changes to your model
class get reflected in the mapping file.

------
daGrevis
Annotations (or decorators) are good idea as it is — they are very popular in
Python. The bad part is that they are implemented horribly — as comment which
are later parsed.

This should be implemented in PHP core or at least someone should write
extension for it. That would solve implementation problems and add new, good
feature to PHP language.

------
shocks
You don't _need_ to use annotations with Symfony2. You can use yaml or xml
configs if you want.

I have a big project written with Symfony2 - not a single annotation to be
found.

------
troels
DX - As in Developer Experience? That's a first for me.

------
EugeneOZ
Comments should be comments only, but your code in "alternative" is very
dirty. Static(!) public(!) property is violation of encapsulation.

~~~
theunraveler
I don't understand how. It's a static property because it applies to all
object of the class, not an individual object (i.e. an individual object
shouldn't be able to change it).

And how is making the property public a bad idea? The configuration system
that parses it will need to read the property, no? And a method like
getUsername() should be reserved for actually getting the value of that field,
not its config.

~~~
EugeneOZ
"It's a static property because it applies to all object of the class, not an
individual object"

Why? if you will have 3 databases, each will have same password?

"And how is making the property public a bad idea?"

Because it's breaks encapsulation.

Also, there is two kind of "class" usages in PHP: as Object and as Structure.
If your class is just Structure (contain no methods at all), then, of course,
public properties is what we need. But when your class is an Object, which
should have instances, API, then keep all properties encapsulated.

------
PaulHoule
For me a lot of the fun in PHP in the last few years has been balls-to-the-
walls metaprogramming.

------
sproketboy
PHP Is a Horrible Idea - FTFY

------
ludovicurbain
That article misses the point:

PHP OO is a HORRIBLE IDEA. if you're doing OO PHP, shoot your other foot right
now and go learn PHP before using it java-style.

Why is it that every time somebody on HN explains that a technology is not
suitable for a use case, it gets downvoted by fans of said technology ?

~~~
theunraveler
Why is PHP OO a horrible idea?

~~~
ludovicurbain
PHP OO is broken in many ways (of which you can find a list in the blog post
"php a fractal of bad design"

PHP is naturally (due to it's C libs) non-OO and will thus only implement OO
"that" far.

Lastly, OO is not a silver bullet and is best used _only_ in front-end, and
languages that were designed with it in mind.

~~~
shakesbeard
Well, OOP in PHP seems to work rather well for thousands of large projects out
in the wild - making your argument invalid.

~~~
ludovicurbain
Well, smoking cigarettes seems to work rather well for millions of successful
people out in the wild - making your argument invalid.

It IS possible to make "business good" software in brainfuck, that's just not
a reason to call it "not broken".

See, this is about science, logic, and whether or not a feature is properly
supported by a language, not about whether or not somebody managed to build
and sell a solution while using that feature.

------
dschiptsov

      while (true)
         read("http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/");

