zmrd

daily occasional dose of nihilism🌗

Typed properties

PHP 7.4 is out and everyone seems to be happy about the typed properties.

I’m not. Don’t get me wrong, having an option to enforce property type and presence is a good thing, I won’t argue on that one. But every feature will eventually get misused and this is especially true when it comes to PHP developers. Every time there’s a discussion about PHP 7.4, I hear people saying things like: „We can finally get rid of that getter and setter boilerplate!“

Can we, though? When it comes to accessors in general, I’m the very last person defending it. I hate getters and setters, I truly do. It’s one of the reason I hate Java so much. I don’t like writing it and using it. But typed public property isn’t the answer.

Consider this:

class Product
{
    public float $weight;
}

So, how about this one? We don’t want $weight to be a non-positive number. How to deal with that? Yeah, you have to make it private and write an accessor for it. Sure, it could be an immutable property (so you need a getter for it anyway), or you could use a magic access, which, however, you can already do prior to PHP 7.4.

Think of an existing class exposing a public property. Later in the development process, you might want to restrict the value somehow. In that case, you have to introduce magic access support, unless you’re fine with breaking your API. Also, can you imagine using an API where half of the properties is exposed and the other one is hidden behind accessor methods?

I can’t think of a reasonable use case, with an exception of static public properties, which are, however, rarely used. Also, how often do you actually introduce a bug by assigning a value of an invalid type to your property?

Long story short, ditching accessor methods in favor of typed properties is most likely a bad idea.

There’s also another problem. PHP doesn’t profit from type-hints in any way; it’s just a runtime type check so it actually just makes your program slower. This doesn’t really stop me from using it, as I doubt it would make a measurable difference most of the time, but consider this:

class Generator
{
    private int $n;

    function run(): void
    {
        for (;;) {
            $this->n++;
            // ...
        }
    }
}

This is a no-no, once there’s a lot of iterations. Why? Because every time you assign a value to the $n, PHP will perform a type check. I believe there will be some optimizations made for such scenarios, but so far, this will slow execution down.

EDIT: In latest release, this exact code doesn’t seem to cause any performance degradation.

Did I mention this feature introduces an uninitialized state?

If a typed property does not have a default value, no implicit null default value is implied (even if the property is nullable). Instead, the property is considered to be uninitialized.

I sort of understand the reasoning behind it and I can definitely live with that, but I don’t like the behavior. Implicit null where possible and throwing an error when there’s an uninitialized property after the constructor call while maintaining the uninitialized property access check would make more sense, I guess.

Typed properties are a good thing in general, especially for static analysis and stuff like that. However, they’re not actually meant to reduce boilerplate. Accessor methods are still a thing you can’t avoid. In my opinion, the answer we’re looking for is something like properties in C#. That’s how you make a great API. I’ll stick with the Nette SmartObject, for now.

Wake on LAN over the Internet

I put my PC to sleep whenever I leave my home, unless there’s a running task or when I’m about to RDP into it. I wasn’t super-excited about the computer running for several days when I was out of home for several days, so I configured WOL. I have a static IP address, so with some port-forwarding magic, this wasn’t a problem.

There’s a nice Android app for waking the computer up. By default, it uses a TCP port 135 and ICMP echo to determine whether the PC is up by simply trying to open a connection to the port of your choice. There’s no point in pinging the IP address, as that’s the address of my router (and that, intentionally, doesn’t reply). Anyway, I just added another rule in port-forwarding table to an always listening service, which is supposed to be forwarded either way.

I would prefer checking the status by an UDP packet (containing the MAC address, for instance), so you could sort of „authenticate“ the status check, but again, there’s a secure service running anyway (but that doesn’t stop me from suggesting this enhancement to the author!).

Let’s get to the point. I installed the app, configured the router and enabled waking on LAN feature in the BIOS. Funny thing happened! Computer was waking up whenever the status check was performed. To be more specific, it woke up whenever I tried to open a TCP connection to any port. No WOL magic packet needed.

This could be a nice feature for local network exclusive use - you could just RDP to a computer, it would just automatically wake up and acknowledged the connection. However, it’s not exactly what I want in this scenario.

It turns out there’s an option in device manager dialog of the specific adapter you need to disable.