Verifica degli oggetti

4

Se un metodo accetta un oggetto di classe A come parametro e analizza le sue proprietà in qualche modo, esegue calcoli ecc. per verificare questo oggetto, è corretto per la classe A avere un campo boolean valid ? Dopo che il metodo della classe B ha completato la verifica di questo oggetto, imposta il flag booleano di conseguenza.

Il processo di verifica richiede alcune informazioni aggiuntive basate su oggetti di classi diverse da A, quindi è impossibile inserire un metodo di verifica in A: l'oggetto non può semplicemente verificare (o validare) stesso, proprio come non fa molto senso per una classe Car di avere un metodo di riparazione. Ma ha senso avere un workingFine flag, credo in un Car . Quindi è meglio memorizzarlo come una bandiera in A? O dovrei fare qualcos'altro?

    
posta user4205580 08.04.2016 - 21:56
fonte

3 risposte

3

Nel tuo caso, l'oggetto stesso non è "valido". È "valido in qualche contesto". Questo contesto è definito come "informazioni aggiuntive" che hai descritto. In quanto tale, dovrebbe essere ovvio in quale contesto l'oggetto è valido.

Direi che mettere flag IsValid nell'oggetto non ha molto senso in questo caso. Solo caso avrebbe senso se context fosse strettamente legato all'oggetto stesso. In tal caso, l'oggetto stesso può avere un riferimento a questo context .

Altrimenti creerei un oggetto speciale di "validazione", che legherebbe insieme le informazioni su quale oggetto, quale contesto e se è valido.

    
risposta data 08.04.2016 - 22:34
fonte
0

Un'opzione potrebbe essere quella di adattare il modello trovato in C # IValidatableObject interfaccia . Come puoi vedere, è necessario un ValidationContext oggetto come parametro. L'oggetto può quindi utilizzare quel contesto per convalidare se stesso per lo scopo / contesto specifico su cui viene convalidato.

Non mi piace particolarmente questo pattern 1 ma è un modo per oggetti per convalidare se stessi in un modo specifico del contesto. In questo caso, penso che sia molto meglio della tua attuale soluzione di un campo booleano valid generico / proprietà impostato da un'altra classe basata su un contesto di convalida sconosciuto.

Un'alternativa a una sorta di interfaccia che consente di specificare il contesto per la convalida sarebbe quella di avvolgere l'oggetto. Ciò ti darebbe i vantaggi di impostare la proprietà / campo senza interrompere l'incapsulamento o richiedere una sottoclasse per ogni oggetto. Non parli della lingua che stai usando, ma qualcosa del genere potrebbe funzionare in C #:

public class Validated<T>
{
  public Validated<T>(bool isValid, T validatedObject)
  {
     IsValid = isValid;
     ValidatedObject = validatedObject;
  }
  public bool IsValid { get; }
  public T ValidatedObject { get; }
}

Potresti aggiungere un'altra proprietà alla classe sopra per specificare in quale contesto la classe è considerata valida se c'è qualche preoccupazione che il contesto possa essere ambiguo in un certo periodo della vita dell'oggetto.

1: Post del blog generico che ho scritto sulla convalida che menziona brevemente questo schema.

    
risposta data 08.04.2016 - 22:42
fonte
0

Idealmente, non dovresti aver bisogno di memorizzare queste informazioni in modo esplicito. Dovrebbe seguire implicitamente dal flusso di controllo del tuo programma.

;; Very easy to read

ROUTINE ProcessItem(item)
BEGIN
    IF IsValidItem(item) THEN
        ProcessValidItem(item)
    ELSE
        ProcessInvalidItem(item)
    FI
END

ROUTINE ProcessValidItem(item)
BEGIN
    DoSomething(item)
    DoAnotherThing(item)
    DoThisThing(item)
END

ROUTINE ProcessInvalidItem(item)
BEGIN
    DoSomethingElse(item)
    DoAnotherThing(item)
END

All'interno delle subroutine ProcessValidItem e ProcessInvalidItem , non ho bisogno di un flag che mi dice se un elemento è valido. Se la struttura del tuo programma implica la validità di un oggetto, non puoi dimenticare di controllarlo. La validità dovrebbe essere verificata esattamente a un punto, se possibile. Invece di combinare il trattamento di articoli validi e non validi nella stessa funzione e decidere ripetutamente cosa fare in base a un flag "valido", separare il flusso di controllo in due percorsi di codice distinti e diretti e calcolare le parti comuni al trattamento di entrambi, articoli validi e non validi, in subroutine. Trovo il codice mostrato sopra molto più pulito rispetto al seguente esempio.

;; Not so easy to read

ROUTINE ProcessItem(item)
BEGIN
    valid ← IsValidItem(item)
    IF valid THEN
        DoSomething(item)
    ELSE
        DoSomethingElse(item)
    FI
    DoAnotherThing(item)
    IF valid THEN
        DoThisThing(item)
    FI
END

Se devi memorizzare la validità su una base per articolo, questo flag deve essere di proprietà di chiunque ne stabilisca la validità.

Se un oggetto può validarsi, dovrebbe avere un metodo che indichi se è valido. Che si convalidi da solo ogni volta che questo metodo viene chiamato o lo memorizza nella cache in un campo privato è un dettaglio di implementazione. Si interrompe chiaramente l'incapsulamento per lasciare che il codice al di fuori del pasticcio di classe con il valore di quel campo.

D'altra parte, se l'oggetto è validato da qualcun altro, allora questo qualcuno è responsabile della conservazione delle informazioni - al di fuori dell'oggetto. Dare l'accesso all'oggetto al suo stato di convalida determinato esternamente sarebbe altrettanto sbagliato che dare a qualcun altro l'accesso allo stato interno dell'oggetto. Una semplice struttura a coppie potrebbe essere utilizzata per allegare tali informazioni a un oggetto e rimuoverlo quando non è più necessario. In una configurazione orientata agli oggetti, il flag potrebbe essere sostituito dal polimorfismo per salvare una parola di archiviazione per il costo di una chiamata al metodo virtuale.

                    +-------------------------+
                    |    ValidatedItem<T>     |
                    +-------------------------+
                    | - item : T              |
                    +-------------------------+
                    | + getItem() : T         |
                    | + isValid() : Boolean   |
                    +-------------------------+
                                 ^
                                 |
             +-------------------+-------------------+
             |                                       |
+-------------------------+             +-------------------------+
|      ValidItem<T>       |             |     InvalidItem<T>      |
+-------------------------+             +-------------------------+
| + isValid() : Boolean   |             | + isValid() : Boolean   |
+-------------------------+             +-------------------------+
    
risposta data 09.04.2016 - 00:12
fonte

Leggi altre domande sui tag