Pergunta

Como você formatar seu try..catch.finally blocos? Especialmente quando apenas envolvê-la em torno de uma pequena quantidade de código, ele sopra tudo e torna o código muito ilegível e sem graça na minha opinião.

Tais como:

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

Estas 7 linhas de código transformado em uma confusão 16-linha.

Todas as sugestões sobre melhor try..catch..finally formatação?

Foi útil?

Solução

Na verdade, este lê muito bem para mim. Se o seu código real se parece muito com isso, então eu realmente não se preocupar com isso. É muito claro o que está acontecendo.

Se o seu código real é mais complexa, em seguida, considere quebrar os blocos em métodos bem-nomeados.

Outras dicas

Você pode usar um bloco using em vez de um Dispose() explícito, ou então você probabilidade tem que verificar para nulo antes de descartá-lo, blocos using faz isso para você. infelizmente, faz aumentar nidificação = /

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

Bem, eu acho que é apenas multa. Alguns isso fica intot ele encaracolado debate colocação cinta. Você poderia fazer isso:

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

Eu prefiro que você tem no entanto. No entanto, você pode querer considerar rever o seu código só para ter uma instrução de retorno. Acho que é um pouco melhor design.

Eu formatar o código com os suportes na mesma linha:

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

I preferem adicionar linhas em branco se quiser mais espaço. Que também funciona como um separador entre os blocos lógicos de código.

Você pode pensar em recipientes (fábricas muito inteligentes) e conselhos (para lidar com todos os detalhes confusos).

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.

Você pode ver isso, em código, 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
}

Chegando-se com a classe interceptor acontece apenas uma vez. Registrar cada interceptor e classe de serviço também acontece apenas uma vez. Configurando o recipiente (muito inteligente de fábrica) é certamente complicado.

No entanto, cada lugar em seu código que tem de usar o objeto de serviço, e para incorporar esse uso dentro complicadas e confusas detalhes de infraestrutura, como a manipulação de exceção e exploração madeireira, ficou muito limpo e muito simples. Há apenas uma CreateContainer, mas há centenas de GottaGoDoSomethings, então isso é um monte de fácil à custa de um pouco de complicado.

(Notas:. O exemplo de código usa a estrutura do recipiente Autofac eo quadro interceptor Castelo Estou ciente de que este é um exemplo do padrão de serviços de localização, não o padrão de dependência de injecção, mas o ponto era ilustrar interceptores e registá-los com um recipiente, não para ilustrar a dependência de injecção.)

espaço em branco. No mínimo eu sempre coloco uma linha de espaços em branco antes de cada instrução de retorno e entre "fazer coisas" e "criação de variáveis" seções de código.

try
{
     MyService service = new Service();

     service.DoSomething();

     return something;

 }
catch (Exception ex)
{
     LogSomething();

     return somethingElse;

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

muito melhor.

Eu acho que sua formatação lê muito bem. Minha sugestão seria apenas para usar a instrução catch com moderação. usá-lo somente quando você realmente precisa para pegar alguma coisa. Caso contrário, você pode deixar que outras partes do programa lidar com a exceção. Toda a "falhar cedo" conceito.

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

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

Pessoalmente, eu tendem a seguir o estilo anterior no meu código ... Ele dá espaço para fazer comentários, e mostra o fluxo de minha lógica melhor.

Eu tenho um widescreen que eu transformar em que é lado, de modo que o espaço em branco permite que as várias colunas para alinhar bem e não me machucar que muito do que porque eu tenho tanta tela imobiliário como é ...

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();

}

Eu também, como o que você tinha originalmente. linhas físicas em um arquivo .cs não custa nada, e não alterar o código de saída final. Portanto, use tudo o que você precisa, a fim de proporcionar a melhor legibilidade para você ou sua equipe.

Na verdade, você deve realmente tentar usar mais linhas do que os 16 que você mostra aqui quando você código, adicionando comentários para si mesmo ou aos outros.

Ao adicionar

// a comment that says what's going on

com freqüência, você pode melhor se lembrar o que este Try.Catch é suposto estar a fazer quando você voltar a ele após 6 meses.

Eu sempre tento e refatorar para fora todos os meus blocos try catch e encapsular-los em seu próprio método.

Isso sempre parece fazer tudo o mais legível, além disso, é uma boa prática de programação para fazer seus métodos só fazer uma coisa. As probabilidades são de que, se você tiver o código acima e abaixo de seu try-catch-finally, então você está fazendo mais de uma coisa.

Se você realmente quer se livrar do obrigatório e formatação feio (sim eu concordo: p)

ir para Aspect Oriented Programação , e você obterá o try ... catch ... finally incorporado para livre em sua montagem e de exceção registrados automaticamente.

Tente PostSharp ou Spring.Net

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top