Pull to refresh

Comments 67

«Решай проблеммы по мере их возникновения». Каждый раз себе это повторяю. Часто помогает. А вобще это очень тонкая материя. Тут, как и во всем остальном, серебрянной пули нет.

Ну и рефакторинг никто не отменял.
излишнее переусложнение — это, конечно, плохо. Но, если вдруг заказчик решит что-нибудь еще, простенькое по его словам, добавить в проект?
Тут, как и во всем, важна золотая середина.
Не писать абсолютно нерасширяемый и неизменяемый код, в который нельзя внести даже минимальные изменения без полного переписывания; но и не стараться написать абсолютно универсальный код, который решает все задачи на свете.
Код должен решать поставленную задачу и поддерживать некоторые отклонения от изначальной задачи, которые кажутся наиболее вероятными на момент разработки.
Соответственно золотая середина тут в нахождении той точки, в которой усилия, затраченные на разработку такого «немного универсального» кода окупаются бонусами от возможности его расширения умноженными на вероятность такого расширения.
вот вот — код ведь все вермя плывет. Как во время разработки, так и потом при поддержке. Постоянно какие-то части устаревают, и не так уж часто ожидания того куда код будет разрастаться оправдываются. Но если периодически окидывать код критичным взглядом для переботки сильно поплывших частей — то вполне можно удержать баланс
В статье про это написано: «Это не „задел на будущее“, потому что мы не можем предвидеть будущее».
И действительно, догадаться, что заказчик захочет добавить в проект сложнее чем кажется.
Делать бесплатно заказчику что-нибудь «простенькое», отсутствующее в утверждённом ТЗ это первый шаг к тому, чтобы заказчик сел вам на шею и получил за ранее утверждённую сумму нечто, фактически стоящее гораздо больше.
хо-хо!

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

Я встречал не мало ПО совершенно непригодного к модернизации. Ради экономии времени было упрощено всё что только возможно, однако это далеко не всегда приводило к однозначной экономии. Увы бывают случаи когда модернизация системы неизбежна, и должна быть максимально упрощена.
Очень часто оба этих явления сосуществуют в одном проекте.
Начало разработки каждого релиза начинается с настроения «а спроектируем ка мы весь мир» и возникает вавилонская башня из классов и совершенно-необходимых-фич. А по мере приближения дэдлайна все понимают, что анальная кара стремительно приближается, и эту башню кое-как скрепляют соплями и скотчем, чтобы держалась. И так — кажый релиз ^_^
> модернизация системы неизбежна, и должна быть максимально упрощена.

Это верно для 99.9% систем.
Вот только (в моей практике) чаще всего причина, по которой систему было трудно модернизировать — именно её переусложнённость. Повыкидывали лишние классы/интерфейсы, поставили простой switch и т.д. — и сразу стало проще модернизировать.
Есть такое понятие как «преждевременная оптимизация», собственно тоже одно из проявлений «переинженеринга»

Я тут в одном из топиков как-то уже рассказывал один случай, вкратце: написал очень простой код, потом начал усложнять, потом ещё и ещё, был уверен что так будет правильнее, а потом понял что никому это не надо и вернулся к собственно первому самому простому и логичному варианту. Код работает уже не первый год и свои функции выполняет на все 100%
Everything should be made as simple as possible, but no simpler.
Данная формулировка мне больше нравится — в ней соблюдается разумный баланс.
все-таки
Here I give you my phone number
When you worry call me
I make you happy
магия блин, не дали дописать)

все описанное — abstraction freak
были несколько статей про типы программистов, там как раз описывался такой

p.s.
всегда думал что Боб Марли написал эту песню, узнал что-то новое не только из сферы IT )
Бей перфекционистов! :)

А если по делу, то всегда нужно искать золотую середину, и статья правильно об этом говорит. Шаблоны проектирование — не должны стать самоцелью. Цель написать хорошо работающую и легкоподдерживаемую программу.
UFO just landed and posted this here
Вы совершенно правы, чрезмерное усложнение — один из факторов, который влияет на программиста и заставляет его писать «плохое ПО».

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

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

