Ho uno scenario molto concreto, ma penso che sarebbe abbastanza frequente.
Sto cercando di trovare una soluzione che sia "migliore" meglio che significhi più scalabile, riutilizzabile e non maleodorante.
Sto lavorando con un vecchio codice legacy crufty e sto provando a migliorarlo una cosa alla volta. In questo momento ho un processo in cui gli utenti possono "votare" "cose".
Il processo per determinare se un utente può votare è una logica complessa e potrebbe essere soggetto a modifiche.
In questo momento ho due funzioni, una (la chiamo can_vote ()) prende l'utente e la cosa e restituisce vero o falso. È usato per sapere cosa visualizzare all'utente.
L'altro è vote () Richiede utente e cosa e controlla di nuovo tutta la logica che can_vote controlla ma invece di restituire false in caso di errore genera un errore che viene visualizzato all'utente.
Il sistema tenta di non arrivare mai a uno stato in cui l'utente sarebbe in grado di utilizzare "vota" se il risultato sarebbe un'eccezione ma si verifica ancora.
So che potrebbero esserci migliaia di difetti nell'intero sistema ma in questo momento l'unica cosa che sto cercando di fare è unire la logica delle due funzioni in un unico posto nel modo migliore (come definito sopra).
Idealmente, mi piacerebbe poter chiamare can_vote nei miei controller solo ottenendo un vero o falso e agendo in modo appropriato. può_vote, essendo una domanda binaria dovrebbe restituire true | false. Potrei essere in grado di utilizzare la logica all'interno di can_vote nei luoghi in cui voglio visualizzare informazioni sulle risposte "false".
Ho diverse idee su come risolverlo ma tutte sembrano ... strane:
Possibili soluzioni
a) usa can_vote (utente, cosa, verboso)
verbose essendo vero falso se true restituisce una stringa con l'errore se false restituisce true | false
public can_vote ( user, thing, verbose ) {
if( user is not logged ) {
if( verbose ) {
throw user is not logged
}
return false
}
//all other checks
return true
}
contro
- restituisce diversi tipi a seconda dei parametri
- ottieni un altro se ti porti dietro la funzione
b) usa una funzione privata per determinare se puoi votare. Utilizza due funzioni di supporto
sarebbe qualcosa di simile:
private can_really_vote ( user, thing ) {
if( user is not logged ) {
throw user is not logged
}
//all other checks
return true
}
public can_vote ( user, thing ) {
try {
can_vote = this->can_really_vote( user, thing )
}
catch {
//can_really_vote threw an exception
return false
}
return false
}
public vote ( user, thing ) {
if ( this->can_vote( user, thing ) ) {
//do the vote thingy
}
else {
// you shouldn't even get here. The user should have gotten an exception from can_really_vote
}
}
c) che php di solito fa
Sarebbe qualcosa di simile
public vote () {
if ( can_vote() ) {
//carry on with the voting
}
else {
display can_vote_last_error()
}
}
Cose del genere sono solitamente viste nelle classi di accesso ai database e simili. Veramente? Mantenere una traccia interna di tutti quegli errori stupidi come "non sei loggato", "il contest è finito" e tutte queste cose solo per poterle richiamare? Sembra abbastanza complicato.
Ovviamente può essere fatto meglio, ad esempio con eccezioni dedicate ... non sembra una pasta giusta.
Sono sicuro di poter ottenere più soluzioni ... il problema si riduce a voler ottenere un risultato vero / falso in un caso e un testo su un altro per la stessa logica.
Suppongo che il problema sia abbastanza comune, quindi ci dovrebbe essere qualche schema software per questo. O forse non riesco a estrapolarlo, quindi vedo l'ovvia soluzione elegante.
Che cosa faresti?
Grazie!
PS Sono quasi sicuro che non importi, ma sto lavorando su vanilla PHP 5.3