[oop] programmeren naar data of behaviour?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ozzie PHP

Ozzie PHP

18/03/2014 02:39:14
Quote Anchor link
Hey guys,

Ik vroeg me ineens iets af. Een van de $_SERVER variabelen bevat een string met de encoding-types die de client ondersteunt.

Nu heb ik in mijn request\client object een method getEncodingTypes() gemaakt waarmee je die string kunt opvragen. Nu is mijn vraag... (ik heb namelijk echt geen idee of hier een "stelregel" voor geldt...) of je het beste kunt programmeren naar data of naar behaviour. Daarmee bedoel ik het volgende:

Hoe ik het nu doe, programmeer ik naar data. Namelijk:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$client
= $request->getClient();
$encoding_types = $client->getEncodingTypes();
if (strpos($encoding_types, 'gzip')) {
  // doe iets
}
?>

Wat er dus gebeurt, is dat ik data ophaal (de string met encoding-types) waarmee ik vervolgens iets ga doen (namelijk controleren of het type "gzip" aanwezig is).

Wat ik ook kan doen, is programmeren naar behaviour (gedrag/functionaliteit).
Voorbeeld:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$client
= $request->getClient();
if ($client->hasEncoding('gzip')) {
  // doe iets
}
?>

Hier haal ik dus geen data op, maar "vraag" ik aan de client of hij het encoding-type "gzip" heeft.

Heeft van deze 2 methodes eentje de voorkeur? Is daar een "stelregel" voor, of maakt het niks uit en is het net wat je zelf leuk vindt?
 
PHP hulp

PHP hulp

28/03/2024 09:56:37
 
Reshad F

Reshad F

18/03/2014 10:22:59
Quote Anchor link
2e voorbeeld.
 
Ward van der Put
Moderator

Ward van der Put

18/03/2014 10:44:54
Quote Anchor link
Het tweede voorbeeld, maar je hebt hier niet echt autonome klassen. Het bestaan van een client impliceert het bestaan van een server: zonder server geen clients. Vervolgens impliceert een response het bestaan van een request: een response is een antwoord op een request, zonder request geen response. Die delen daarbij een gemeenschappelijk toestand: wel of geen gzip gebruiken.

Je hebt hierdoor als het ware meerdere niveaus in collecties:

• client <--> server
• client{request} <--> server{response}
• client{request{content-encoding}} <--> server{response{compression}}

Misschien een ander voorbeeld verzinnen, want het eerste voorbeeld is niet per se onbruikbaar.
 
D Vivendi

D Vivendi

18/03/2014 11:43:11
Quote Anchor link
Het eerste voorbeeld, kort waarom dit zo moet zijn:

In een threaded language zoals C#.NET kan het bijvoorbeeld zo zijn dat je een "state" opvraagt.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
if ( Obj.HasType("blaat") )
{
    var calc = DoeEenBerekening();
    var val = Obj.GetTypeValue("blaat");
    calc.value = val;
}


Het probleem wat je kan hebben is dat je eerst kijkt of "blaat" bestaat. Vervolgens zou een andere thread dat type weer verwijderd kunnen hebben door een ander request.
Vervolgens wil je wel "GetTypeValue()" aanroepen wat dan reslteert in vervelende fouten. Om dit te voorkomen heb je in die talen wel weer locking, maar het gaat om het principe.

In PHP heb je dan welliswaar niet zo zeer last van Threading problemen. Maar je zou het zelfde voorbeeld kunnen verplaatsen naar iets als wanneer je eerst checked of een record in je DB bestaat, en vervolgens haal je het er pas uit. Het zou tussen de "has" en "get" al verwijderd kunnen zijn.

Dit principe heet "Tell, don't ask". Als je meer info hier over wilt en meer voorbeeld wilt hebben dan zou ik gewoon het een en ander even doorlezen hierover:

http://martinfowler.com/bliki/TellDontAsk.html
https://www.google.nl/#q=tell+dont+ask+oop&safe=active
 
Ozzie PHP

Ozzie PHP

18/03/2014 13:07:59
Quote Anchor link
Bedankt voor jullie reacties.

@Ward: je uitleg is spot on. Je hebt inderdaad een client en server als onderdeel van het request. En een response als antwoord op dat request. In de response wil je dan via het request aan de client vragen of deze bijv. gzip ondersteunt.

@D Vivendi:
Ik snap (nog) niet helemaal nog wat je bedoelt eigenlijk :-s
Wat is precies het verschil of ik vraag welke types er aanwezig zijn (situatie a) of dat ik vraag of een specifiek type aanwezig is (situatie b)? Waarom is optie b volgens het "tell don't ask" principe niet goed?


Ook nog een andere vraag:

Ik zag dat mensen cheken met strpos of een bepaalde encoding method bestaat:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
if (strpos($_SERVER['HTTP_ENCODING_TYPES'], 'gzip')) {
  // doe iets
}
?>

Is dit niet een "tricky" manier van controleren? Stel dat er ook een encoding type "bugzip" zou bestaan, dan zou strpos een positief resultaat opleveren. Dat is dan toch geen veilige manier van controleren? Of zie ik dat verkeerd?
 
