Quando consertar algo que está “errado” mas funciona bem

5

Versão resumida:

Eu escrevi um código que não é feito "da maneira certa" porque, quando eu escrevi, não sabia como fazer isso. Agora que sei como fazer "o caminho certo", como decido como consertar isso?

Versão mais longa com detalhes:

java.util.DecimalFormat não é seguro para Threads. Eu tenho o que é essencialmente um objeto Description imutável que é usado em todo o meu código em muitos threads diferentes. Para corrigir esse problema, criei uma classe de wrapper SynchronizedFormatter que basicamente apenas bloqueia os métodos de DecimalFormat que eu uso.

O jeito certo de fazer isso é usar um ThreadLocal . Eu nem sabia o que era quando escrevi o código pela primeira vez. Vale a pena consertar? A versão synchronized funciona bem. Como eu decido sobre isso em específico e sobre esta situação de forma mais geral?

Além disso, devo mencionar que preciso fazer outras alterações nessa classe por razões mais importantes do que "Eu fiz um pouco errado na primeira vez". Isso é o que me fez pensar - se eu estou mexendo nessa classe de qualquer maneira, talvez eu deva consertar essas outras coisas que estão na minha lista de desejos. Mas então eu temo uma ladeira escorregadia ...

Esta não é uma duplicata de Quando refatorar porque Reforçar significa :

Improving a computer program by reorganising its internal structure without altering its external behaviour.

Esta questão fala sobre realmente modificar o comportamento do código (por exemplo, usando synchronized vs. ThreadLocal . Talvez não deva ser marcado .

    
por durron597 28.01.2015 / 19:48
fonte

2 respostas

4

Uma correção simples seria substituir os componentes internos do wrapper para usar o Threadlocal.

Portanto, o format() é alterado de:

private DecimalFormat format = new ...;

private final Object lock = new Object();

public String format(double value){
    synchronized(lock) {
        return format.format(value);
    }
}

para

private ThreadLocal<DecimalFormat> format = new ThreadLocal(){
    public DecimalFormat initialValue(){
        return new ...;
    }
};

public String format(double value){
    return threadLocalFormat.get().format(value);
}

Isso tem a vantagem de que a nova implementação é threadsafe sem o custo de sincronizar as chamadas e a interface para todas as outras classes permanece a mesma. Assim, a mudança é localizada em apenas uma classe.

    
por 28.01.2015 / 19:58
fonte
1

Tudo se resume a gerenciamento de riscos e intuição. Tente estimar o seguinte:

  • Qual é o custo do erro, pois ele está no código agora. Isso causa custos recorrentes? Ou custa na forma de um risco que pode se transformar em um bug no futuro? Qual é o custo e a probabilidade desse bug?

  • Qual é o custo de consertar isso agora: risco de quebrar algo + o tempo que você (e o resto da equipe) precisa.

Por fim, faça este cálculo para NOW e por algum tempo no futuro. Alguns tipos de problemas não são um problema tão grande no momento, mas podem se transformar em uma bagunça feia daqui a um ano, mas também são muito mais caros de se consertar. Você provavelmente quer corrigi-los agora.

Na maioria dos projetos, você não fará isso com números reais, mas com base em seus sentimentos.

Eu geralmente tento reservar algum tempo para esse tipo de manutenção de código, e usá-lo para os problemas com o maior retorno por investimento, e ajustar o tempo total para que minha base de código permaneça em constante e alta qualidade. / p>     

por 29.01.2015 / 12:41
fonte