Non sono d'accordo con la vostra conclusione. Esistono molti buoni modi per incapsulare in C# con tutte le tecnologie sopra citate, al fine di mantenere buone pratiche di codifica del software. Direi anche che dipende dalla demo della tecnologia che stai guardando, ma alla fine si riduce a ridurre lo spazio degli stati dei tuoi oggetti in modo che tu possa assicurarsi di tenere sempre le loro invarianti.
Take framework relazionali oggetto; la maggior parte di questi ti consente di specificare come stanno andando ad idratare le entità; Per esempio, NHibernate ti consente di dire access="property"
o access="field.camelcase"
e simili. Questo ti permette di incapsulare le tue proprietà.
L'iniezione di dipendenza funziona sugli altri tipi che hai, principalmente quelli che non sono entità, anche se puoi combinare AOP + ORM + IOC in alcuni modi molto carini per migliorare lo stato di queste cose. IoC è spesso usato da strati sopra le entità di dominio se stai costruendo un'applicazione basata sui dati, che suppongo tu sia, dal momento che stai parlando di ORM.
Essi ("loro" sono applicazioni e servizi di dominio e altre classi intrinseche al programma) espongono le loro dipendenze ma in realtà possono essere incapsulati e testati in un isolamento ancora migliore rispetto al passato dai paradigmi di design per contratto/design -by-interface che usi spesso quando fai il mocking delle dipendenze nei test di simulazione (in congiunzione con IoC), ti sposterà verso la "semantica" di classe come componente. Voglio dire: ogni classe, una volta costruita utilizzando quanto sopra, sarà meglio incapsulata.
aggiornato per urig: Questo vale sia per i esponendo concreti dipendenze e interfacce esponendo. Prima di tutto sulle interfacce: ciò di cui mi accenno sopra era che i servizi e le altre classi di applicazioni che hanno dipendenze, possono con OOP dipendere da contratti/interfacce piuttosto che da implementazioni specifiche. In C/C++ e nelle lingue più vecchie non c'era l'interfaccia e le classi astratte non potevano che andare così lontano. Le interfacce consentono di associare diverse istanze di runtime alla stessa interfaccia senza doversi preoccupare di perdite di stato interno, ovvero di ciò che si sta tentando di allontanarsi durante l'astrazione e l'incapsulamento. Con le classi astratte è ancora possibile fornire un'implementazione di classe, solo che non è possibile creare un'istanza, ma gli eredi hanno ancora bisogno di conoscere gli invarianti nella tua implementazione e questo può rovinare lo stato.
In secondo luogo, sulle classi concrete come proprietà: devi essere cauto su quali tipi di tipi;) esponi come proprietà. Di 'che hai una lista nella tua istanza; quindi non esporre IList come proprietà; questo probabilmente cola e non è possibile garantire che i consumatori dell'interfaccia non aggiungano cose o rimuovano le cose dalle quali si dipende; esporre invece qualcosa come IEnumerable e restituire una copia dell'elenco o, ancora meglio, farlo come metodo: public IEnumerable MyCollection {get {return _List.Enum(); }} e puoi essere sicuro al 100% di ottenere sia le prestazioni che l'incapsulamento. Nessuno può aggiungere o rimuovere questo oggetto IEnumerable e non è ancora necessario eseguire una costosa copia dell'array. Il metodo di supporto corrispondente:
static class Ext {
public static IEnumerable<T> Enum<T>(this IEnumerable<T> inner) {
foreach (var item in inner) yield return item;
}
}
Così, mentre non si può ottenere il 100% incapsulamento in diciamo creando sovraccarico uguale operatori/metodo è possibile avvicinarsi con le interfacce pubbliche.
È inoltre possibile utilizzare le nuove funzionalità di .Net 4.0 basate su SpeC# per verificare i contratti di cui sopra.
Serializzazione sarà sempre presente e lo è stato per molto tempo. Precedentemente, prima che l'area internet venisse utilizzata per salvare il tuo oggetto grafico su disco per il successivo recupero, ora è utilizzato nei servizi Web, nella semantica della copia e quando si passano dati ad es. un browser. Ciò non interrompe necessariamente l'incapsulamento se si inseriscono alcuni attributi [NonSerialized] o gli equivalenti nei campi corretti.
Gli inizializzatori di oggetti non sono la stessa cosa dei costruttori, sono solo un modo per comprimere alcune righe di codice. I valori/istanze in {} non saranno assegnati fino a quando tutti i costruttori non avranno eseguito, quindi in linea di principio è come non utilizzare gli inizializzatori di oggetti.
Immagino che ciò a cui devi prestare attenzione si discosti dai buoni principi appresi dal tuo precedente lavoro e assicurati di mantenere gli oggetti del dominio pieni di logica aziendale incapsulata dietro buone interfacce e idem per il tuo servizio -strato.
Non farti ingannare da nessuno, quegli inizializzatori dell'oggetto sono solo zucchero sintattico. – BobbyShaftoe
So che gli inizializzatori di oggetti non sono realmente costruttori, ma non è questo il mio punto. Permettono di costruire un oggetto usando il costruttore predefinito e impostando le proprietà a mano. –
Non proprio sicuro di quale sia la differenza tra questi e semplicemente digitando ogni istruzione per impostare ciascuna proprietà. Ma ok. – BobbyShaftoe