Ward van der Put
Moderator

Ward van der Put

18/03/2014 13:29:58
Quote Anchor link
Hangt ook van de compressie van de response af. Het mag bijvoorbeeld ook 'deflate' zijn als je ergens ob_start('ob_gzhandler') wilt doen.

Niet-hoofdlettergevoelig controleren met stripos() in een Yoda-conditie met een strikte gelijkheid vind ik zelf netter. Kwestie van smaak:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
if (
    false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') ||
    false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate')
) {

    ob_start('ob_gzhandler');
}

?>
 
Dos Moonen

Dos Moonen

18/03/2014 13:32:18
Quote Anchor link
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3

Het zal waarschijnlijk niet mis gaan de komende 10-20 jaar, maar als je zekerheid wilt dan doe je het strikt op basis van de bovenstaande regels.

PS. zoals ward zei: niet hoofdletter gevoelig, spaties kun je negeren geloof ik
Gewijzigd op 18/03/2014 13:34:11 door Dos Moonen
 
D Vivendi

D Vivendi

18/03/2014 13:34:05
Quote Anchor link
Je optie B is niet "tell, don't ask". Daar "ask" je juist iets -> "Heb je toevallig 'gzip' in je lijst zitten".

Ik heb al geprobeerd uit te leggen waarom je dat niet op jouw "B" manier wilt doen, maar juist volgens het "Tell, don't ask" pricipe. Er is zat leesvoer hier over te vinden, als je echt geintreseerd bent dan zoek je gewoon heel wat informatie op en neem je dat door. Daarna snap je het echt wel, het is geen rocket science.
 
Ozzie PHP

Ozzie PHP

18/03/2014 13:39:04
Quote Anchor link
@Ward:

Ik bedoel eigenlijk dit: stel dat er een comppressie methode "bugzip" bijkomt, dan zou "gzip" matchen met "bugzip". Hoe voorkom je zoiets? Strpos is toch niet echt een veilige manier om iets te controleren?

@D Vivendi:

Ik snap het principe niet. In het voorbeeld wordt gezegd dat je iets opvraagt, wat even later weg kan zijn. Echter, in dit geval haal je verder niks op. Je vraagt of de client iets ondersteunt. Het is niet zo dat de client dat het ene moment wel ondersteunt, en even later ineens niet meer. Vandaar dat ik niet begrijp op welke manier het "tell, don't ask" principe hier van toepassing is.
 
Ward van der Put
Moderator

Ward van der Put

18/03/2014 13:44:43
Quote Anchor link
>> Strpos is toch niet echt een veilige manier om iets te controleren?

Al gezegd: HTTP is hier niet hoofdlettergevoelig. Als je daar omheen fietst met stripos() in plaats van strpos(), dan ben je er eigenlijk al, want de implementatie van ob_start('ob_gzhandler') in PHP controleert zelf achter de schermen al óf er een acceptabele compressie wordt gevraagd en past de gevraagde compressie vervolgens toe. Dat hoef je niet nog eens zelf na te bouwen.
 
Ozzie PHP

Ozzie PHP

18/03/2014 13:54:01
Quote Anchor link
Ik bedoelde eigenlijk wat anders, maar ik heb het denk ik niet heel duidelijk uitgelegd waarvoor mijn excuses.

Stel je hebt een string:

$string = "foo, barbarapappa";

Als je nu wil kijken of in die string de waarde "bar" aanwezig is, dan zou dat met strpos resulteren in een positief resultaat omdat barbarapappa een match oplevert. Echter, er is helemaal geen waarde "bar". Mijn idee is dan ook dat strpos geen veilige manier is om waardes in een string te controleren.
 
Dos Moonen

Dos Moonen

18/03/2014 14:01:11
Quote Anchor link
Klopt, ik heb je een link gegeven waar staat uitgelegd hoe je de accept-encoding header moet parsen. Dus als je wilt kun je het veiliger maken. De vraag is of het nodig is.
 
D Vivendi

D Vivendi

18/03/2014 14:01:53
Quote Anchor link
Quote:
Ik snap het principe niet. In het voorbeeld wordt gezegd dat je iets opvraagt, wat even later weg kan zijn. Echter, in dit geval haal je verder niks op. Je vraagt of de client iets ondersteunt. Het is niet zo dat de client dat het ene moment wel ondersteunt, en even later ineens niet meer. Vandaar dat ik niet begrijp op welke manier het "tell, don't ask" principe hier van toepassing is.


En wat als je ergens anders die zelfde "$client->hasEncoding()" gebruikt om vervolgens wél $client->getEncondigStrcuture()" oid aan te roepen? Dat weet je van te voren toch nooit. Wellicht heb je die methode nu niet, maar misschien wil je dat in de toekomst wel.

Het gaat hier ook om het "principe", vadaar de naam "Tell, don't ask principle". Het legt uit wat het idee er achter is, welke gevaren er achter kunnen schuilen etc. Als je die ideeën gewoon eens door lees, dan krijg je vanzelf antwoord op al die vragen.

