[PHP]Sequental Coupling voorkomen of is het ok

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 12-09 13:36
Ik heb een class die een HTTP verzoek moet parsen: Request. Ik ben aan het testen met SimpleTest (http://www.simpletest.org).

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Request {
    /*
     * Handles all needed processing for urls, methods etc
     */
    public function process() {
        
        //Process HTTP accept so we know how to responds
        if(!$this->processHttpAccept()) {
            throw new HttpAcceptException('Authorisation failed.');
        }
        
        //parse url
        if(!$this->parseUrl($this->requestUri)) {
            throw new UrlParsingException('Url could not be parsed.');
        }
        
        //Process HTTP accept so we know how to responds
        if(!$this->processAuthorisation($_SERVER['HTTP_AUTHORISATION'])) {
            throw new AuthorisationFailedException('Authorisation failed.');
        }
        
        //Process the request method and the data so we get it all in our request object
        return $this->processMethodAndData();
    
    }

//overige methoden even weggelaten.
}


PHP:
1
2
3
4
5
6
7
8
9
//Aanroep van de class

$request=new Request($_SERVER['REQUEST_URI']);
            
//Configure the Request
$request->setBasePath(BASE_PATH);
            
//process whatever came in and get the response data back
$request->process();


Ik heb een aantal nette functies er in zitten, het voorbeeld is: $this->parseUrl($this->requestUri);

Dit is een functie die vanalles netjes uit de url haalt. Zo heb ik een stuk of 8 losse functie die duidelijk zijn in wat ze doen, duidelijk te testen op juist return.

De vraag:Die process() functie is slecht te testen, het doet van alles. Dus geen duidelijke specifieke taak. Eigenlijk vind ik dat dus maar niks. Aan de andere kant is het wel logisch $request->process() is te begrijpen.

Wat is de juiste manier: Of ik roep die functies allen gewoon los aan. Of ik behoud de process() functie maar test deze niet of alleen op Exceptions.

Het los aanroepen van de methodes lijkt me mooier maar dan krijg je het Sequential Coupling probleem. Daarnaast wordt de class erg public waardoor je bijna moet gaan snappen hoe je een Request verwerkt als je deze class aan gaat roepen. Dat is ook weer niet de bedoeling.

Wikipedia: Sequential coupling

Er zal niet echt 1 antwoord zijn maar wat is de best practice?

Acties:
  • 0 Henk 'm!

  • SoulWar1
  • Registratie: Augustus 2004
  • Laatst online: 21:06
Zelf vind ik het mooi om alles zoveel mogelijk te scheiden, classes maken die een enkele verantwoordelijkheid hebben. Je ziet dit ook terug in een aantal PHP frameworks. Om het even op jou voorbeeld toe te passen, het Request object heeft nu eigelijk al teveel dingen die hij moet doen. Request data uitlezen, controleren op geldigheid en het genereren van een Response.

Eigelijk zou je een Request object willen die puur bedoelt is voor het uitlezen van de request data die binnen komt. Dat is makkelijk te testen, klopt het wat je uitleest? Een tweede object kan dit Request object nemen en controleren, autorisatie bijv. Ook makkelijk te testen door een aantal verschillende Request objecten te geven.
Het laatste object kan dan het Request object accepteren en een response genereren, dit is meestal de verantwoordelijkheid van een Controller object (MVC).

Know Thyself


Acties:
  • 0 Henk 'm!

  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 12-09 13:36
Ik heb ook een Request object. Daar tussen processors, dus die scheiding heb ik aangebracht. Het enige wat de Request doet is de url, headers etc. opslaan in properties.

De vraag gaat me dus met name om die process() functie, die is vreemd en niet testbaar omdat deze alle benodigde acties triggert. Alleen is de enige manier om de specifieke taken dan aan te roepen.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
djluc schreef op zondag 22 januari 2012 @ 17:12:
De vraag gaat me dus met name om die process() functie, die is vreemd en niet testbaar
Waarom zou je die überhaupt testen (of meer dan 1 a 2 generieke testjes geven, allee). Zolang de process() method alleen maar intern andere classes instantieert en diens functionaliteiten gebruikt dan volstaat 't toch (voornamelijk) om die classes te testen?
Als er logica in process() zit, wat me wel voor de hand liggend lijkt, dan test je die logica; voor de rest kun je vertrouwen op de tests die op de rest van de classes uitgevoerd zijn/worden.

M.a.w.; je gaat voor bijvoorbeeld een XMLDocument->Load(location) toch ook niet elke mogelijkheid testen of 't ding wel nodes kan instantiëren, tags goed parsed, juiste parent/child relaties aan nodes hangt etc. Je test alleen of 'ie bijvoorbeeld url's en files en streams goed vreet (en netjes throwed bij fouten etc.).

Als deze methode de enige manier is om zaken aan te roepen dan zul je wat meer zaken moeten exposen of internals moeten testen op een andere manier. Ik weet niet hoe SimpleTest werkt, en ben niet heel erg bekend met PHP unittesting, maar in .Net hebben we daar bijvoorbeeld de InternalsVisibleToAttribute voor.

[ Voor 18% gewijzigd door RobIII op 22-01-2012 17:31 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 12-09 13:36
Daar heb je absoluut een punt, wellicht gaat het inderdaad te ver. Op een gegeven moment krijg je altijd ergens een punt waarop je de aanroep van de classes gaat doen waarbij het eigenlijk niet op te lossen is.

Sowieso wil je in zo'n classe zo min mogelijk inhoud hebben, dat voegt weinig toe dus denk dat je inderdaad gelijk hebt. Gewoon basis testje doen en that's it.