Extremely Defensive PHP

I liked the slides a lot. I felt those words come from true experience and pain.

But some of the advice is too extreme.

Code can't be reusable:

If you go about it naively and just "wish" code is reusable you'll see a lot of failure. It takes practice to learn how to create reusable code (and it's mostly about APIs, not the code that implements them, so code can be "crap", but reusable).

I believe the point of the code reuse slides was not to anticipate far in the future what you might need and create reusable code for an undetermined future. But over time, as you start repeating yourself over and over... you'll figure out how to create reusable code.

No optional dependencies:

I suppose the talk would clarify this slide, but optional "things" in general are a fact of life. It's ok if component users ignore them at first. That's the point: they're optional. If a log is optional and you need to log, you'll find the option.

The idea of passing null objects (that's what "FakeLogger" is in the example) can work, but you still need to differentiate null objects from real objects, otherwise it's the literal equivalent of doing a lot of extra work and "saving" it in /dev/null.

And if you'll differentiate and switch on null objects, might as well use null. That's the purpose of it.

Assertions:

In general you don't need to embed outgoing assertions in your code, because this is what unit tests do - test outbound conditions.

As for assertions on incoming data, that's best put inline but there should be a switch to turn them off in production (you can do this either by using the actual PHP assert() or your own DEBUG flag).

Remember: assertions are distinct from input validation. Assertions only exist to enforce a contract with the developer while he programs. So if you feel you need an assertion to run on stable code deployed to production, then probably it's not an assertion.

Assertions are also never recoverable, they should terminate the program immediately.

BTW instead of using a closure for Wagons, you could foreach and use instanceof... But yeah, whatever you want, I guess.

Value objects:

I like value objects and use them for some kinds of data (most obvious: datetime).

However in practice it doesn't really save you "validations".

If you don't use a value object for email, you'd validate at the point of calling your model or service. That's one.

And if you use a value object for email, then you'd validate at the point of creating the value object. That's also one.

The cases where you validate multiple times are rare, and offset by the fact you don't have to pack and unpack strings from value objects (which also takes resources, if we're that performance conscious).

Fluent interfaces:

I checked the blog post, but I'm not sure the critique makes sense. I mean, he praised PSR-7 just a few slides earlier, too.

Not everything should be fluent, and it ca be abused, but in my team we use fluent interfaces in several key places of our apps with great success.


Everything else is nice though. I like the idea of disabling cloning and serialization when the object can't handle it. We deal with this differently (in my team we assume nothing is cloneable and serializable, unless explicitly said so), but this is more explicit.

/r/PHP Thread Link - ocramius.github.io