0 like 0 dislike

Blogmotor tervezésével kapcsolatban jött elő, de mindenféle kollekciónál felmerülhet.

Adott a PostCollection osztály, a blogposztokat viszont mindenféle szempont alapján kell kiválogatni és rendezni. Ezt valahogy így képzelem el:

<?php

/** @var PostCollection $allPosts */
$postList = $allPosts
        ->filter(new PublishedPostFilter())
        ->filter(new CategoryFilter($category))
        ->orderBy(new PublicationDateComparator());

A felhasznált osztályok így néznének ki:

<?php

class PublishedPostFilter implements PostFilter {

    public function matchesCriteria(Post $post) {
        return Post::STATUS_PUBLISHED == $post->getStatus();
    }

}

class PublicationDateComparator implements PostComparator {

    public function compare(Post $post1, Post $post2) {
        return ... // valami számítás a timestampekkel
    }

}

A filter és orderBy metódusok mind egy új PostCollection objektummal térnének vissza, a kollekció, amin meghívjuk őket, érintetlenül maradna. A teljesítmény egyelőre nem számít, kevés poszttal számolunk.

Nekem ez a láncos megoldás nagyon szimpatikus, úgy lehet írni az új szűrőfeltételeket, kicsit olyan, mintha SQL-t írnánk. Viszont már ránézésre is sérti Demeter törvényét, mivel egy másik osztály által létrehozott objektumok metódusait hívogatja.

Ezt valahogy így lehetne megkerülni:

<?php

$selector = new PostSelector(
    array(
        new PublishedPostFilter(),
        new CategoryFilter()
    ), array(
        new PublicationDateComparator()
    )
);
$postList = $selector->selecFrom($allPosts);

Mit gondoltok? Csúnya az első megoldás?

kérdezve Jún 2, 2016 PHP kategóriában lencse (2 pont) által

Szerintem nincs vele baj, bár én lehet, hogy valamilyen buildert csinálnék vagy egy lazy collection megoldást és csak a végén végezném el a műveleteket.

1 válasz

0 like 0 dislike

Nem hiszem, hogy sérül. Ha megnézed, a Law Of Demeter nem egy abszolut szabály, nem azt mondja ki, hogy senki nem tudhat semmiről, hiszen akkor nem tudnánk programozni.

Ha az angol Wikipediából indulok ki:

  1. Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
  2. Each unit should only talk to its friends; don't talk to strangers.
  3. Only talk to your immediate friends.

Nézzük ezeket a szabályokat a filtereidre vetítve.

  1. A filter szorosan hozzá tartozik a blog funkcionalitáshoz? Persze, mi máshoz tartozna?
  2. A filter barátja a blogpostnak? Persze, az az egyetlen barátja. (Tudom, valahol szomorú.)
  3. A filter csak és kizárólag a közvetlen barátjával beszél.

Ezek a szabályok nem abszolutak, nincs egy elemző engine ami el tudja dönteni helyetted, hogy mi tartozik össze és mi nem.


Mindazonáltal, nekem vannak tervezési aggályaim a felvázolt mintával kapcsolatban, ugyanis minden áron flexibilis akarsz lenni, de ezzel egy olyan API-t formálsz, ami szinte esélytelen arra, hogy optimalizáld a teljesítményt. Ez pedig oda fog vezetni, hogy lesznek emberek, akik a későbbiekben az átadott filter tipusára írnak if statementeket a színfalak mögött, vagy ami még rosszabb, SQL statementeket raknak a filterbe, onnantól pedig elkezd rohadni a kód.

Szerintem, Keep It Simple Stupid. Olyan API-kat tervezz, amire valóban szükség van, ne próbálj meg a projekt nulladik percében egy általános, mindenre alkalmas API-t tervezni. Szinte biztos, hogy nem találod el azt, amire a végén szükség van, és szívni fogsz a meglevő struktúrákkal. Hagyd, hogy a kialakuljanak az igények, és ez alapján refaktoráld őket egy általánosított API-ba.

Az API tervezéssel kapcsolatban ezt az előadást tudom javasolni: https://www.refaktor.hu/how-to-design-a-good-api/

megválaszolva Jún 8, 2016 Pásztor János (494 pont) által
A Veremcsere a Refaktor Magazinhoz kapcsolódó, barátságos kérdezz-felelek oldal, ahol felteheted a webfejlesztéssel és üzemeltetéssel kapcsolatos kérdésedet.

A részletekért olvasd el az üdvözlő postunkat!
Az oldal valamennyi tartalma a Creative Commons Attribution NonCommercial ShareAlike 3.0 licenc alatt érhető el.

Kapcsolódó kérdések

0 like 4 dislike
1 válasz
1 like 0 dislike
2 válasz
0 like 0 dislike
0 válasz
0 like 0 dislike
2 válasz
kérdezve Ápr 22, 2016 PHP kategóriában kocsisdavid99 (13 pont) által
0 like 0 dislike
1 válasz
kérdezve Ápr 18, 2016 PHP kategóriában wpdaniel (178 pont) által
67 kérdés
142 válasz
354 hozzászólás
113 felhasználó