Кроме того, сама задача может быть до такой степени сложной, что легче воспользоваться чудовищным, но привычным паттерном проектирования, чем анализировать, что в этом месте лучше написать.
Например, у меня иногда доходит до того, что перестаю следовать даже правилам именования переменных, чтобы скорее записать кодом то, что в текущий момент сформировалось в голове (естественно, это потом попадает под рефакторинг, но не в этом суть).

Я давным-давно перестал злиться на программистов из Microsoft, т.к. представляю, какую ОГРОМНУЮ работу они проделали. Легко говорить «как меня достала эта глюкавая винда», но мало-кто представляет насколько сложно это написать.

— Как видите, ваш «преступный переинженеринг» — относительно небольшая часть очень большой проблемы.

Думаю, в этом случае лучшие рекомендации — снижать любыми способами нагрузку на голову. Именно не в плане упрощения программы — простую программу написать очень сложно — а в том смысле, чтобы на протяжении всего процесса разработки не перегружать мозг.

Лично мне очень нравятся принципы Agile-методологий: быстрое получение работающей программы и последующий рефакторинг, развитие программы маленькими шагами. Ну и обязательно хорошо высыпаться и иметь хорошее настроение.

— Спасибо Вам за статью. Она помогла мне лучше понять некоторые вопросы.
кстати, один из методов снижения нагрузки на моск — разделение работы между несколькими людьми: тестированием занимается тестировщик, проектированием интерфейсов человек, профессионально проектирующий UI, оформлением и рисованием иконок — дизайнер.
В этом случае также есть ряд проблем.
Например, при тестировании системы с точки зрения безопасности необходимо не только тестировать «черный ящик», но и изучить программный код с целью выявления мест, где про безопасность халатно забыли. Мало времени, много мест рефакторинга, рассредоточение внимания — мало ли причин? А наличие одного единственного слабого место может привести к серьезным проблемам безопасности. За примером далеко ходить не надо — посмотрите web-браузеры )
эта проблема будет в любом случае
В примере кода есть ошибка. оператор break пропущен везде.
Это пример того, как избавиться от переинженеринга окончательно или просто досадная опечатка?
извиняюсь. ошибся сам.
Очень хорошая и полезная статья. Что касается меня, я стараюсь вообще не заглядывать в будущее и решать проблемы по мере их поступления. Если в приложении действительно есть какая-то общая функциональность, то это обязательно станет заметно в процессе работы. Ну и конечно же, надо понимать, что совершенного (или даже близкого к совершенству) решения не существует, и что рано или поздно тот софт, который мы написали, придется все-таки переписывать частично или полностью (ну или как вариант просто выбросить и забыть о нем).
Ещё одна хорошая и полезная статья… Когда же на Хабре перестанут учить жизни?! Опять кто то пишет новые истины обобщая десятки профессий в сферического программиста в вакууме. На виртуальные плечи программиста одиночки перекладывают такие массы как Excel.
Почему вообще в статье проектированием занимается программист?


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

Спасибо за перевод, но оригинал не несёт смысловой нагрузки.
Вот вот… И тем более вся теория не срабатывает, когда программисту приходится все делать самому — у него банально может не хватить времени исследовать, какой из путей развития проще сделать сейчас…
Так о чём и речь. Если банально нет времени, то стоит выбрать самое простое и очевидное решение. Для этого не надо ничего исследовать, простое решение — оно всегда простое.
Насколько я понял, речь в статье как раз не об этом, а о том — что зачастую как раз очевидные решения ничуть не лучше. Что из-за того, что делают только то, что прийдет первое в голову и возникают непонятно-громоздкие конструкции… Любой код нужно вдумчиво писать и аргументировано. Я так понимаю эту статью…
Вопрос для меня в другом — что в русских реалиях это не приживается. «Наш» заказчик никогда не поймет, что в разработке заплатить больше можно лишь за качество, но никак не за скорость. И платить нужно за знания, а не за быстроту.
Я думаю, что вы неправильно поняли, о чём идёт речь в статье.

