On 4/19/2016 9:39 PM, Stanislav Malyshev wrote:
> Hi!
> 
>> Except these two are in separate libraries that cannot share an interface.
> 
> If these are separate libraries, you can't be sure that method does the
> same thing, or even that it will be existing in both.
> 
>> An interface is not possible: separate libraries. Duck-typing is not
>> appropriate: only these two specific classes are supported.
> 
> This looks very strange and brittle design - two random classes from two
> unrelated libraries, which you rely on have exactly the same
> functionality and keep it that way. Not a robust design if you ask me.
> Also, it looks strange why only those two random classes can be
> converted to arrays but none others can. What if you had third class
> that also can be converted to array? What if you had 20 of them? Again,
> looks like brittle and ad-hoc design.
> 

Stanislav is completely right here, this is exactly one of the usages of
union types that is completely wrong. You had this example:

namespace Application;
function log(Eloquent\Collection | Haldayne\Map $entity) {
    $logger->log($entity->toArray());
}

try {
    log(Config::find());
} catch (Eloquent\Exception\UnexpectedValue | \UnexpectedValueException
$ex) {
    die('Configuration is neither array nor object');
}

The problem with this is that you now require both libraries to be
installed at the same time because otherwise the union type cannot be
verified by PHP's type system. This will bite you in the ass in no time.
Just think of your composer:

"require": {
    "eloquent/collection": "*",
    "haldayne/map": "*"
}

Both do the same?!? Better rely on duck typing in such cases.

function log($entity) {
    if (method_exists($entity, 'toArray')) {
        $logger->log($entity->toArray());
    }
    else {
        // handle is in another way.
    }
}

If you really want to ensure that the method is not being called by a
dev in that way go for assertions.

function log($entity) {
    assert('method_exists($entity, "toArray")', 'entity must implement
`toArray` method');

    // Check in production too to avoid fatal errors?
    if (method_exists($entity, 'toArray')) {
        $logger->log($entity->toArray());
    }
}

Union types only have a few special use cases but those are worth
exploring imho.

function div(int|float $x, int|float $y): int|float {
    if (is_float($x) || is_float($y)) {
        return $x / $y;
    }
    else {
        return intdiv($x, $y);
    }
}

function even(int|string $x): bool {
    if (is_int($x)) {
        return $x % 2 === 0;
    }
    else {
        return gmp_mod($x, 2) == 0;
    }
}

-- 
Richard "Fleshgrinder" Fussenegger

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to