First of all, Larry, thanks for taking the time to reply. Thanks also to
Matthew for replying yesterday; I felt my response to Larry was sufficient
to cover both emails which is why I haven't quoted you directly.

> It sounds like this is another case of naming things (one of the 2 hard
problems in CS).  There's a proposal on the table to change it to "Catalog":
>
> https://groups.google.com/d/msg/php-fig/D-qAsZ5_f0s/PrKQL7RzAgAJ
>
> Thoughts there?  (As in, over in that thread.)

(On a side note, that link takes me to this current thread, which does
contain messages about renaming the LinkCollectionInterface to
LinkCatalogInterface and is the same one I've been replying to all along.
I'm not sure if Gmail is screwing around or if one of us is missing
something.)

My contention isn't with the name of the interface, I'm simply arguing that
providing an interface for *any object which has links* isn't very helpful
(although a proper LinkCollection object might be).

I think it might be helpful to take a step back and project our solution to
a problem from a different domain. I think that you, Matthew and I all
agree that a Link is a simple value object. A classic example of another
type of value object is a quantity of money. Let's imagine we are creating
a Money PSR instead of a Link PSR. Consider the following interface, which
I believe would be fairly analogous to what you are proposing with the
LinkCollectionInterface (semantically ThisObjectHasLinksOnItInterface):

interface HasMoney
{
    public function getMoney(): Money;
}

What use would this interface be? When would we realistically create a
polymorphic function to consume such an object? Rather, the way an object
would expose any money objects it referenced would depend on what those
objects represented in the specific domain of the object itself. For
example:

interface SaleableProduct
{
    public function getSalePrice(): Money;

    public function getCostPrice(): Money;
}

Similarly, I think that the way links will be exposed by objects will
depend on the domain and context of the object. For example:

interface Author
{
    public function getName(): string;

    public function getPublicLinks(): LinkCollection;

    public function getLinksForUser(string $userId): LinkCollection;
}

I appreciate the example of (HTTP) Resources having links. Defining an
interface to allow polymorphic functions which consume HTTP resource
objects specifically would make sense, but that isn't what is being
proposed here. Regarding your earlier example; there do not appear to be
any polymorphic functions and, therefore, nothing which justifies a
ThisObjectHasLinksOnItInterface. If you are only dealing with a specific
concretion then you have no need to know which abstract interfaces the
object implements. I suspect it would be helpful to identify a real-world
example of a polymorphic function which would make use of this interface
but not require some other domain-specific interface (such as an
HttpResourceInterface).

I feel like I've asked all the questions I can. You guys are the
stakeholders here and are also more likely than I am to make use of this
PSR, so I think I'll leave you to it. I hope my questions have been helpful
even if you do decide that the current approach is the right one!

Cheers

On Wed, Sep 14, 2016 at 4:21 PM Larry Garfield <[email protected]>
wrote:

> On 09/13/2016 09:28 AM, Josh Di Fabio wrote:
>
> On Tue, Sep 13, 2016 at 2:50 PM Larry Garfield <[email protected]>
> wrote:
>
>> The standard example we've been using is a domain object of some sort
>> that then is getting rendered to an HTTP Response.  To wit:
>>
>
>>
>
> Thanks for taking the time to reply.
>
>
>> $article = load_article(...);
>> // Article is a class in a domain model, but can generate links to other
>> articles such as next/prev, up to the index of articles, etc.
>> // ...
>> // LinkableResponse is an implementation of PSR-7 ResponseInterface and
>> LinkCollectionInterface
>> $r = new LinkableResponse(200);
>>
>> // Whatever app-sensitive rendering logic applies, not our problem.
>> $r = $r->withBody(new StringStream(render($article));
>>
>> // The links on article are generated on the fly here,
>> // based off of the underlying data of article, whatever that is.
>> foreach ($article->getLinks() as $link) {
>>   $r = $r->withLink($link);
>> }
>>
>> Forcing both Article and Response to be traversable on links is a no-go,
>> as they may have other data sets in them that would make just as much sense
>> to iterate.  But it makes total sense for Article to be able to provide
>> links (read only) and Response to both accept them and be able to return
>> them (or turn them into HTTP headers directly, or whatever else someone
>> feels like doing).  Neither Response nor Article are PSR-13-specific
>> concretions.
>>
>
> I don't think I've made myself clear. My contention is that
> LinkableResponse is not *a collection of links*, rather, it *has* a
> collection of links. It should not implement LinkCollectionInterface at
> all. Does this make sense? I fully appreciate that you and Matthew are
> smart guys who understand that interfaces are analogous to *is a* and not
> *has a* semantics, but I feel that this spec is currently overcomplicating
> things a bit.
>
>
> It sounds like this is another case of naming things (one of the 2 hard
> problems in CS).  There's a proposal on the table to change it to "Catalog":
>
> https://groups.google.com/d/msg/php-fig/D-qAsZ5_f0s/PrKQL7RzAgAJ
>
> Thoughts there?  (As in, over in that thread.)
>
> The problem with excluding the the ThisObjectHasLinksOnItInterface
> (whatever it's named) is that it's then impossible to reliably do the
> transfer I mentioned earlier.  In a multi-stage DDD system (Drupal, or some
> ADR-esque systems) there could be multiple levels of object transformation
> in which you want to carry the links along.  Eg, in the example above,
> you'd wrap the foreach ($article->links ...) in an interface check; that
> way you can pass any object to a function containing that code and it will
> transfer links if possible.  That's only doable if you have a
> ThisObjectHasLinksOnItInterface, which is why we included it.
>
> getLinks() returns an iterable (array|Traversable, technically), so you
> could filter that however you want; you could even build it with a
> generator if you were so inclined.
>
> --Larry Garfield
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "PHP Framework Interoperability Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/0e9c9b93-880b-a705-69d4-bd7746eddf94%40garfieldtech.com
> <https://groups.google.com/d/msgid/php-fig/0e9c9b93-880b-a705-69d4-bd7746eddf94%40garfieldtech.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups "PHP 
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/CAKiSzdCKJwdTOiJ%2BOtp8o8AcECXB59wQnK25GxaJYcSUxpEu1A%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to