Насчёт русских реалий ничего сказать не могу, увы.
В наших эстонских реалиях тоже тяжело разговаривать с заказчиком, но всё же иногда получается ему объяснить, что вот так ему самому будет выгоднее, чем этак, хотя это и не очевидно на первый взгляд. Так что опыт в этом смысле вполне позитивный.
В наших эстонских (кстати привет земляк) вообще с заказчиками трудно разговаривать, понтов у них как у цивилизованных европейцев, а вот мозгов у некоторых меньше чем у «индусов» (причём слово «индусов» в кавычках, ибо это в переносном смысле)
В большой системе это чревато.
Когда дублирование кода хотя бы в трех модулях, каждый со своей спецификой использования — поддерживать такой код достаточно сложно, очень легко ошибиться.
Так про дублирование тут речи не шло. Речь шла о действительно простых ситуациях.
И дальше был комментарий: «Применить паттерн, если этот код начнёт разрастаться (читай: если его начнут дублировать)».
При чём чистота?
В статье идёт речь о проектировании КОДА на уровне «if / switch / extract method».
Этим занимаются исключительно программисты и никто больше.
Почитайте что ли повнимательнее…
То есть вы считаете, что использование паттерна Strategy это уровень if/switch? Кстати, при нормальном проектировании никаких extract method не должно быть. Иначе может получиться дублирование функции — так как возможны варианты, что несколько программистов сделают одинаковые вспомогательные функции (допустим какой-нибудь isEmpty()). Ещё хуже если работа идёт в одном namespace и возникнет дублирование имён и функции с одинаковыми подписями — код проекта просто не будет компилироваться. А может получиться, что автономные функции будут связанны на уровне вспомогательной, хотя их видимая схожесть была запланирована лишь как база следующего релиза. То есть тот общий функционал, который вынесли отдельно был запланирован лишь для первой стадии проекта, а потом он исчезает из одной функции.
> при нормальном проектировании никаких extract method не должно быть
Вы что-то слышали о том, что модель waterfall морально устарела? Что невозможно спроектировать всё заранее, так чтобы потом ничего не пришлось менять?

PS. Между прочим, когда код проект не компилируется, это не «ещё хуже», а это наоборот, хорошо. Все сразу видят, в чёс проблема, и быстро её исправляют.
Я слышал о том, что модель «я знаю лучше всех и сам буду решать, что и как» — морально уродлива. Вы так же как и автор мешаете в кучу разные профессии. Моделирование — не для программиста. Как в армии — приказ не обсуждается. Дали класс и функции — делай не больше и не меньше. В нормальном рабочем процессе есть сроки и задание. Задание известно и за него платит деньги клиент. Не можете спроектировать всё заранее — не беритесь за работу.
По-моему вам ничего не понятно.
Проблемы возможного обобщения и усложнения задачи в будущем надо решать на стадии создания технического задания. Тут нужно действительно глубоко продумывать перспективы. А после этого — читаем статью! Избавляемся от всего, от чего возможно. Но! Методами, учитывающими перспективы. На практике переусложнение встречается все же реже, чем недоучет.
О нет, практика бывает разная.
В моей практике как раз-таки переусложнение чаще мешает жить.
В программировании наиболее важен баланс, баланс между скоростью и объемом, баланс между простотой и функциональность и т.д. и т.п.
с этого дня я противник патентования ПО.
Костыли — это кошерно (с) забыл
(цитата) русские программисты тем отличаются от западных, что вместо того чтобы просто решить задачу начинают писать инструмент для решения обобщенного класса похожих задач. (конец цитаты) и в зависимости от того успеет программер уложить в сроки заказчика — он либо мегакрут для всех, либо хуже индуса…
где то была статья про это на хабре,
Меня больше всего забавляет, когда ООПарасты мотивируются тем что они якобы избавляются от «копирования кода», с помощью абстракций.
Думаю, в большинстве случаев, интерфейсы нужны только тогда, когда планируется плагинизация (взаимодействие заменяемых компонентов).
Проблема как всегда одна, нужен баланс, и он не имеет чёткой величины, он зависит только от задачи.

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

