2009-06-02 10 views
6

¿Cómo está formateando sus bloques try..catch.finally? Especialmente cuando solo lo envuelvo en una pequeña cantidad de código, lo destruye todo y hace que el código sea bastante ilegible y antiestético en mi opinión.Formateo de difícil de leer try..catch..finally blocks?

Tales como:

try 
{ 
    MyService service = new Service(); 
    service.DoSomething(); 
    return something; 
} 
catch (Exception ex) 
{ 
    LogSomething(); 
    return somethingElse; 
} 
finally 
{ 
    MarkAsComplete(); 
    service.Dispose(); 
} 

Estos 7 líneas de código se convirtió en un lío 16 de línea.

Cualquier sugerencia sobre mejor intento ... captura ... ¿formato final?

+4

Ya tiene el formato ideal. –

Respuesta

6

En realidad, esto me parece muy bien. Si su código actual se parece mucho a esto, entonces realmente no me preocuparía. Está MUY claro lo que está sucediendo.

Si su código real es más complejo, entonces considere dividir los bloques en métodos bien nombrados.

+1

Cualquiera que sea su postura sobre la ubicación del bracket, o espacios en blanco, o cantidades de sangría, siempre debe romper bloques complejos de código en métodos bien nombrados. http: // coliveira.net/2009/05/day-2-write-short-methods/ –

1

Espacio en blanco. Como mínimo, siempre pongo una línea de espacios en blanco antes de cada declaración de devolución y entre las secciones de código "hacer cosas" y "crear variables".

try 
{ 
    MyService service = new Service(); 

    service.DoSomething(); 

    return something; 

} 
catch (Exception ex) 
{ 
    LogSomething(); 

    return somethingElse; 

} 
finally 
{ 
    MarkAsComplete(); 
    service.Dispose(); 
} 

mucho mejor.

+0

Aunque no me apego a esto el 100% del tiempo, tiendo a adherirme también a este formato. –

+2

Diría que funciona cuando tienes un montón de líneas, pero en este caso, parece demasiado escaso. – Neil

+0

Para este caso, puede ser. Personalmente trato de mantener la coherencia en mi estilo de codificación y hacerlo independientemente de si hay 3 líneas o 10 líneas en un bloque de prueba/captura. –

4

Bueno, creo que está bien. Algo de esto llega después del debate sobre la colocación de llaves. Usted podría hacer esto:

try { 
    // 
} catch(Exception ex) { 
    // 
} finally { 
    // 
} 

Yo prefiero lo que tiene. Sin embargo, es posible que desee considerar la revisión de su código para que solo tenga una declaración de devolución. Me parece que es un poco mejor diseño.

+1

¡Bienvenido a The One True Brace Style! – Richard

2

que formatear el código con los soportes en la misma línea:

try { 
    MyService service = new Service(); 
    service.DoSomething(); 
    return something; 
} catch (Exception ex) { 
    LogSomething(); 
    return somethingElse; 
} finally { 
    MarkAsComplete(); 
    service.Dispose(); 
} 

prefiero añadir líneas en blanco si quiero más espaciado. Eso también funciona como un separador entre bloques lógicos de código.

+0

Creo que esto empeora las cosas :-) – hdoghmen

0

Creo que su formateo también es muy buena. Mi sugerencia sería usar solo la declaración catch con moderación. Solo úsalo cuando realmente necesites atrapar algo. De lo contrario, puede dejar que otras partes del programa manejen la excepción. Todo el concepto de "falla temprano".

try 
{ 
    //do something that may throw an exception. 
} 
finally 
{ 
    //handle clean up. 
} 

//let a method further down the stack handle the exception. 
0

Personalmente, tiendo a seguir el estilo anterior en mi código ... Se da espacio para hacer comentarios, y muestra el flujo de mi lógica mejor.

Tengo una pantalla ancha que enciendo de su lado, por lo que el espacio en blanco permite que las distintas columnas se alineen bien y no me duele tanto porque tengo tanto espacio en la pantalla como es ...

try { // getting a service 

    MyService service = new Service(); 
    service.DoSomething(); 

    return something; 

} 

catch (Exception ex) { // the fact that a service might be full/timedout 

    LogSomething(); 

    return somethingElse; 

} 

finally { // remove any resources the service may still hold. 

    MarkAsComplete(); 
    service.Dispose(); 

} 
1

Puede pensar en contenedores (fábricas muy inteligentes) y consejos (para manejar todos los detalles desordenados).

