Как сделать рефакторинг кода на C#

Приветствую всех, сегодня мы рассмотрим что такое рефакторинг на практике. Рефакторинг- своего рода перепроектирования кода программы, уменьшив ее в объеме но не изменив ее функциональности, порой после рефакторинга код программы может сократиться в десятки раз. И так рассмотрим код метода.

Посмотрев на код выше, сразу бросается количество ветвлений условных операторов. И относительно не большая функциональность метода, занимает слишком много строк кода. Попробуйте самостоятельно уменьшить ее размер и если ли не получиться подстмотрите код ниже. Функциональность метода нельзя нарушать, лишь сократить ее в объеме. В первую очередь для меня бросается локальная переменная shouldFire которая тут вообще не нужна. А весь остальной код можно сгруппировать в return. И так смотрите что у меня получилось:

Метод настолько уменьшился что поместился в одну строку, а функциональность его осталось не изменой. Рефакторинг программы следует проводить только тогда, кода ваш код рабочий, не имеет ошибок. Только после этого надо думать над тем как его уменьшить. Но сильно уменьшать его тоже не стоит, так как сокращение кода может вести к сложности читаемости кода, в особенности если над кодом работать будут и другие разработчики.

При рефакторинге стоит учитывать то, что метод должен вмещаться в 20 строк кода и максимум в один экран, в случаи разрастания кода следует метод разделять на под методы, это уменьшит их, упростит процедуру отладки, а другим программистам сократит время на понимание логики. Так же при работе с операторами выбора, такими как switch не стоит злоупотреблять, в программе, а лучше всего их заменить на словари Directionary, а так же Делегаты.

Используйте StringBuilder над String, чтобы получить лучшую производительность:

Есть целый ряд статей и сообщений , которые говорят , что StringBuilderявляется более эффективным , поскольку он содержит изменяемый буфер строки. .NET Строки неизменны, что является причиной , почему новый Stringобъект создается каждый раз , когда мы изменяем его (вставка, Append, удалить и т.д.).

В следующем разделе я объясню это более подробно, чтобы дать новичкам четкое представление об этом факте.

Я написал следующий код, и , как вы можете видеть, я определил Stringпеременную и StringBuilderпеременную. Я затем добавить строку в обоих этих переменных:

Если разобрать этот код под рефлетором станет понятно по какой причине лучше использовать StringBuilder.

Если вы зашли в рефлектор можете видеть, Concatфункция принимает два аргумента и возвращает String. Следующие шаги выполняются , когда мы выполняем Append с типом строки:

  1. Проверяет, является ли строка пустой или нет
  2. Создает строку destи выделяет память для строки
  3. Заполняет destстроку str0иstr1
  4. Возвращает destстроку, которая представляет собой новую переменную строку

Таким образом, это доказывает, что всякий раз, когда я делаю операцию конкатенации строк, он создает новую строку из-за неизменное поведение строк. 

Функция Append принимает аргумент типа Stringи возвращает StringBuilderобъект. Следующие шаги выполняются , когда мы выполняем Appendс StringBuilderтипом:

  1. Получить значение строки из StringBuilderобъекта
  2. Проверьте, если требуется выделить память для новой строки мы будем добавлять
  3. Выделение памяти при необходимости и добавить строку
  4. Если не требуется, чтобы выделить память, а затем добавить строку непосредственно к существующей выделенной памяти
  5. Возвращает StringBuilderобъект , который вызывает функцию, используя thisключевое слово

Таким образом, она возвращает тот же объект, не создавая новый.

Я надеюсь , что этот пример помог вам понять внутренние детали о том, почему мы должны использовать StringBuilderчаще чем , Stringчтобы получить более высокую производительность , когда мы делаем основную обработку строк в коде.

Структура инициализации в C #

Структуры в C # позволяют нам группировать переменные и методы. Они несколько похожи на классы, но есть ряд отличий между ними. В этой статье я не буду обсуждать это. Я собираюсь объяснить, как инициализировать структуру.

