Pergunta

Eu gosto do conceito de imutabilidade, mas às vezes me pergunto, quando uma aplicação não pretende ser paralelo, se deve evitar fazer coisas imutáveis?

Quando um aplicativo não é multi-threaded, você não está atormentado por problemas de estados compartilhados, certo?

Ou é imutabilidade um conceito como OOP que você utilize todo o caminho ou não? Excluindo os casos quando algo não deve ser baseada imutável sobre o uso / performance, etc.

Eu sou confrontado com esta questão ao escrever uma aplicação para mim, que é moderadamente grande (talvez como 1-2k linhas).

Foi útil?

Solução

Eu amo imutabilidade porque significa que eu não tenho que confiar em código de outros povos para não mexer com objetos eu espero ficar na mesma.

Quando você passar um objeto para outro componente, como um List<T>, você está à mercê do que aquele componente faz. Isto é especialmente importante quando você retornar coleções como propriedades.

public class Foo { 
  private List<Bar> _barList;
  public ICollection<Bar> BarList { get return _barList; } 
}

Não há nada que impeça um consumidor dessa classe de limpar a coleção debaixo de mim. Mesmo mudar o tipo de retorno para IEnumerable<Bar> não é inteiramente seguro. Não há nada que impeça algum pedaço de código mal escrito de lançar esta de volta para List<T> e chamando .Clear ().

No entanto, se eu realmente quero a coleção para ficar consistente eu poderia reescrevê-la como followis

public class Foo {
  private ImmutableCollection<Bar> _barList;
  public ImmutableCollection<Bar> BarList { get { return _barList; } }
}

Agora estou segura de ter que confiar em outro código de usar a minha classe incorretamente. Eles não podem mexer-se.

Outras dicas

Eu como a vantagem de imutabilidade que você precisa para validá-lo apenas uma vez - na criação de objeto. Isso é um grande bônus realmente.

Um dos grandes benefícios de imutabilidade é que não é preciso controlar a posse de objetos imutáveis. Eles só existirá enquanto ninguém precisa deles, e depois desaparecem no nada quando eles não são mais necessários. Enquanto estiver usando um coletor de lixo em muitos casos, significa que não é necessário escrever qualquer código expressamente lidar com a propriedade de objetos mutáveis ??(o maior exceção sendo aquelas que implementam IDisposable), em muitos casos, é muito difícil escrever código correto em que os objetos que têm estado mutável não tem um "dono" claramente definida. A confusão sobre quem possui o estado de objetos mutáveis ??podem ser uma fonte muito frequente de erros; ao usar objetos imutáveis ??(com exceção de alguns que implementar IDisposable) que geralmente se pode ignorar questões de propriedade.

Outro ponto a considerar é que é muito mais fácil raciocinar sobre uma referência mutável para um objeto semanticamente-imutável, ou uma referência imutável a um objeto mutável, que é para raciocinar sobre uma referência mutável para um objeto mutável. Se alguém tem uma referência mutável para um objetos mutáveis, que muitas vezes pode não ser claro se a abordagem correta para o estado de actualização é simplesmente transformar o objeto diretamente, ou copiar seu estado para um novo objeto, mutação isso, e atualizar a referência. Em alguns casos, haverá circunstâncias que exijam cada tipo de operação (como acontece com List<T>, que às vezes substitui uma matriz com um maior, mas geralmente faz atualizações in-place), mas tal abordagem só funciona se o tipo mantém controle exclusivo sobre mutável objetos em questão. É muitas vezes mais útil que quer ter uma referência imutável a um tipo mutável (no qual o código caso pode expor a referência, possivelmente através de um read-only invólucro, a outros objetos que querem um "live view" do seu estado), ou então têm um mutável referência a um objecto que é imutável ou, no mínimo, nunca será mutado durante o tempo de vida da referência.

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