Voor een API heb ik een abstract class AbstractRequest die het dataverkeer regelt:
<?php
namespace NewCo;
abstract class AbstractRequest
{
public function __construct($api_key)
{
$this->setApiKey($api_key);
}
// <...>
}
?>
Voor elk type API-transactie geldt daarnaast de interface TransactionInterface:
<?php
namespace NewCo;
interface TransactionInterface
{
public function __construct($api_key);
public function startTransaction();
public function validateTransaction($transaction_id);
}
?>
Elk transactieklasse ziet er tot slot zo uit:
<?php
namespace NewCo;
class Foo extends AbstractRequest implements TransactionInterface
{
public function __construct($api_key)
{
parent::__construct($api_key);
}
public function startTransaction()
{
// <...>
}
public function validateTransaction($transaction_id)
{
// <...>
}
}
?>
[/code]
Klinkt dit logisch? Of zie ik iets over het hoofd? Zouden jullie ergens iets anders doen? Ik hoor het graag!
Volgens mij kan het wel. Het enige wat ik me afvraag is of een request en transactie bij elkaar horen in 1 class, maar dat kun jij beter inschatten dan ik. Wat je nu zegt is dat een transactieklasse een request is "Foo extends AbstractRequest".
Volgens mij kan het wel. Het enige wat ik me afvraag is of een request en transactie bij elkaar horen in 1 class, maar dat kun jij beter inschatten dan ik. Wat je nu zegt is dat een transactieklasse een request is "Foo extends AbstractRequest".
Klopt, de Request-klasse bouwt een URL op voor de API inclusief de API-sleutel via een eigen setter. Alle transacties voegen daaraan vervolgens unieke parameters toe. Het abstracte Request-object is een onbesmeerd broodje en de transactie het beleg, zeg maar, zodat je een broodje ham of een broodje kaas kunt maken.
Ward, ja dit is ook hoe ik het zou doen, behalve...
- De constructor hoort niet bij de interface, maar bij de AbstractRequest. Haal die weg uit de interface. Mocht je vinden dat ze wel bij elkaar horen dan laat je de AbstractRequest meteen de interface testen.
- bij klasse Foo regel 6 - 9 zijn nutteloos, waarom heb je dat gedaan?
- Waarom krijgt startTransactie geen parameter?
- Als je klasse al Transaction heet zou ik gewoon een method ->start() en ->validate() gebruiken
- Ik vraag me sterk af wat de klasse precies doet. Ik zou het bijv. al in 3 delen onderdelen: Transaction (entity/document), TransactionHandler (doet de transactie), Validation
Toevoeging op 20/11/2013 15:24:00:
- Je stopt alles in de hoofdnamespace, bundel het eens lekker in subnamespaces :)
Dank je Wouter! Die constructor is inderdaad niet fris. (Het viel me op toen ik de code ging kopiëren naar een andere klasse en dat had al een teken aan de wand moeten zijn.)
De API-sleutel moet er wel altijd in. Zou dat een apart object moeten worden of is dat een brug te ver?
De transactie en de validatie van de transactie kunnen eigenlijk inderdaad wel worden gesplitst. Je gebruikt ze nooit beide tegelijk, maar altijd na elkaar. Je kunt immers niet valideren of een transactie is geslaagd als je die nog niet hebt gestart (en daarom stonden ze oorspronkelijk in één klasse, maar dat is niet zaligmakend).
Oh, wacht. Met validatie bedoel je of de request geslaagd is? Dan zou ik het wel in deze klasse stoppen. Dan krijg je iets als:
<?php
$transaction = new IBANTransaction($apiKey);
$transaction->start();
while (true) {
if ($transaction->isFinished()) {
break;
}
}
if ($transaction->hasErrors()) {
echo 'Errors: '.implode(', ', $transaction->getErrors());
} else {
// ... rest van de applicatie
}
?>
De API sleutel moet er altijd in vanwege het Request object. De Transactie heeft niet perse een API sleutel nodig. Vandaar dat ik zeg: Stop hem in de AbstractRequest object en haal hem weg uit de TransactionInterface.