Dear Mr. Container Sir, 
Whenever I request from you an instance object of the interface ISomething, 
    please construct for me an instance of the concrete class SomethingImpl; 
    in addition, please see to it (however you do it) that, whenever I call a 
    method on this instance, it is wrapped within a complicated and messy try- 
    catch-finally which logs exceptions and mark calls as completed. That way, 
    all I have to do is write the business logic that goes into the SomethingImpl 
    and I don't have to worry about all the messy infrastuctural details. 
Sincerely, 
Mr. Agile. 

Es posible que vea esto, en clave, como:

//a class that knows how to take care of the messy infrastructure details 
public class MyMessyInterceptor : IInterceptor { 
    public void Intercept(IInvocation invocation) { 
     //handle the messy details of continuing with the method-invocation, 
     //but within a try-catch-finally that includes exception handling and 
     //call logging. 
    } 
} 

//a function that will configure a container (very smart factory) 
public IContainer CreateContainer() { 
    var builder = new ContainerBuilder(); 

    //tell the container-builder about the interceptor 
    builder 
     .Register(c => new MyMessyInterceptor()) 
     .Named("keep-my-code-clean") 
    ; 

    //tell the container what to do when you ask it for a ISomething 
    builder 
     .Register<SomethingImpl>() 
     .As<ISomething>() 
     .InterceptedBy("keep-my-code-clean") 
    ; 

    return builder.BuildContainer(); 
} 

//some function out there in your code somewhere that needs to make a 
//service call; there's hundreds of functions out there just like this 
//in your code, and they all just got much simpler 
public object GottaGoDoSomething() { 
    //find the container 
    var container = GetTheSingletonContainerObject(); 
    //ask for an instance of ISomething - it knows to provide a 
    //SomethingImpl wrapped in an interceptor that takes care of all 
    //the logging and exception handling 
    var something = container.resolve<ISomething>(); 
    //call the big method 
    return something.DoSomething(); 
    //magically (not really), the exception handling and logging are 
    //already taken care of 
} 

El subir con la clase de interceptor sucede sólo una vez. El registro de cada interceptor y clase de servicio también ocurre solo una vez.Configurar el contenedor (fábrica muy inteligente) es ciertamente complicado.

Sin embargo, cada lugar en su código que tiene que usar el objeto de servicio, y tiene que incorporar ese uso dentro de detalles de infraestructura complicados y desordenados como el manejo y registro de excepciones, acaba de ser muy limpio y sin complicaciones. Solo hay un CreateContainer, pero hay cientos de GottaGoDoSomething s, así que es mucho más fácil a costa de un poco complicado.

(Notas: El ejemplo del código utiliza el marco del contenedor Autofac y el marco del interceptor Castle. Soy consciente de que este es un ejemplo del patrón de ubicación del servicio, no el patrón de inyección de dependencia, pero el punto era ilustrar interceptores y registrarlos con un contenedor, no para ilustrar la inyección de dependencia.)

0

Yo también, como lo que originalmente tenía. Las líneas físicas en un archivo .cs no le cuestan nada, y no cambian el código de salida final. Por lo tanto, use todo lo que necesite para proporcionar la mejor legibilidad para usted o su equipo.

De hecho, en realidad debería tratar de usar más líneas que las 16 que muestra aquí cuando codifica, agregando comentarios para usted u otros.

Mediante la adición de

// a comment that says what's going on 

con frecuencia, puede recordar mejor a ti mismo lo que se supone que esto Try.Catch a hacer cuando vuelva a ella después de 6 meses.

4

puede usar un bloque using en lugar de un Dispose() explícito, o si no es probable que tenga que verificar el nulo antes de eliminarlo, using bloques lo hace por usted. lamentablemente lo hace aumento de anidación =/

try 
{ 
    using(MyService service = new MyService()) 
    { 
     service.DoSomething(); 
     return something; 
    } 
} 
catch (SpecificException ex) 
{ 
    LogSomething(ex); 
    return somethingElse; 
} 
finally 
{ 
    MarkAsComplete(); 
} 
+0

No hay "desafortunadamente" al respecto. El bloque 'using' es definitivamente el método preferido para eliminar un recurso después * de * it para una sección de código. –

0

Siempre trato de refactorizar todos mis bloques catch try y encapsular en su propio método.

Esto siempre parece hacer que todo sea más legible, además de que es una buena práctica de programación hacer que sus métodos solo hagan una cosa. Las probabilidades son que si tiene un código por encima y por debajo de su declaración try-catch-finally, entonces está haciendo más de una cosa.

0

Si realmente quiere deshacerse de la obligatoria pero fea formato (sí estoy de acuerdo: p)

van para Programación Orientada a Aspectos, y obtendrá el try ... catch ... finalmente incrustado gratis en su ensamblaje y la excepción se registra automáticamente.

Trate PostSharp o Spring.Net

Cuestiones relacionadas