Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
A menudo, varios algoritmos o implementaciones pueden resolver correctamente la misma tarea. El código que eliges comunica un diseño. Los desarrolladores y agentes de codificación que leen el código usan su estructura para deducir su intención: lo que necesita cada operación, dónde pertenece y cuándo se ejecuta.
Tip
Este artículo forma parte de la sección Aspectos básicos para desarrolladores que conocen expresiones, instrucciones y métodos básicos de C#. Si no está familiarizado con la programación, comience primero con los tutoriales de introducción .
En esta sección se comparan los enfoques válidos para algoritmos y se explican las diferencias sutiles en su comportamiento y cómo los lectores los interpretan. Combinará elementos de lenguaje conocidos, como tipos, expresiones, instrucciones y métodos, y elegirá formas que comuniquen el diseño que pretende.
Comparar el comportamiento y la intención de diseño
Antes de elegir una implementación, considere cómo lo usará otro código. Ese código es el llamador: proporciona entradas, invoca la operación y usa los resultados. ¿Necesita un resultado completado inmediatamente o puede procesar valores de uno en uno? ¿Es una función auxiliar parte solo de esta operación, o también la usarán otras operaciones? Estas preguntas le ayudan a comparar tanto el comportamiento que necesita como el diseño que el código comunica.
Una breve operación integrada muestra a los lectores los pasos en el punto de uso. Por ejemplo, Where(task => task.Priority > 3) hace que la regla de filtrado sea visible inmediatamente. Una función auxiliar con nombre, como en Where(IsUrgent), enfatiza el propósito de la regla y permite a los lectores inspeccionar sus detalles por separado. Elija en función de si los pasos o su propósito explican mejor el código circundante.
Dónde declara un asistente comunica su ámbito previsto. Una función local dentro ShowDashboard indica que la función auxiliar pertenece a esa operación e impide que otros miembros la llamen. Un método privado en el tipo contenedor hace que el método auxiliar esté disponible para otros miembros, lo que sugiere que prevé reutilizarlo en otro lugar del tipo. Ambos pueden organizar el mismo cálculo, pero llevan a los lectores a diferentes expectativas sobre su rol.
Cómo se proporcionan las entradas de un asistente comunica sus dependencias. Pasar un límite como parámetro, como IsUrgent(task, minimumPriority), hace que esa entrada sea visible en cada llamada. En su lugar, una función local o lambda puede capturarlaminimumPriority, usando la variable de su ámbito circundante sin recibirla como argumento. Capture conecta el auxiliar al contexto de la operación contenedora; los parámetros explícitos facilitan la identificación de los datos proporcionados. Use una static función local o lambda cuando desee garantizar que no capture el estado circundante.
La forma de devolver los resultados indica cuándo se realiza el trabajo. Un método que crea y devuelve una colección completa ese trabajo antes de que el código que realiza la llamada reciba la colección. Un iterador genera elementos a medida que quien llama los solicita, por lo que quien llama puede detenerse antes de que se generen todos los elementos. Ambos pueden producir los mismos valores, pero quienes llaman deben comprender si reciben resultados completados o una secuencia cuyo cálculo aún está pendiente.
Para cada opción, identifique primero el comportamiento que necesita el código que realiza la llamada. A continuación, tenga en cuenta lo que otro desarrollador o agente de codificación deducirá del nombre, el ámbito, las entradas y el resultado. Elija una forma que haga que esas expectativas coincidan con el diseño y explique un comportamiento importante que la forma del código por sí sola no revela. El objetivo es elegir deliberadamente entre alternativas válidas, no aplicar una forma en todas partes.
Leer opciones de diseño en un ejemplo
En el ejemplo siguiente se muestra cómo varias opciones comunican diferentes partes de un diseño. Muestra las tareas urgentes y listas para iniciarse.
ProjectTask contiene el título, la prioridad y el estado de bloqueo de una tarea.
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);
Cada opción mantiene clara una parte diferente del trabajo:
- La expresión lambda pasada a
Wherecoloca una regla de prioridad corta junto a la operación que la usa. - La función local
FormatTaskda nombre a un paso de formato que solo pertenece aShowDashboard. - El iterador
ReadyTaskspermite al código llamador consumir tareas listas sin crear una colección intermedia. - El
foreachbucle hace que la acción final, la escritura de cada resultado, sea explícita.
Para la comparación, Where(static task => !task.IsBlocked) podría reemplazar a ReadyTasks porque esta prueba de preparación es un filtro simple. Ambas formas aplazan la aplicación del filtro hasta la enumeración. La expresión lambda coloca la regla en el sitio de llamada; ReadyTasks proporciona un nombre a la regla. Elija entre ellos en función de la información que ayude a los lectores a comprender a la persona que llama.
Los artículos que siguen usan comparaciones como estas para explicar cuándo encaja cada enfoque y qué pueden deducir los lectores de su elección.