Или может тебе надо забить гвоздь для того чтоб… (и вот тут опять нужно включить мозги и искать подходящее решение, забить гвоздь, закрутить шуруп, или просто посадить на клей...)
Ну вообще-то Dependency Injection без интерфейсов сложновато будет реализовать.
Да нет, формально для Dependency Injection не нужны.
Это просто такая широко распространённая практика, но она вовсе не обязательна.
Правильно, широко распространенная.

Поэтому если я увижу в коде DI реализованный не на интерфейсах, я сильно удивлюсь и начну искать причину, по которй был выбран именно этот путь, и если я ее не найду, или она окажется банальной, типа, «я всем доказал, что DI можно реализовать без интерфейсов», то мнение о таком подходе будет «закапывать капли в глаза через ж… пу», ну и о программисте соответственное.
А если автор назовёт вам такую причину: «Я решил задачу, написав меньше кода. И ничуть не хуже»? То что такой подход вам кажется непривычным — не причина считать его плохим.

PS. Впрочим, мы сейчас говорим немножко о выдуманной ситуации. В основном, там где применяется DI, и интерфейсы всё-таки нужны, но не потому, что DI этого требует, а в силу естественных причин.
>А если автор назовёт вам такую причину: «Я решил задачу, написав меньше кода. И ничуть не хуже»?

Я ее с удовольствием приму и добавлю в копилку своих знаний ;)
Интерфейсы также нужны, когда разные части системы разрабатывают разные команды, между которыми слабая коммуникация (например, физическая удаленность команд, работающих над одним проектом).
Есть анти паттерн такой — голдхаммер. КОгда у вас в руке молоток, все проблемы кажутся гвоздями.
Об этом и идёт речь в этой статье.
Когда в руках молоток, вокруг — реально гвозди, а тебе кажется: «А вдруг это не гвозди? А вдруг я как раз тот, про кого придумали паттерн голдхаммер?»
Тсранно, не помню ни одной проблемы с переинжененрингом, а вот проблем с простыми но неизменяемыми решениями — сколько угодно.
*Странно, конечно же.
Ну значит, не сталкивались. Я тоже не сталкивался со злыми милиционерами, но все говорят, что они есть.

PS. Если решение действительно простое, то почему оно неизменяемое-то? Должно быть наоборот: простое — понимаемое — меняемое.
Вообще, я заметил, что тяга к универсальности идет от неточно поставленных требований, или когда проект начинается с разработки базы, а не UI, как это было модно лет 10 назад.

Когда же четко определено что и как должно работать на UI, то мудрить с абстракциями и универсальностями просто не тянет — тупо возникает вопрос «а на фига?», задача поставлена, вот решение, если что-то добавится или поменяется, то код изменю я здесь, и здесь.
Вообще, я заметил, что тяга к универсальности идет от неточно поставленных требований, или когда проект начинается с разработки базы, а не UI, как это было модно лет 10 назад.

Когда же четко определено что и как должно работать на UI, то мудрить с абстракциями и универсальностями просто не тянет — тупо возникает вопрос «а на фига?», задача поставлена, вот решение, если что-то добавится или поменяется, то код изменю я здесь, и здесь.
«Переинженеринг» наверно такое же зло, как copy-paste. Помимо того, что тратится время на создание избыточного кода, то еще больше времени нужно для поддержки => стоимость разработки растет. Как сказано выше, нужно писать так, чтобы в дальнейшем можно было расширить до новой нужно функциональности, если понадобится.
Как одно из решений от переинженеринга можно рассматривать применение TDD и пользовательский историй
Реинжинеринг физически необходим, когда простое решение начинает использоваться в разных частях системы, в каждой из которых нужно «так же, но чуть-чуть по-другому».
В некоторых случаях, например, таких, подобные шаблоны проектирования здорово облегчают жизнь тем, кто поддерживает и дорабатывает продукт.
Я всецело согласен, что делать из этого панацею не следует (в этом смысле пример из Википедии можно рассматривать лишь как учебный пример, который вряд ли применим на практике). Но тем не менее ценность обобщенных решений в сложных случаях никто не отменял.
Хотелось заострить на этом внимание, чтобы соблюсти некоторый баланс между «использовать» и «не использовать».
Sign up to leave a comment.

Articles