факты

  1. Структура является типом значения
  2. Это не позволяет создать параметр меньше конструктора, поскольку он инициализирует переменную со значениями по умолчанию

Теперь рассмотрим ниже случай, когда я создал две структуры:

Структура 1: с открытыми переменными.

Структура 2: со свойствами.

Учитывая вышеуказанные два факта, я пытался использовать обе структуры, как показано ниже:

После этого, когда я пытаюсь скомпилировать код, я получаю сообщение об ошибке.

C # компилятор сообщает нам, что позволяет использовать первую структуру без ошибок, но не позволяет использовать вторую структуру, которая выставляет свойство. Чтобы решить эту проблему, я написал ниже строки кода для инициализации второй структуры:

Дело в том, что структура может быть реализована без использования newоператора. Если вы не используете new, то поля будут оставаться Unassigned и объект не может использоваться , пока все поля не инициализированы.

В .NET, все простые типы структур  когда вы пишете код на C # необходимо инициализировать, рассмотрим случай ниже, где я создаю целочисленную переменную:

Это очень важно, чтобы инициализировать структуру правильно.

Оператор Checked

В следующем разделе я буду объяснять о Checked оператора доступна в C # .NET для обработки целочисленных переполнений.

В моей системе управления заказами, я должен вычислить точку продаж для каждого клиента, который размещает заказ. Пункты продажи являются целыми числами, которые получают заработанные клиент на основе продуктов, которые они покупают, и получает вычитаются из общей суммы счета, как они покупают новые продукты, используя эти точки. Но есть некоторые клиенты, которые не знают о балльной системе или не потребляют эти точки так, что точки накапливают более чем предел целочисленных переменных, то есть, 2 ^ 32. Таким образом, всякий раз, когда расчет происходит, я получаю некоторое значение опасное для тех клиентов, которые имеют значение точек больше, чем максимально допустимые целочисленное значение.

Чтобы избежать этой проблемы переполнения целых значений и информировать клиентов о своих точках, я использую Checked оператор C # .NET.

Проверено оператор для проверки на переполнение в математических операциях и переходах для целочисленных типов.

Синтаксис

Когда мы запустим код выше, он бросает исключение.

который говорит , что cбольше , чем максимально допустимое целочисленное значение.

Точно так же, в моем приложении, я ловлю исключение переполнения брошенного при расчете точке заказа, с и затем отправить почту клиенту с напоминанием о необходимости использовать очки.

GO TO Switch..Case

Go To Идти к..

Позволяет нам прыгать безоговорочно, когда это требуется и не рекомендуется для использования в большой степени.

Switch..Case

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

В моем приложении, я достиг той стадии , когда я должен был выполнить код Case 1из Switch..Caseи если какое — то условие было выполнено, я должен был выполнить код Case 3из Switch..Case.

Первое решение этой проблемы , чтобы скопировать код Case 3и поместить его в ifблоке Case 1.

Но проблема выше решения заключается в том, что он делает избыточный код.

Второе решение заключается в создании функции и поместить код в том , а затем выполнить код.

Проблема с этим решением является то, что я должен создать дополнительную функцию, которая не нужна.

Третье решение , чтобы сделать использование Go Toв Switch..Caseблоке:

Go toВ Switch..Caseпозволяет мне сделать код легко и в обслуживаемой образом.

В заключительной части статьи о рефакторинге кода я бы посоветовал вам использовать паттерны при написании кода,  ускоряют процесс их написания, так как они основываются на ООП, тем самым вы избавитесь от дублирования кода в своих приложениях, Он становиться более лаконичен и читабельнее.

Обновлено: 19.10.2018 — 12:02

1 комментарий

Оставить комментарий
  1. Александр

    Вторая версия с тернарными операторами работает быстрее,
    у меня получилось приблизительно ~3030ms против ~3400ms на 100000000 итераций.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.