Dan kun je uiteindelijk ook voor jezelf bepalen of je het wel of niet wilt toepassen. Het enige wat ik er mee wil zeggen is, dat mensen hier al over negedacht hebben en dat je daar meer over kan lezen als je wilt.
Gewijzigd op 18/03/2014 14:02:34 door D Vivendi
 
Ozzie PHP

Ozzie PHP

18/03/2014 14:13:36
Quote Anchor link
@Dos: ik geloof dat ik niet helemaal begrijp wat je bedoelt :-/

@D Vivendi:

>> En wat als je ergens anders die zelfde "$client->hasEncoding()" gebruikt om vervolgens wél $client->getEncondigStrcuture()" oid aan te roepen? Dat weet je van te voren toch nooit. Wellicht heb je die methode nu niet, maar misschien wil je dat in de toekomst wel.

Sorry, ik doe echt m'n best om te begrijpen wat je bedoelt. Stel dat ik het voorbeeld iets wijzig, misschien kan ik dan beter overbrengen wat ik bedoel, en misschien kan jij dan uitleggen wat jij bedoelt en valt bij mij het kwartje.

Laten we de encoding types vergeten, maar laten we hetzelfde voorbeeld gebruiken om de browser te checken.

We zouden dat weer op deze 2 manieren kunnen doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$browser
= $client->getBrowser();
if ($browser === 'internet explorer') {
  // doe iets
}
?>

Of...

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
if ($client->hasBrowser('internet explorer')) {
  // doe iets
}
?>

Jij zou kiezen voor de 1e optie, maar ik begrijp de redenering erachter niet.

Ik wil alleen weten of ie een bepaalde browser gebruikt. Zijn browser zal gedurende het request niet ineens veranderen, en als ik weet dat de browser bestaat, dan hoef ik die niet via een get method te getten. Het kwartje valt bij mij nog niet.
 
Ward van der Put
Moderator

Ward van der Put

18/03/2014 14:40:36
Quote Anchor link
>> Als je nu wil kijken of in die string de waarde "bar" aanwezig is, dan zou dat met strpos resulteren in een positief resultaat omdat barbarapappa een match oplevert. Echter, er is helemaal geen waarde "bar". Mijn idee is dan ook dat strpos geen veilige manier is om waardes in een string te controleren.

Dan schrijf je een kleine parser voor dit specifieke type string. Zoals Dos ook aangaf. Daarin zul je vervolgens moeten vastleggen wat een acceptabel "woord" is waarop gecontroleerd kan worden (denk aan spaties, komma's of komma's gevolgd door een spatie en kleine letters, hoofdletters of mengvormen). Tot slot controleer je of het gezochte woord voorkomt in de string.

In wezen doe je iets vergelijkbaar ook bij een regexp: die voer je een instructie met verschillende regels in een pattern, waarna die regels achter de schermen worden geëvalueerd. En als het met een regexp kan, dan hoef je zelf geen parser te schrijven. Misschien een idee?
 
Ozzie PHP

Ozzie PHP

18/03/2014 14:49:18
Quote Anchor link
Ik heb dus getest en de waarde die uit de $_SERVER variabele komt is "gzip, deflate".

Wat ik zou kunnen doen is de spaties verwijderen, en dan exploden:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$_SERVER
['HTTP_ACCEPT_ENCODING'] = explode(',', str_replace(' ', '', $_SERVER['HTTP_ACCEPT_ENCODING']));
?>

Dan wordt het een array:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
array(2) { [0]=> string(4) "gzip" [1]=> string(7) "deflate" }

En dan is het een stuk makkelijker, want dan kun je in_array gebruiken. Maar nu moet ik dus wel eerst die string ombouwen naar een array. En ik vraag me af of dat niet een beetje over de top is.

Of je dat kunt doen met een regexp? Vast wel, maar daar ben ik nog niet zo goed in.
 
Dos Moonen

Dos Moonen

18/03/2014 15:59:22
Quote Anchor link
Je vergeet een explode op ';' (zou met array_map() kunnen, of een foreach() of verzin zelf iets)

Quote:
14.3 Accept-Encoding

The Accept-Encoding request-header field is similar to Accept, but restricts the content-codings (section 3.5) that are acceptable in the response.

Accept-Encoding = "Accept-Encoding" ":"

1#( codings [ ";" "q" "=" qvalue ] )
codings = ( content-coding | "*" )

Examples of its use are:

Accept-Encoding: compress, gzip
Accept-Encoding:
Accept-Encoding: *
Accept-Encoding: compress;q=0.5, gzip;q=1.0
Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0


Weet je nog wat ik zei over meer maar goed te volgen kleine stapjes versus weinig complexe stappen (regex in dit geval)?
 
Ozzie PHP

Ozzie PHP

18/03/2014 16:10:17
Quote Anchor link
Thanks Dos. Ik had dat zien staan, maar begreep niet hoe het te interpreteren. En nu ik er naar kijk nog niet echt. Die q waardes die horen toch bij een type? Bijv. bij gzip?

>> Weet je nog wat ik zei over meer maar goed te volgen kleine stapjes versus weinig complexe stappen (regex in dit geval)?

Ja, beter kleinere stapjes en het overzicht bewaren.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.