2012-09-03 4 views
18

Sto guardando il codice che è essenzialmente il superamento di un id in giro, per esempio:Che vantaggio c'è nel wrapping di un tipo semplice in una classe?

GetPersonById(int personId) 

Ma invece di usare un int, ha usato un oggetto PersonId.

GetPersonById(PersonId personId) 

L'oggetto PersonId è solo un int con qualche codice a mano per renderlo nullable. Così è stato creato nel vecchio .NET quando gli inteble nullable non erano disponibili o esiste uno scopo più elevato per il wrapping di tipi semplici in una classe?

public sealed class PersonId { 

    private PersonId() { 
     _isNull = true; 
     _value = 0; 
    } 


    private PersonId(int value) { 
     _isNull = false; 
     _value = value; 
    } 

    // and so on! 
} 
+0

È questo codice DDD? –

+0

Un motivo per cui immagino è tenere traccia del ciclo di vita degli oggetti. Forse automatizzare alcuni meccanismi di rilascio dell'ID? – mtsvetkov

+0

@DanielHilgarth - Non posso davvero descrivere il codice in grande dettaglio e non ho ancora capito i pensieri del creatore, ma nel complesso direi che il dominio era lontano dai loro pensieri. Mi piacerebbe sentire come sarebbe usato in DDD, piuttosto che in int (o in una classe Person). – Fenton

risposta

16

In DDD codice come questo è usato per fare il tipo di questo ID riferimenti più espliciti.

Soprattutto nel contesto di aggregati ben progettati, i riferimenti ad altri aggregati sono molto spesso per ID, non per riferimento oggetto. In questo caso, tali oggetti con valore ID possono essere utilizzati per evitare il mescolamento accidentale di questi ID e - come detto prima - per rendere più esplicito l'aggregato a cui si fa riferimento.

+2

+1 I costruttori privati ​​di' PersonId' lo rendono probabilmente più significativo di "solo un valore nullable". –

+2

Esatto, quindi se abbiamo eliminato il codice nullable creato manualmente e utilizzato un valore nullable int (e modificato i metodi di conseguenza), potrebbe ancora avere un valore - non potremmo mai passare un PersonId in 'GetSession (SessionId sessionId) 'ad esempio. – Fenton

+0

@Sohnee: esattamente. –

2

Questo codice è stato probabilmente scritto in C# 1.0, quando Nullable<T> non esisteva.

Ora è necessario utilizzare int?.

+2

Non saltare alle conclusioni così in fretta. Potrebbero esserci altre ragioni. Ho visto questo tipo di oggetto valore in un sacco di codice DDD e campioni. –

+0

Beh, questa è la mia opinione ;-) –

+0

Suppongo che questo sia il caso della domanda. Non riesco a pensare a nessuna ragione per farlo a parte il fatto che sia stato creato prima di valori nulli, quindi a meno che qualcuno non abbia una ragione convincente, otterrai il segno di spunta verde! – Fenton

0

Non vi è alcun vantaggio, tranne l'utilizzo di tipi di valori come valori nulli. Niente di più.

1

Per me penso che sia preferibile utilizzare i tipi più primitivi del framework.

-> Non ci sono benefici

1

Il vecchio C# può essere una spiegazione per questo.
ma suppongo che possa avere altra spiegazione, un pensiero futuro ...
Se in futuro vorresti avere più dati per una persona, cambiando la classe PersonId stessa o ereditandola, tutto il codice sarà funziona ancora così com'è. ma se dovessi usare int? allora dovrai cambiare tutte le chiamate.

8

L'utilizzo di una classe è un buon modo per semplificare l'ulteriore refactoring se i campi utilizzati per identificare una persona devono essere modificati. Supponiamo che domani il sistema raggiunga le persone Int32.MaxValue e si desideri utilizzare uno o una stringa per identificarli. Un altro caso potrebbe essere, quando i requisiti per il sistema non sono accurati al 100% e non hanno specificato se una persona sarebbe identificata da un ID, un PIN o qualsiasi combinazione di campi a cui si possa pensare. L'autore di questo codice, potrebbe avere però di impedire un importante refactoring creando questa classe.

5

La risposta potrebbe essere anche la semantica!

Immagina di avere un valore int. È un ID? O è l'età, l'altezza in cm, la temperatura in gradi centigradi, il numero di programmi TV? Bene, puoi dare un buon nome alla variabile, ma questo non ti proteggerà se commetti un errore.

Al contrario, se una funzione richiede un'istanza classe ID (che è, ben, int mascherato) e non solo int, ma si tenta di passare valore per errore (che risulta essere int come coordinata X bene, o istanza di Coordinate, o qualsiasi altra cosa, il compilatore sarà catturarlo e avvisare. Inoltre, chiunque legga il codice può vedere chiaramente che il valore necessario non è solo int, ma un ID: non è possibile farlo meglio con la documentazione, nessuno lo legge comunque.

(Nota a margine:! Non si può immaginare, quanto mal di testa mi ero cercando di refactoring del codice che ha usato double per gli angoli in entrambi i gradi e radianti E 'stato un incubo Dopo il passaggio a un class Angle, tutto è andato molto meglio.)

Problemi correlati