Quais são as melhores práticas para eliminar gradualmente o código obsoleto?

9

Eu tenho a necessidade de eliminar gradualmente um método obsoleto. Estou ciente do [Obsolete]atributo. A Microsoft possui um guia de práticas recomendadas para fazer isso?

Aqui está o meu plano atual:

R. Eu não quero criar uma nova montagem porque os desenvolvedores precisariam adicionar uma nova referência aos seus projetos e espero receber muita tristeza do meu chefe e colegas de trabalho, se eles precisarem fazer isso. Também não mantemos várias versões de montagem. Nós usamos apenas a versão mais recente. Alterar essa prática exigiria alterar nosso processo de implantação, o que é um grande problema (é preciso ensinar as pessoas a fazer coisas com o TFS em vez do FinalBuilder e fazê-las desistir do FinalBuilder)

B. Marque o método antigo como obsoleto.

C. Como a implementação está mudando (não a assinatura do método), preciso renomear o método em vez de criar uma sobrecarga. Portanto, para conscientizar os usuários do método adequado, pretendo adicionar uma mensagem ao [Obsolete]atributo. Essa parte me incomoda, porque a única alteração que estou fazendo é separar o método da string de conexão. Mas, como não estou adicionando uma nova montagem, não vejo como contornar isso.

Resultado:

[Obsolete("Please don't use this anymore because it does not implement IMyDbProvider.  Use XXX instead.")];
        /// <summary>
        /// 
        /// </summary>
        /// <param name="settingName"></param>
        /// <returns></returns>
        public static Dictionary<string, Setting> ReadSettings(string settingName)
        {
            return ReadSettings(settingName, SomeGeneralClass.ConnectionString);
        }

        public Dictionary<string, Setting> ReadSettings2(string settingName)
        {
            return ReadSettings(settingName);// IMyDbProvider.ConnectionString private member added to class.  Probably have to make this an instance method.
        }
P.Brian.Mackey
fonte

Respostas:

5

A Microsoft usa o atributo [obsoleto] para informar aos desenvolvedores que o método, propriedade ou classe está obsoleta e pode ser alterada (ou não é suportada) em versões futuras.

Isso fornece pelo menos um ciclo de lançamento para notificar os usuários da sua API que o recurso está "desaparecendo" e remover referências a ela em versões futuras do software.

Quanto tempo você deixa o recurso original depende inteiramente de você. Se você deseja "encorajar fortemente" os desenvolvedores a usar seus novos recursos em relação aos antigos, você só precisa de um ciclo de lançamento adicional para removê-lo. Se você pretende ter compatibilidade permanente com versões anteriores, pode deixá-lo para sempre.

Como Brian aponta, se você está apenas alterando a implementação subjacente, mas não a assinatura do método, pode não ser necessário fazer nada disso.

Robert Harvey
fonte
A prática da Microsoft é geralmente remover uma coisa obsoleta no próximo grande lançamento. Por outro lado, o Java nunca remove coisas obsoletas - portanto, é com você.
Scott C Wilson
Não fazemos a versão de montagens além do nível do aplicativo (1 aplicativo gigante com muitas soluções). Combine isso com o fato de que o número de soluções que dependem de qualquer montagem é indefinido. Não consigo testar um aplicativo que não conheço. Mas, se eu fizer uma alteração que cause uma quebra de um aplicativo que eu não conheço ... bem, isso é culpa minha. Foi por isso que renomeei o método. Portanto, pelo que li até agora, não há melhor maneira de fazer isso.
usar o seguinte
4

Como a implementação está mudando (não a assinatura do método), preciso renomear o método em vez de criar uma sobrecarga.

Eu não entendo Se a implementação está mudando, mas a assinatura não está, por que você faria isso? Deixe o método "antigo" usar a implementação nova e aprimorada. Qualquer desenvolvedor que consome essa API estará revirando os olhos quando vir um método com a mesma assinatura exata criada e avisos de descontinuação em suas chamadas de método existentes. (Você consegue pensar em um momento em que isso aconteceu em uma API?)

Se você não tiver certeza se a alteração da implementação subjacente desse método funcionará, verifique o comportamento com testes de unidade antes e depois de alterar a implementação.

Brian
fonte
Esse é um ótimo ideal. A questão é que não temos chicotes de teste. Essa é outra questão que espero resolver. Portanto, como não há teste de integração, não posso fazer o que você recomenda. Existem muitas representações ainda não definidas que não serão testadas.
usar o seguinte código
A razão pela qual mencionei o teste é porque você claramente queria fazer isso, para que os consumidores da sua API fizessem o teste e o ajudassem a descobrir problemas entre as duas chamadas. Sua melhor opção parece ser lançar os desenvolvedores que usam seu código no fogo e fazê-los usar a nova implementação e espero que eles façam um controle de qualidade completo ou façam seus próprios testes.
brian
Eu estaria me jogando no fogo. Prefiro ficar com o código original que publiquei. Dessa forma, ninguém me liga às três da manhã, perguntando-se por que o código de produção quebrou. Em seguida, dependa dos desenvolvedores para resolver a obsolescência do código à medida que passam e reparam seus sinalizadores de aviso. Se eles não o consertarem nesse ponto, quando as cadeias de conexão começarem a falhar neles, será culpa deles por não reparar seus sinalizadores de aviso ... não os meus.
usar o seguinte código
Sempre que você escreve um novo código, corre o risco de apresentar problemas. Os testes permitem refatorar sem ter tanto medo. O medo é o assassino da mente. Além disso, você está apenas adiando o inevitável; eles adicionarão um "2" relutantemente às chamadas em algumas iterações a partir de agora e você receberá a mesma ligação se não funcionar.
brian