cybercog / laravel-love

Add Social Reactions to Laravel Eloquent Models. It lets people express how they feel about the content. Fully customizable Weighted Reaction System & Reaction Type System with Like, Dislike and any other custom emotion types. Do you react?
https://komarev.com/sources/laravel-love
MIT License
1.16k stars 72 forks source link

Implement Reacter & Reactant Facades #54

Closed antonkomarev closed 5 years ago

antonkomarev commented 5 years ago

Since package API is strict typed its might be harder to use and couple your application with the package subsystems. Developers will pass to the reactTo method reactable instance and string value of reaction type name: ->reactTo($comment, 'Like')

Facade design pattern to the rescue. Not the same as Laravel Facades (which act as "static proxies").

These facades will replace experimental global Cog\Laravel\Love\Facades\Love facade.

Facade concept

Facade shields developers from the complex details of the system and provides them with a simplified view of it which is easy to use. It also decouples the code that uses the system from the details of the subsystems, making it easier to modify the system later. It decreases maintenance cost, but adds additional layer of code & decreases runtime performance.

Reacter Facade

User via Reacterable trait will have additional method which will provide simpler access to Reacter model methods. This method returns Facades\Reacter class which hide internal complexity behind a single interface that appears simple from the outside. Method will have via (by way of) prefix.

trait Reacterable
{
    public function viaLoveReacter(): ReacterFacade
    {
        return new ReacterFacade($this->getLoveReacter());
    }
}

Usage

Instead default strict typed Reacter model calls:

$reactant = $comment->getLoveReactant();
$reactionType = ReactionType::fromName('Like');

$user->getLoveReacter()->reactTo($reactant, $reactionType);

Facades\Reacter class has simpler interface:

$user->viaLoveReacter()->reactTo($comment, 'Like');

Under the hood it will resolve Reactant model from $comment & ReactionType from the string name and call strict typed method.

Reactant Facade

Comment via Reactable trait will have additional method which will provide simpler access to Reactant model methods. This method returns Facades\Reactant class which hide internal complexity behind a single interface that appears simple from the outside. Method will have via (by way of) prefix.

trait Reactable
{
    public function viaLoveReactant(): ReactantFacade
    {
        return new ReactantFacade($this->getLoveReactant());
    }
}

Usage

Instead default strict typed Reactant model calls:

$reacter = $user->getLoveReacter();
$reactionType = ReactionType::fromName('Like');

$comment->getLoveReactant()->isReactedByWithType($reacter, $reactionType);

Facades\Reactant class has simpler interface:

$comment->viaLoveReactant()->isReactedBy($user, 'Like');

Under the hood it will resolve Reacter model from $user & ReactionType from the string name and call strict typed method.

Naming

Facades\Reacter & Facades\Reactant instantiation methods name candidate variants described in comments below.

antonkomarev commented 5 years ago

Name Variant №1 actAs prefix

$user->actAsLoveReacter()->reactTo($article, 'Like');

Pros

Cons

Decision

Don't use it.

antonkomarev commented 5 years ago

Name Variant №2

Convention

Method should have as prefix. Treat User model as Reacter.

$user->asLoveReacter()->reactTo($article, 'Like');

Pros

Cons

Decision

Don't want to use it because this prefix used in other languages in other cases. Usually in Java & C# as performs a cast; the same reference passed in is returned behind the "mask" of a different type. Expected that method return a potentially different view of the source. And we are returning completely different class: instead of Reacterable we will return Reacter model encapsulated in ReacterFacade.

Related reading

antonkomarev commented 5 years ago

Name Variant №3

Convention

Method should have aka prefix. User also known as Reacter.

$user->akaLoveReacter()->reactTo($article, 'Like');

Pros

Cons

Decision

Don't use it in favor of via prefix.

antonkomarev commented 5 years ago

Name Variant №4

Convention

Method should have as prefix and Facade suffix.

$user->asLoveReacterFacade()->reactTo($article, 'Like');

Pros

Cons

Decision

Don't use it. It's better than variant 2 because asLoveReacterFacade will return ReacterFacade of the Love package. But it wouldn't expose that in fact we are not dealing with user model anymore, but with Reacter.

antonkomarev commented 5 years ago

Name Variant №5

Convention

Method should have get prefix and Facade suffix.

$user->getLoveReacterFacade()->reactTo($article, 'Like');

Pros

Cons

Decision

Don't use it.

antonkomarev commented 5 years ago

Name Variant №6

Convention

Method should have via prefix. By way of Reacter.

$user->viaLoveReacter()->reactTo($article, 'Like');

Pros

Cons

Decision

Use it.

antonkomarev commented 5 years ago

Implemented in v7.0 release.