Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Spesso più algoritmi o implementazioni possono risolvere correttamente la stessa attività. Il codice scelto comunica una progettazione. Gli sviluppatori e gli agenti di codifica che leggono il codice usano la struttura per dedurre la finalità: quali sono le esigenze di ogni operazione, dove appartiene e quando viene eseguita.
Tip
Questo articolo fa parte della sezione Nozioni fondamentali per gli sviluppatori che conoscono espressioni, istruzioni e metodi C# di base. Se non si ha familiarità con la programmazione, iniziare prima con le esercitazioni introduttive .
In questa sezione vengono confrontati gli approcci validi agli algoritmi e vengono illustrate le piccole differenze nel comportamento e il modo in cui i lettori li interpretano. Si combinano elementi del linguaggio familiari, ad esempio tipi, espressioni, istruzioni e metodi, e si scelgono moduli che comunicano la progettazione desiderata.
Confrontare il comportamento e la finalità di progettazione
Prima di scegliere un'implementazione, valutare il modo in cui verrà usato da un altro codice. Tale codice è il chiamante: fornisce input, richiama l'operazione e usa i risultati. È necessario un risultato completato immediatamente o può elaborare i valori uno alla volta? Un helper fa parte di questa operazione da solo o lo userà anche altre operazioni? Queste domande consentono di confrontare sia il comportamento necessario che la progettazione del codice comunica.
Un'operazione inline breve mostra i passaggi da eseguire al momento dell'utilizzo. Ad esempio, Where(task => task.Priority > 3) rende immediatamente visibile la regola di filtro. Un helper denominato, come in Where(IsUrgent), enfatizza lo scopo della regola e consente ai lettori di esaminare i dettagli separatamente. Scegliere in base al fatto che i passaggi o il loro scopo spieghino meglio il codice circostante.
Dove si dichiara un helper comunica l'ambito previsto. Una funzione locale all'interno ShowDashboard indica che l'helper appartiene a tale operazione e impedisce ad altri membri di chiamarlo. Un metodo privato sul tipo contenitore rende disponibile l'helper ad altri membri, suggerendo di riutilizzare altrove nel tipo. Entrambi possono organizzare lo stesso calcolo, ma portano i lettori a aspettative diverse sul suo ruolo.
La modalità di fornitura degli input di un helper comunica le relative dipendenze. Il passaggio di un limite come parametro, ad esempio IsUrgent(task, minimumPriority), rende l'input visibile a ogni chiamata. Una funzione locale o lambda può invece acquisireminimumPriority, usando la variabile dall'ambito circostante senza riceverla come argomento. Capture connette l'helper al contesto dell'operazione contenitore; I parametri espliciti semplificano l'identificazione dei dati forniti. Usare una static funzione locale o un'espressione lambda quando si vuole imporre che non acquisisca lo stato circostante.
La modalità di restituzione dei risultati comunica quando si verifica il lavoro. Metodo che compila e restituisce una raccolta completata prima che il chiamante riceva la raccolta. Un iteratore produce elementi quando il chiamante li richiede, in modo che il chiamante possa arrestarsi prima che vengano generati tutti gli elementi. Entrambi possono produrre gli stessi valori, ma i chiamanti devono capire se ricevono risultati completati o una sequenza la cui calcolo è ancora in anticipo.
Per ogni scelta, identificare innanzitutto il comportamento necessario al codice chiamante. Si consideri quindi quale altro sviluppatore o agente di codifica dedurrà dal nome, dall'ambito, dagli input e dai risultati. Scegliere un modulo che soddisfi le aspettative della progettazione e spiegare un comportamento importante che la forma del codice da sola non rivela. L'obiettivo è fare una scelta deliberata tra alternative valide, non applicare un modulo ovunque.
Leggere le scelte di progettazione in un esempio
Nell'esempio seguente viene illustrato il modo in cui diverse scelte comunicano parti diverse di una progettazione. Visualizza le attività urgenti e pronte per l'avvio. Un ProjectTask oggetto contiene il titolo, la priorità e lo stato bloccato di un'attività.
var tasks = new[]
{
new ProjectTask("Confirm venue", Priority: 3, IsBlocked: false),
new ProjectTask("Print badges", Priority: 2, IsBlocked: true),
new ProjectTask("Test microphones", Priority: 2, IsBlocked: false),
};
ShowDashboard("Community meetup", tasks, minimumPriority: 2);
static void ShowDashboard(
string projectName,
IEnumerable<ProjectTask> tasks,
int minimumPriority)
{
var urgentTasks = tasks.Where(
task => task.Priority >= minimumPriority);
foreach (ProjectTask task in ReadyTasks(urgentTasks))
{
Console.WriteLine(FormatTask(task));
}
string FormatTask(ProjectTask task) =>
$"{projectName}: {task.Title}";
}
static IEnumerable<ProjectTask> ReadyTasks(
IEnumerable<ProjectTask> tasks)
{
foreach (ProjectTask task in tasks)
{
if (!task.IsBlocked)
{
yield return task;
}
}
}
record ProjectTask(string Title, int Priority, bool IsBlocked);
Ogni scelta mantiene chiara una parte diversa del lavoro:
- L'espressione lambda passata a
Whereinserisce una regola di priorità breve accanto all'operazione che la usa. - La funzione
FormatTasklocale assegna un nome a un passaggio di formattazione che appartiene solo aShowDashboard. - L'iteratore
ReadyTasksconsente ai chiamanti di utilizzare attività pronte senza creare una raccolta intermedia. - Il
foreachciclo rende esplicita l'azione finale, scrivendo ogni risultato.
Per il confronto, Where(static task => !task.IsBlocked) potrebbe sostituire ReadyTasks perché questo test di idoneità è un filtro semplice. Entrambi i moduli rinviano il filtro fino all'enumerazione. L'espressione lambda inserisce la regola nel sito di chiamata; ReadyTasks assegna alla regola un nome. Scegliere tra di essi in base alle informazioni che consentono ai lettori di comprendere il chiamante.
Gli articoli che seguono usano confronti come questi per spiegare quando ogni approccio si adatta e quali lettori possono dedurre dalla propria scelta.