Feel Good.

29 марта 2010

Obsolete код

Наверняка Вы сталкивались с ситуацией, когда Ваш код устаревал и, например, если Вы пишите код в команде, то как проще всего сказать другим разработчикам, что Ваш код устарел? Да, просто пометьте его атрибутом Obsolete.

Рассмотрим простой пример как это работает. Обычно подобное возникает в двух ситуациях:

  1. Пусть в самом начале класс Example1 содержал только метод Old(), которым все успешно пользовались, спустя какое-то время, Вы понимаете, что скорость работы метода Old() довольно низкая, поэтому решаете реализовать новую версию старого метода - метод New(), который делает тоже самое, но гораздо быстрее. Конечно, в качестве совместимости, вы обязаны оставить метод Old() и New().
  2. Эта ситуация очень похожа на предыдущую, у нас есть старый метод VeryOld() и новый New(), но с одним отличием, метод VeryOld() настолько устарел, что использование его стало недопустимым. Это означает, что метод VeryOld() подлежит удалению из класса Example2.
Разумеется, другие разработчики пока не догадываются о Ваших изменениях, поэтому нужно как-то сообщить им об этом. Наиболее удобное решение, это использование атрибута Obsolete. Приведу простейшие примеры: для первого случая класс Example1 и Example2 для второго:


class Example1

{

    /// <summary>

    /// Данный метод использовать можно, но не рекомендуется.

    /// </summary>

    [Obsolete("Используй New()")]

    public void Old() { }

 

    /// <summary>

    /// Свежая версия метода Old().

    /// </summary>

    public void New() { }

}

 

class Example2

{

    /// <summary>

    /// Данный метод использовать нельзя.

    /// </summary>

    [Obsolete("Используйте New()", true)]

    public void VeryOld() { }

 

    /// <summary>

    /// Заменяющая версия метода VeryOld().

    /// </summary>

    public void New() { }

}


После чего, во время компиляции кода, где будет происходить использование устаревших методов будет возникать предупреждение (warning) компиляции с текстом предупреждения:

Example1 e1 = new Example1();

e1.New(); // Без предупреждений и ошибок.

e1.Old(); // С предупреждением "Используй New()".


или ошибка (error) компиляции тоже с текстом предупреждения:

Example2 e2 = new Example2();

e2.New();        // Без предупреждений и ошибок.

e2.VeryOld();    // Выдаст ошибку компиляции с сообщением "Используйте New()".


Это и есть основное предназначение атрибута Obsolete. Но существует и другой интересный способ использования данного атрибута, до тех пор, пока в .NET не будет атрибута "Этот код нуждается в рефакторинге":

[Obsolete("Нуждается в рефакторинге.")]

public class RefactoringAttribute : Attribute { }


и использовать этот атрибут в качестве маркера кода, который нужно отрефакторить:

class Example3

{

    /// <summary>

    /// Метод нуждающийся в рефакторинге.

    /// При компиляции, будет предупреждение.

    /// </summary>

    [Refactoring]

    public void Ugly() { }

 

 

    /// <summary>

    /// Класс который нуждается в рефакторинге.

    /// При компиляции, будет предупреждение.

    /// </summary>

    [Refactoring]

    class UglyClass { }

}


Причем в самом коде, где мы используем ugly-методы никаких предупреждений нет, только на уровне описания.

Example3 e3 = new Example3();

e3.Ugly(); // Здесь без предупреждений и ошибок.

10 комментариев:

  1. Хорошая статья! Спасибо.
    Мне только один момент непонятен (я просто не разбирался в пользовательских атрибутах, поэтому просто скажите, правильно ли я догадался): когда мы пишем
    [Obsolete("Нуждается в рефакторинге.")]
    public class RefactoringAttribute : Attribute { }

    То такая запись автоматически дает нам атрибут [Refactoring]?

    ОтветитьУдалить
  2. @Andrey Stukalin

    Спасибо за отзыв. Да, если класс RefactoringAttribute доступен (см. пространство имен), то можно использовать [Refactoring] или [RefactoringAttribute] - это одно и то же.

    ОтветитьУдалить
  3. Спасибо! Буду использовать:)

    ОтветитьУдалить
  4. Как советы начинающим или мысли чайника вслух пойдёт, но не больше. Во втором случае проще пользовать #warning и вставлять его куда угодно (да хоть среди комментариев)

    ОтветитьУдалить
  5. Хорошая идея. Приму на вооружение.

    ОтветитьУдалить
  6. спасибо за статью)))

    ОтветитьУдалить
  7. Использование вашего атрибута Refactoring очень сомнительное, если честно.

    ОтветитьУдалить
  8. @Сергей Звездин

    Это потому что мы ввели его искусственным образом.

    ОтветитьУдалить
  9. Согласен с Сергеем Звездиным. Я бы тоже применил лучше препроцессор #warning или комментарий //TODO: Refactor this

    ОтветитьУдалить