Contesto
Recentemente ho letto della tecnica orientata agli oggetti per fare una distinzione tra oggetti e strutture dati passive , meglio riassunti in Clean Code:
"Objects hide their data [...] and expose functions [...]. Data structures expose their data and have no meaningful functions."
Sto pensando di utilizzare C # structs
per strutture dati passive .
Per chiarire questo: SE una parte del mio codice deve funzionare come una struttura di dati passivi , quindi voglio usare struct
per quello.
vantaggi
Fornirebbe una distinzione linguistica tra oggetti e strutture dati passive .
Inoltre, se un oggetto ha un campo privato di class
, ma lo espone in una funzione, può essere cambiato da qualche altra parte. Ciò significa che i dati oggetto vengono modificati dall'esterno, il che non è positivo. So che dovresti ad es. esporre un List
interno come ReadOnlyList
, ma questa è buona pratica , che anche i buoni programmatori non sempre seguono. Utilizzando structs
invece applica automaticamente questo
Quello che ho scoperto finora
Conosco la domanda " Quando utilizzare struct
" ha già risposto più volte . Le risposte si riducono sempre al parere dei documenti ufficiali:
AVOID defining a struct unless the type has all of the following characteristics:
- It logically represents a single value, similar to primitive types (int, double, etc.).
- It has an instance size under 16 bytes.
- It is immutable.
- It will not have to be boxed frequently.
Penso che i primi 2 punti siano per migliorare le prestazioni nello stack. Tuttavia, per quanto ho capito, structs
è meglio nello stack, ma non è peggiore sull'heap.
Il punto 3 posso ancora aderire. Potrebbe rendere il codice più pulito, potrebbe renderlo più complicato, ma non lo so ancora.
Il punto 4 riguarda anche i miglioramenti delle prestazioni, ma in realtà non ho bisogno di molte prestazioni. Anche se, a questo punto, sarebbe presto, l'ottimizzazione iniziale: non sto lavorando con i big data qui.
Con un nome del genere, voglio pensare che structs
sia esattamente la cosa da usare per le strutture di dati passivi orientate agli oggetti . La documentazione dei documenti ufficiali mi fa dubitare che, soprattutto, la limitazione delle dimensioni. Anche 2 stringhe per un indirizzo con 2 righe sarebbero già troppe.
La domanda
Esistono altri argomenti contro l'uso di strutture per queste strutture dati passive? O ho capito qualcosa di sbagliato?
Esempio
public struct EmployeeId // data structure (exposed data, no functions)
{
public string Value;
}
public struct Address // data structure
{
public string Line1;
public string Line2;
}
public struct Performance // data structure
{
public int Successes;
public int Failures;
}
public struct Employee : IEquatable<Employee>
// data structure
{
public EmployeeId Id:
public Address Address;
public Performance Performance;
public bool Equals(Employee employee)
{
return Id == employee.Id;
}
}
public class OfficialEmployeeRegistry // object (hidden data, exposed functions)
{
private Dictionary<EmployeeId, Employee> _employees;
public void Add(Employee employee)
{
_employees.Add(employee.Id, employee);
}
public List<Employee> GetPositivePerformers() {...}
}
public class SantaClause // object
{
private EmployeeRegistry _employeeRegistry;
private PresentSender _presentSender;
public void SendChristmasPresents()
{
List<Employee> goodEmployees = employeeRegistry.GetPositivePerformers();
foreach(Employee employee in goodEmployees)
{
_presentSender.SendPresent(employee.Address);
}
}
}
Tutti structs
in questo codice sono esempi di ciò che voglio fare. Ad esempio, ora possiamo ottenere le prestazioni di un dipendente da OfficialEmployeeRegistry
. Possiamo inviare tali dati a una classe di stampanti, ma se tale classe lo modifica nel processo, le voci in OfficialEmployeeRegistry
sono protette. I dati ufficiali di OfficialEmployee saranno manipolati da solo. Oh, e le strutture dovrebbero essere immutabili, ovviamente, ma sento che aggiungere un costruttore a ognuno di loro farebbe ingrossare questo post.
Reazione agli impegni
Hai bisogno di serializzazione dei dati?
No.
Sarà necessario passare da e verso funzioni / metodi?
Sì.
Verrà iterato e modificato su base abbastanza significativa?
No. Immagino che questo riguardi le prestazioni; ma la performance non è sicuramente un problema