Qual è il modo migliore per ottenere output diversi per due flussi di lavoro correlati molto similari

1

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

    
posta Miquel Adell 23.02.2015 - 14:57
fonte

2 risposte

1

Raccomando la soluzione c), ma la cambierei un po ': non visualizzerei alcun errore dalla funzione can_vote. L'utente dovrebbe sapere molto prima se può votare o meno e perché. La funzione vote () controlla solo se l'utente può votare come salvaguardia, perché come hai detto tu stesso dovrebbe esserci NO WAY il tuo programma chiama mai vote () quando l'utente non è autorizzato a votare. Quindi basta lanciare un'eccezione o registrare un errore.

Alcuni commenti sulle altre soluzioni:

Considero che a) sono molto confusionario e molto rischioso, perché se capovolgete accidentalmente il parametro verbose e controllate il risultato per vero / falso, potreste pensare che tutto sia andato a buon fine anche se avete ricevuto un messaggio di errore. Prova a risolvere il problema: un incubo!

La soluzione b) è solo un eccesso di codice, perché tutto ciò che fai è racchiudere una chiamata a una funzione in un try / catch e renderla un'altra funzione. Inoltre, immagina che un nuovo sviluppatore nel tuo progetto voglia sapere se un utente può votare. Trova le due funzioni can_vote e can_really_vote - quale dovrebbe chiamare?

Inutilmente confuso e senza alcun vantaggio.

    
risposta data 23.02.2015 - 23:28
fonte
0

Suggerirei (d) che la funzione di voto restituisca un risultato che dice se ha avuto successo o meno. Qualunque meccanismo tu usi per votare può fallire, l'utente dovrebbe essere informato se ciò accade.

public bool vote() {
   if (!can_vote()) { return false;}

   // take whatever action you need to, prefer functions that signal failure
   return true;
}
    
risposta data 25.05.2015 - 04:49
fonte

Leggi altre domande sui tag