Pull to refresh
7
0

User

Send message
К сожелению «выделение метода» catch-тел не уменьшает количества catch-блоков.

Если логика разная, то это приведет к появлению нескольких функций в носителе метода с try...catch. Из статьи я вынес возможность перености эти методы в соответствующие exception-классы. И вызывать их через полиморфизм.
А мне понравилось.

1. «Сразу скажу, что для меня исключение != ошибка...». Я с Вами.
2. Мне пративно, когда вижу три и более catch-конструкции. А здесь увидел простое и изящное средство от своих комплексов.
3. Помоему есть некоторые проблеммы гибкости с типами исключений и перехватом (возможно я и ошибаюсь — будет ястно когда воспользуюсь советом). На 100% они решаемы.

Аналогичным образом я передаю часть ответственности классам аттрибутов. Может поэтому мне не кажется это нарушением SOLID-принципов.
Не стоит говорить о гибких методологиях. Они просто не работают на проектах с 15-и летней историей, десятками тысяч классов. Переписать все это абсолютно невозможно.

Подход: работает не трожь.

Рефакторинг замечательно масштабируется. Главное помнить о маленьких шажках и команде «Undo». Не обязательно править все 15 тысяч классов сразу. Постепенно узел за узлом, по мере того как вспоминается о их существовании (по ним появляются задачи).
При этом основная масса разработчиков не может четко ответить на вопрос: «Когда стоит переписывать код?»

А как же Фаулеровские «запахи»?
К стати интересная мысль. Затраты на внесение изменений с рефакторингом надо сравнивать не с изменениями без него. А со следующими изменениями без рефакторинга. :)
Я о том, что заставляет вас делать костыли. Сомневаюсь что это имена переменных.

Если у вас появляется необходимость еще и в видоизмененном варианте какого-то алгоритма (выбираемым например по параметру из config-а или базе) можно действовать двумя способами:
1. Вставить пару тройку if-ов
2. Выделить логику в отдельную стратегию (рефакторинг) и создать еще одну стратегию с видоизмененной логикой.

Второй вариант в первый раз займет в два раза больше времени. Зато во второй раз эти затраты примерно сравняются.

Все как вы сказали
Рефакторинг — это как раз способ не переписывать по новой. За две недели вы возможно и напишите 30 000 строк кода, но наверника не учтете все case-ы.
Рефакторинг, как часть рабочего процесса и нужен, что бы не попадать в подобные ситуации.
Потому я вами и не соглашаюсь :)
Я бы с вами согласился, если бы не нашел такой фразы:

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

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

Бороться с размытием надо. Но удаление слова this — это не выход.

Я считаю нормальной практикой не хранить фикстуры в тестовом классе. Для этих целей в простых случаях я использую методы расширений. Проект один. Классы обычно находятся в одном файле. Но, задача разделения абстракции решена. От других тестовых классов функция отделена. Вектор развития системы (по необходимости) очевиден: либо выносить методы в общий статический класс, либо преобразовывать в отдельный класс (не статический). Так где здесь проблема?
Не надо забывать что функции расширения — есть свертка паттерна «функция расширения» (Фаулер «Рефакторинг») — вариант реализации простой стратегии. Это синтаксический сахар и ничего более. Обе описанные вами проблемы есть и у любой стратегий.

По связке инкапсуляция-функция расширения вообще не согласен. Функции расширения позволяют лучше оттачивать интерфейсы, оставляя в них только то что действительно необходимо. Вспомните IEnumerator(IEnumerable) — я считаю его лучшем интерфейсом в .NET. А таким самодостаточным, легким и удобным он стал только с версией 3.5. До того он был довольно ущербным.
Я как-то об этом не задумывался. Но однозначно существует оба термина. Скорее всего это переводы raise и throw, используемые в разных языках программирования.
Если вы будете везде, где достаточно передать функцию, строить классическую схему построение патернов, то вы утонете в коде раньше чем решите задачу. GAF-ы пишут именно об этом, когда говорят, что люди отказываются от использования патернов.

Есть замечательная книга Джошуа Кериевски «Рефакторинг к паттернам», основная ее мысль — стройте такую структуру типов, которая действительно необходима. Паттерн — это картинка, которая поможет в трудную минуту, а не инструкция по сборке самолета.

Взгляните на передачу функции в качестве аргументов под углом достаточности и вы поймете, что mokus прав
Я не имел в виду review перед выкладыванием (я выкладываю 1-3 раза в час — бедный цензор). Да и не review в чистом виде, а рефакторинг. Я говорил о том, что любой код должны увидеть минимум двое (с точки зрения review — создатель и цензор). Может через неделю, может через месяц после создания.

Вы говорите о review, как о мере обратно пропорциональной доверию. Я как о способе привлечения свежей головы. Это даст пользу даже если вы гуру, а цензор — достаточно смелый студент 4-го курса (если он обладает навыком рефакторинга и работает в основном руками, а не языком). Рефакторинг достаточно механическая деятельность (при наличии тестов конечно).

По поводу компании сказано хорошо: мы, в конце концов, все делаем по ее усмотрению. За это и получаем зарплату.
«Совместное владение кодом». Мысль — шикарная, хотя и мало пропагандируемая. Оно избавляет от всяких препирательств по поводу рефакторинга чужого кода, потому что такого нет.

Review быть обязан — каким бы опытным не был разработчик, к своему творению в первые дни он относится как ТВОРЕНИЮ, а потому не видит многих явных проблем. А что бы цензор, в это время принасил реальную пользу, он как раз и должен заняться рефакторингом (без лишних разговоров с рецензентом, он все равно о всем узнает). Это наложит некоторую дополнительную ответственность при написании тестов, но от этого система только выграет.
Сущность в ООП определяется состоянием и поведением. Статические классы — есть вырожденный случай такой сущности.

Если изредка они встречаются, то это можно списать на необходимость: профилирование, низкоуровневые особенности свойств статических классов, наконец достаточность. Это такой полухак.

Если часто, то скорее всего в восприятии разработчика система представляется преобразователем входных данных в выходные.
Большое количество статических классов в большинстве случаев говорит от функционально ориентированном подходе разработчика к решению проблемы (хотя исключения и возможны). SOLID же это своего рода правила решения ООП проблем.
Я с вами абсолютно согласен.

Перехватывать Exception-ы надо только там, где ты точно знаешь как их обработать. Если же мы каждую функцию будем обрамлять в try catch, то это будем ни чем не лучше GetLastError, возврата -1, или макроса ASSERT в который, дядьки с большими головами, советовали обрамлять каждый вызов в C++ коде.
К моменту получения информации о существовании проблемы вы уже разработали работающий функционал. Разработка окончена (по крайней мере на этом локальном участке кода на данной итерации). Устранение непрерывного потока exception-ов является задачей процесса профилирования, которую в подавляющем большинстве случаев решать не приходится.
Если я правильно понял вопрос.

Если вы чем-то отделяете 100500-ое исключение от остальных 100499 вы должны об этом в коде явно сказать (сделать ответвление в иерархии наследования исключений). Ни кто же не утверждает что все исключения class-а Exception. Иначе это не чем не будет отличаться от возврата -1.

Даже если этого не делать, у современных Debuger-ов достаточно развиты breakpoint-ы. Если по каким-то причинам их применять тяжело, можно поставить if с условием остановки с пустым телом — breakpoint поставить в нем.

Другими словами это не проблема Exception-ов как таковых.

Information

Rating
Does not participate
Registered
Activity