practices - convenciones de codigo c#
Preguntas sobre los estándares de codificación C#de Juval Lowy (8)
Aquí están algunas de mis reacciones de las cuales me atrevo a responderlas :)
1.13 Evite los nombres tipográficos completos. Utilice la instrucción "using" en su lugar. Estoy en desacuerdo. Ciertamente no está relacionado con el rendimiento. Puede llevar a una mejor legibilidad para tener var foo = new Foo()
lugar de var foo = new MyCompany.MyNamespace.Helpers.Xml.Foo()
pero aparte de eso, no.
2.19 Evite definir clases de excepción personalizadas Esto es un imho sin sentido. Debe evitar la creación de excepciones personalizadas que se derivan de ApplicationException, pero no hay nada de malo en las excepciones personalizadas (siempre que no vaya a reinventar las excepciones existentes).
2.29 Evite usar el operador condicional ternario No tengo idea de por qué sería una guía. He leído que no todas las personas lo usan y puede que no lo reconozcan, pero esa no es una razón válida para no usar un operador útil.
2.31 Evitar llamadas a funciones en sentencias condicionales booleanas. Asignar en variables locales y comprobarlas. Esto es simplemente un problema de legibilidad en mi opinión.
2.47 Evita las interfaces con un miembro. También estoy en desacuerdo aquí. Sin embargo, debe evitar las interfaces de ''marcador'' - interfaces sin marcador, pero que solo sirven el propósito de que algo es ''... ble''. Pero, un método en una interfaz me parece bien.
Disfruto y recomiendo altamente Juval Lowy''s - C # Coding Standard . Juval explícitamente evita las razones de cada directiva para mantener el estándar ajustado (ver el prefacio). Sin embargo, hay algunas directivas por las cuales me siento curioso en cuanto a la razón.
¿Cuál es el fundamento específico de las siguientes directivas del estándar C # de Lowy''s?
Esperemos que haya respuestas difíciles (no subjetivas) a estas.
1.13 Evite los nombres tipográficos completos. Utilice la instrucción "using" en su lugar.
¿Es este un problema de rendimiento? A veces solo necesito una instancia del nombre completo y agregar un uso parece pesado.
1.26 Utilice paréntesis vacíos en métodos anónimos sin parámetros. Omita el paréntesis solo si el método anónimo se podría haber utilizado en cualquier delegado.
En realidad estoy confundido por la segunda frase. Explicación con ejemplo (s) ayudaría, gracias.
2.19 Evite definir clases de excepción personalizadas
¿Cuáles son las consideraciones para minimizar sus números? (Luego da pautas si las define (en 2.20).)
2.29 Evitar el uso del operador condicional ternario.
¿Demasiado difícil de digerir para el lector u otras consideraciones?
2.31 Evitar llamadas a funciones en sentencias condicionales booleanas. Asignar en variables locales y comprobarlas.
No creo que haga esto, pero tengo curiosidad ... ¿por qué no?
2.47 Evita las interfaces con un miembro.
¿Porque siempre es / generalmente más preferible hacer qué? Un método de interfaces funciona cuando?
2.53 Prefiero usar una implementación de interfaz explícita
¿Por qué? Además, Jon Skeet no está de acuerdo aquí .
¡Gracias por adelantado! Robert
Con respecto a 1.13 (Evite los nombres de tipo completamente calificados. Use la instrucción "using" en su lugar):
Puede ser un poco más que legibilidad. Si tiene demasiados usos al principio del archivo, tiene una clase que está acoplada con clases de demasiados espacios de nombres.
La clase está gritando por refactorización. El uso de usos en lugar de nombres de clase completamente calificados le permite identificar clases tan estrechamente acopladas con mayor facilidad.
Este es mi mejor intento por las preguntas que has enumerado. Para los que realmente no puedo decir, he omitido.
1.13 Evite los nombres tipográficos completos. Utilice la instrucción "using" en su lugar.
Legibilidad. Debe ser más difícil leer el código cuando tiene que leer nombres de tipo totalmente calificados.
2.19 Evite definir clases de excepción personalizadas
El marco .NET viene con un buen conjunto de excepciones integradas en el sistema. A menos que la excepción que está modelando sea específica del dominio de negocios, probablemente podrá usar una de las clases de excepción existentes.
2.29 Evitar el uso del operador condicional ternario.
Creo que esto es muy probable porque él piensa que las personas pueden no entender al operador, pero no estoy de acuerdo.
2.47 Evita las interfaces con un miembro.
Él podría estar advirtiendo a la gente de construir interfaces que son demasiado delgadas. Sin embargo, realmente diría lo contrario, advirtiendo a las personas de hacer interfaces demasiado detalladas. Si alguna vez ha tenido que lidiar con ASP.NET MembershipProvider, sabe de lo que estoy hablando.
2.31 Evitar llamadas a funciones en sentencias condicionales booleanas. Asignar en variables locales y comprobarlas.
Un par de razones que se me ocurren aquí. Legibilidad. Puede hacer que las declaraciones condicionales sean difíciles de entender si está realizando llamadas a funciones en ellas. Además, es más difícil de depurar si no estás viendo.
2.53 Prefiero usar una implementación de interfaz explícita
Creo que su razonamiento aquí es por brevedad. Sin embargo, no estoy de acuerdo con esta evaluación. Creo que Jon es correcto, la interfaz implícita debería usarse cuando se pueda y explícita cuando sea apropiado.
Muchas de estas pautas se refieren a los "atributos de calidad" de un buen diseño de software (es decir, capacidad de mantenimiento, confiabilidad, reutilización, capacidad de prueba, capacidad de expansión, depuración, interoperabilidad y otras funciones que puede nombrar).
A menudo, las personas crean un código que funciona bien en el momento, pero puede que no sea la mejor opción cuando se consideran todos los atributos de calidad (en el sentido de "dónde puede ir este software en el futuro " o "alguien más tiene que usar este código también" ).
Por ejemplo:
2.29 Evitar el uso del operador condicional ternario.
No tengo ningún problema con las expresiones ternarias, per se, pero al escribir código como: int result = CheckMethod ()? OnTrueDoThis (): OnFalseDoThat () ... estás diciendo: "Tengo un condicional que, si es verdadero (o falso), puedes hacer una y solo una cosa ". Todo el constructo desalienta la capacidad de expansión . Debe recrear la construcción (con una sentencia if..else).
Similar...
2.31 Evitar llamadas a funciones en sentencias condicionales booleanas. Asignar en variables locales y comprobarlas.
Usted llamó a una función y esencialmente "descartó" los resultados para su uso posterior. Si esa información se necesita más adelante, la función tendrá que volver a llamarse o la estructura del código deberá volver a escribirse. También dificultaría la verificación o el registro de los resultados (para la depuración futura).
Disfrutar,
Robert c. Cartaino
Obviamente, no soy Juval, pero puedo probar esto
1.13 Evite los nombres tipográficos completos. Utilice la instrucción "using" en su lugar.
El rendimiento no puede ser el problema aquí. Estoy seguro de que el problema es la legibilidad.
1.26 Utilice paréntesis vacíos en métodos anónimos sin parámetros. Omita el paréntesis solo si el método anónimo se podría haber utilizado en cualquier delegado.
public delegate void Foo1();
public delegate void Foo2(int val);
public void Foo()
{
Foo1 first = delegate { Console.WriteLine("Hello world"); };
Foo2 second = delegate { Console.WriteLine("Hello world"); };
Foo1 third = delegate() { Console.WriteLine("Hello world"); };
Foo2 fourth = delegate() { Console.WriteLine("Hello world"); }; // does not compile
}
Sin los parens, el delegado anónimo se puede aplicar a cualquier delegado. Con los parens, estás siendo específico acerca de la firma del delegado. Prefiere la segunda sintaxis a menos que realmente necesites la flexibilidad.
2.19 Evite definir clases de excepción personalizadas
Una vez más, la legibilidad es el problema aquí. Las clases de excepción del marco son ricas y bien entendidas. Tenga cuidado al reemplazarlos.
2.29 Evitar el uso del operador condicional ternario.
Es una cosa de legibilidad y capacidad de expansión. Realmente no estoy de acuerdo, pero es una pelea religiosa estándar.
2.31 Evitar llamadas a funciones en sentencias condicionales booleanas. Asignar en variables locales y comprobarlas.
Parcialmente esto es legibilidad, y parcialmente es para facilitar la depuración. He empezado a asignar casi todo a las variables temporales para que luego se encuentren fácilmente en el depurador.
2.47 Evita las interfaces con un miembro.
"Evitar" es un poco como "preferir", él solo está diciendo que piense dos veces antes de hacerlo. Si solo tiene un miembro, ¿la interfaz realmente modela algo útil y completo en su diseño? Es bastante raro tener una clase con un solo miembro, piense seriamente en por qué su interfaz es diferente.
2.53 Prefiero usar una implementación de interfaz explícita
Esto es similar a la idea de usar el acceso menos público que puedas. Si su clase no necesita hacer pública la interfaz, entonces probablemente no debería. Esto va a diferir significativamente según su diseño, obviamente, pero dado que la mayoría de las personas simplemente hacen que la interfaz sea implícita sin pensarlo realmente, es un consejo que vale la pena considerar.
1.26 es sobre la sintaxis del delegate { }
pre-lambda.
// #1 Empty parenthesis on parameterless-anonymous methods would be:
delegate() { }
// #2 ... anonymous method could have been used on any delegate, is:
delegate { }
Recuerde, este último se puede asignar a cualquier delegado, independientemente de sus parámetros. El delegado simplemente los ignora utilizando algunos trucos del compilador.
Si define un delegado que no toma parámetros, dígalo explícitamente utilizando # 1. No "deje fuera el paréntesis porque su delegado no toma ningún parámetro de todos modos".
2.29 Evite utilizar el operador condicional ternario No tengo problemas con los usos "simples" del operador ternario, pero he recomendado su uso de forma anidada:
// This is fine
x := (conditionA) ? true_resultA : false_resultA;
// This would probably be clearer using if-then-elseif
x := (conditionA) ?
((conditionA1) ? true_resultA1 : (condition2) ? true_result2 : false_result2) :
((conditionA2) ? true_resultA2 : false_resultA2);
2.29 operador ternario
Para empezar, si comienza a utilizar el operador ternario, debe haber una razón para el uso del operador ternario en un uso regular si no lo hace. Observar
if (x == 0) {...} else{...} //A set of statements demand a regular If-then-else
//A simple assignment can be handled by the ternary operator
y = (x == 0)? 1 : 0 //this is readable and how it should be used
(x==0)? callSomething() : callSomethingElse() //this is NOT how it should be used
La declaración ternaria está destinada a devolver uno de dos valores dependiendo del condicional que esté evaluando. Esto es extremadamente útil al hacer FP. Para las declaraciones de llamada que no devuelven un valor, debe volver a if-then-else.