Как я могу избежать ощущения, будто полностью перестроив свою программу с нуля, я бы сделал это намного лучше? [закрыто]

91

Я изучил значительный объем программирования, однако он всегда находился в научной среде (не в области компьютерных наук), полностью самоучка, и никто не мог направить меня в правильном направлении. Таким образом, мое путешествие по кодированию было ... грязным. Теперь я заметил, что всякий раз, когда я создаю какую-то программу, к концу я понимаю, как я мог бы сделать это гораздо более элегантно, гораздо более эффективно и таким образом, чтобы в будущем было гораздо более гибким и простым в управлении. В некоторых обстоятельствах я на самом деле вернулся и перестроил вещи с нуля, но обычно это практически невозможно. Хотя большинство моих программ до сих пор были относительно небольшими, кажется довольно громоздким полностью переписывать большие программы каждый раз, когда вы что-то создаете.

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

Ashish
источник
87
это нормально, программа больше
Ewan
43
Добро пожаловать в программирование. Если вы не смотрите на старый код и думаете «ура», то вам следует начать беспокоиться, поскольку это означает, что вы перестали учиться.
Caltor
9
Честно говоря, когда я увидел этот вопрос, я засмеялся - потому что буквально каждый программист, с которым я когда-либо разговаривал, включая меня самого, постоянно испытывал это чувство постоянно. Если вы хотите попасть в область, где вы чувствуете, что конечный продукт, который вы создали, не имеет недостатков - программирование было неправильным выбором.
Зиббобз

Ответы:

4

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

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

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

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

asrjarratt
источник
100

Это очень распространенный опыт

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

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

«У всех есть план, пока они не получат удар в лицо».

Что с этим делать

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

Чтобы облегчить проблему, нужно постоянно искать потенциальные улучшения, поскольку вы постоянно работаете и проводите рефакторинг. Убедитесь, что вы нашли хороший баланс между рефакторингом и добавлением новых функций / исправлением ошибок. Это не поможет с большими проблемами дизайна, но, как правило, оставит вам более отточенную базу кода, которой вы можете гордиться.

Андреас Каммерлохер
источник
18
Единственное, что я хотел бы добавить к этому ответу - учиться и следовать принципам TDD при написании кода. Эти тесты затем обеспечивают безопасную среду для рефакторинга и переписывания, поскольку вы продолжаете совершенствоваться как разработчик и хотите вносить изменения в существующий код.
Дэвид Арно
10
@DavidArno в чем смысл рефакторинга с тестами? Это все равно что обновить систему и сделать резервную копию до ... 0 удовольствия.
Джурис
3
@ Džuris, :) Правда, если вам нравятся испытания, не пишите тесты
Дэвид Арно
6
@ Джурис Это как выпрыгнуть из самолета в парашюте!
JollyJoker
3
@jamesqf - это неверное представление о том, что делают TDD и модульные тесты - например, они могут сказать вам, что ваша модель или алгоритм реализованы правильно, и что вы ничего не сломали при рефакторинге. Они не могут сказать вам, что ваша модель действительно полезна. Это так же верно в научной среде, как и в любой другой.
Муравей P
46

Научитесь рефакторингу - искусству постепенного улучшения кода. Мы все учимся все время, поэтому очень часто понимают, что код, который вы написали самостоятельно, мог бы быть написан лучше.

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

JacquesB
источник
4
Эта практика также поможет вам научиться писать код, который является модульным и может быть легко реорганизован. Все лекции в мире не научили меня этой привычке так сильно, как необходимость разбивать старые большие функции на управляемые куски, чтобы мне не пришлось переписывать с нуля. Каждый новый проект у меня получается лучше.
JKreft
На мой взгляд, лучшая отправная точка, чтобы узнать о рефакторинге: рефакторинг о новых функциях
Wildcard
9

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

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

Однако, как правило, вам не так уж и повезло: требования будут менее чем звездными и неполными, и, хотя вы думали, что поняли их, оказывается, что есть области, в которых вы сделали неверные предположения.

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

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

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

В конце, тем не менее, примите, что изменение является постоянным, и проигнорируйте приступ, который говорит: «Я мог бы сделать это лучше» Гордитесь и радуйтесь, что вы предоставили решение вообще.

Wildbill
источник
Или, говоря по-другому: научитесь разрабатывать для гибкости с самого начала, не вводя ненужных накладных расходов. В идеале гибкость проистекает из простоты. Тогда у вашего дизайна есть шанс пройти тест на изменение требований.
начальник
3

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

Что вы можете сделать, это создать одноразовый прототип, прежде чем начинать делать «настоящий» проект. Быстро и грязно. Затем, когда вы получите прототип, подтверждающий концепцию, вы узнаете о системе и о том, как все делать правильно.

Но не удивляйтесь, если через N лет вы вернетесь к этому коду и подумаете «что за бардак».

BЈовић
источник
3
Или, вы показываете прототип своему боссу, он говорит: «Отлично, это подойдет». перемещает вас в другой проект, и ваш прототип становится производственным.
RyanfaeScotland
2
Этот совет настолько распространен, что об этом говорят. «Построить один, чтобы выбросить». И этот совет настолько неправильно используется, что в нем есть поговорка: «Если вы построите один, чтобы выбросить, вы, вероятно, выбросите два».
Эрик Липперт
2
@EricLippert Мой опыт был ужасен в противоположном направлении - если мы создадим один, чтобы выбросить, он неизбежно будет отправлен клиенту.
Джон
2
@Jon: Да, это может произойти, особенно когда ошибки управления «пользовательский интерфейс выглядит так, как будто он работает», когда там действительно есть какой-то код. Тем не менее, мой опыт всегда был, как говорил один из моих коллег, «у нас достаточно времени, чтобы дважды его построить неправильно, но не хватает времени, чтобы один раз построить его правильно». :-)
Эрик Липперт
@EricLippert Это как раз причина для создания GUI последним, а НЕ для создания GUI для прототипа;)
BЈовић
3

Запомните эту мантру:

Идеальное враг хорошего .

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

  • Удовлетворяет ли он всем требованиям относительно функциональности и производительности?
  • Это без критических ошибок, которые вы не можете исправить в текущей архитектуре?
  • Оцените, сколько работы вы потратите на поддержание этого приложения в будущем. Будут ли усилия по переписыванию быть больше, чем долгосрочные усилия, которые это сэкономит?
  • Есть ли вероятность того, что ваш новый дизайн может ухудшить ситуацию?

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

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

Philipp
источник
3

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

Соблазнительно думать, что идеальное планирование даст вам идеальный дизайн / архитектуру программного обеспечения, однако оказывается, что это категорически неверно. Есть две большие проблемы с этим. Во-первых, «на бумаге» и «код» редко совпадают, и причина в том, что легко сказать, как это следует делать, а не делать это на самом деле . Во-вторых, непредвиденные изменения в требованиях становятся очевидными в конце процесса разработки, о чем нельзя было говорить с самого начала.

Вы слышали о гибком движении? Это способ мышления, в котором мы ценим «реагировать на изменения», а не «следовать плану» (среди прочего). Вот манифест (это краткое чтение). Вы также можете прочитать о Big Design Up Front (BDUF) и о подводных камнях.

К сожалению, корпоративная версия «Agile» является фальшивой (сертифицированные мастера Scrum, тяжелый процесс во имя «Agile», форсирование Scrum, 100% покрытие кода и т. Д.), И обычно приводит к изменениям процесса asinine, потому что менеджеры Подумайте, Agile - это процесс и серебряная пуля (чего нет ни у одного). Прочитайте проворный манифест, послушайте людей, которые начали это движение, таких как дядя Боб и Мартин Фаулер, и не впитывайте бессмысленную версию «корпоративного гибкого подхода».

В частности, вы обычно можете просто выполнить TDD (Test Driven Development) для научного кода , и есть большая вероятность, что ваш программный проект окажется чертовски хорошим. Это связано с тем, что успешный научный код в основном имеет ультраиспользуемые интерфейсы, а производительность является второстепенной (а иногда и конкурирующей) проблемой, и поэтому вы можете избежать неприятностей с более «жадным» дизайном. TDD отчасти заставляет ваше программное обеспечение быть универсальным , потому что вы пишете, как вы хотите, чтобы вещи назывались (в идеале) до того, как вы на самом деле их реализуете. Он также предоставляет небольшие функции с небольшими интерфейсами, которые можно быстро вызывать простым способом «ввод» / «вывод», и это дает вам хорошую возможность для рефакторинга в случае изменения требований.

Я думаю, что мы все можем согласиться, что numpyэто успешное программное обеспечение для научных вычислений. Их интерфейсы маленькие, удобные в использовании, и все прекрасно сочетается. Обратите внимание, что numpyсправочное руководство явно рекомендует TDD: https://docs.scipy.org/doc/numpy-1.15.1/reference/testing.html . В прошлом я использовал TDD для программного обеспечения SAR (Synthetic Aperature Radar), и я также могу утверждать, что он работает очень хорошо для этой конкретной области.

Предостережение: часть разработки TDD работает не так хорошо в системах, где фундаментальный рефакторинг (например, решение о том, что ваше программное обеспечение должно иметь высокую степень параллелизма) будет трудным, как в распределенной системе. Например, если вы должны были разработать что - то вроде Facebook , где у вас есть миллионы пользователей одновременно, делая TDD (диск вашего дизайна) было бы ошибкой (все еще хорошо использовать после того, как у вас есть предварительный проект, и просто сделать «тест первого развития «). Важно подумать о ресурсах и структуре вашего приложения, прежде чем переходить к коду. TDD никогда не приведет вас к высокодоступной распределенной системе.

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

Учитывая вышесказанное, должно быть несколько очевидно, что идеальный дизайн на самом деле невозможен, поэтому погоня за идеальным дизайном - игра для дураков. Вы действительно можете только приблизиться. Даже если вы думаете, что можете изменить дизайн с нуля, вероятно, все еще есть скрытые требования, которые не показали себя. Кроме того, переписывание занимает как минимум столько же времени, сколько потребовалось для разработки оригинального кода. Это почти наверняка не будет короче, так как вполне вероятно, что новый дизайн будет иметь непредвиденные проблемы самостоятельно, плюс вам придется заново реализовать все функции старой системы.

Еще одна вещь, которую следует учитывать, это то, что ваш дизайн действительно имеет значение только тогда, когда меняются требования .Неважно, насколько плох дизайн, если ничего не изменится (при условии, что он полностью функционален для текущих случаев использования). Я работал над базовой линией, в которой было 22 000 операторов переключения строк (функция была еще длиннее). Был ли это ужасный дизайн? Черт возьми, это было ужасно. Мы это исправили? Нет, все работало нормально, и эта часть системы никогда не вызывала сбоев или ошибок. Он был затронут только один раз за два года моего участия в проекте, и кто-то, как вы уже догадались, вставил в коммутатор еще один чехол. Но не стоит тратить время на то, чтобы починить то, к чему так редко прикасаются, просто это не так. Пусть несовершенный дизайн будет таким, какой он есть, и если он не сломался (или постоянно ломается), то не исправляйте его. Так что, может быть, вы могли бы сделать лучше ... но стоит ли это переписывать? Что вы получите?

НТН.

Мэтт Мессерсмит
источник
2

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

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

Еще одна хорошая вещь - это исправление кода. Когда вы работаете в одиночку, легко срезать углы. Если у вас есть второй человек, который просматривает ваш код, он сможет указать, где вы не следуете этим рекомендациям. Таким образом, вы создадите лучший код и узнаете кое-что.

Истр
источник
1

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

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

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

Кроме того, чувство, что вы могли бы сделать лучше, является хорошим знаком ! Это показывает, что вы заботитесь о качестве своей работы и что вы оцениваете ее критически; так что вы, вероятно, учитесь и улучшаете. Не позволяйте этим вещам беспокоить вас - но не прекращайте их делать!

gidds
источник
1

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

Поскольку разработка программного обеспечения стала общепринятой лишь в 90-х годах, ей примерно 30 лет. Мы узнали, что это не столько инженерная дисциплина, сколько социальная наука, и мы только начали.

Да, вы попробуете TDD, Рефакторинг, Функциональное программирование, Шаблон репозитория, Источник событий, MV что-то, Java Script (<- Делайте это, это безумие), Привязка модели, Нет Sql, Контейнеры, Agile, SQL (<- сделать это это мощно).

Там нет ни одного исправления. Даже эксперты все еще цепляются за соломинку.

Добро пожаловать, и будьте осторожны, это одинокое место; но абсолютно увлекательно

Marius
источник
1

Я собираюсь пойти немного против зерна. Это невероятно часто , но это не приемлемо . Это говорит о том, что вы не признаете хорошие способы организации своего кода во время его написания. Ощущение исходит от того, что ваш код не прост .

Ваш опыт был моим долгое время, но в последнее время (последние пару лет) я производил больше кода, который не дает мне ощущения, что мне нужно все выбросить. Вот примерно то, что я сделал:

  1. Уясните, какие предположения делает какой-либо конкретный блок кода. Бросайте ошибки, если они не встречаются. Подумайте об этом изолированно , не полагаясь на детали того, что делает остальная часть программного обеспечения. (То, что делает остальная часть программного обеспечения, влияет на то, какие предположения вы применяете, и какие варианты использования вы поддерживаете, но это не влияет на то, выдаете ли вы ошибку, если допущение нарушено.)
  2. Перестаньте верить, что следование правилам, шаблонам и практикам даст хороший код. Отбросьте образ мыслей и практики, которые не являются очевидными и простыми. Этот был огромен. ОО и TDD обычно преподаются таким образом, который не основан на практических соображениях, как набор абстрактных принципов, которым вы должны следовать при написании кода. Но это совершенно бесполезно для разработки хорошего кода. Если вы вообще используете OO или TDD, это следует использовать в качестве решения проблем, которые, как вы понимаете, у вас есть . Другими словами, их следует использовать только тогда, когда вы смотрите на проблему и думаете: «Хорошо, это имеет полный смысл и чрезвычайно очевидно как хорошее решение». Не раньше, чем.
  3. Когда я пишу код, сосредоточьтесь на двух вопросах:
    • Использую ли я функции и библиотеки так, как они предназначены для использования ? Это включает в себя использование его для тех задач, которые он должен был решить, или, по крайней мере, очень похожих.
    • Это просто ? Смогу ли я и мои коллеги позже легко следовать логике? Есть ли вещи, которые не сразу очевидны из кода?

Мой код теперь более «процедурный», и я имею в виду, что он организован по тому, какие действия он выполняет, а не по структурам данных, которые он использует. Я использую объекты в языках, где автономные функции не могут быть заменены на лету (C # и Java не могут заменить функции на лету, Python может). Сейчас у меня есть тенденция создавать больше служебных функций, которые просто отбрасывают раздражающий шаблон, чтобы я мог фактически прочитать логику своего кода. (Например, когда мне нужно было обработать все комбинации элементов в списке, я поместил индекс зацикливания на метод расширения, который возвращаетTuples, чтобы исходная функция не была загромождена этими подробностями реализации.) Теперь я передаю гораздо больше функций в качестве параметров, вместо того, чтобы функция обращалась к какому-либо другому объекту для его извлечения. (Вызывающий извлекает или создает его и передает его.) Теперь я оставляю больше комментариев, которые объясняют вещи, которые не очевидны, просто глядя на код , что облегчает следование логике метода. Я пишу тесты только в ограниченных случаях, когда меня волнует логика того, что я только что сделал, и я избегаю использования мошенничества. (Я делаю больше тестов ввода / вывода на изолированных кусочках логики.) В результате получается код, который не идеален , но на самом деле кажется, что все в порядкедаже через 2 или 3 года. Это код, который довольно хорошо реагирует на изменения; незначительные вещи могут быть добавлены или удалены или изменены без разрушения всей системы.

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

jpmc26
источник
0

Помня, что ваше время ограничено. И ваше будущее время также ограничено. Будь то работа, учеба или личные проекты, когда речь идет о рабочем коде, вы должны спросить себя, «переписывает ли это лучшее использование моего ограниченного и ценного времени?». Или, может быть, «это наиболее ответственное использование моего ограниченного времени»?

Иногда ответ будет однозначно да . Обычно нет. Иногда это будет на заборе, и вам придется использовать свое усмотрение. Иногда это хорошее использование вашего времени просто из-за того, чему вы научитесь, делая это.

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

Джаред Смит
источник
0

Это совершенно нормальная часть обучения. Вы понимаете ошибки, как вы идете.

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

mathreadler
источник
0

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

  • Ваш дизайн с нуля получился таким элегантным, как вы надеялись?
  • Действительно ли ваше решение точно такой же проблемы? Какие функции вы пропустили? Какие крайние случаи вы пропустили?
  • Какие с трудом заработанные уроки в оригинальном проекте вы стерли в погоне за элегантностью?
  • После того, как вы добавите эти недостающие части обратно в свой дизайн, станет ли он таким же чистым, как и без них?

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

Maxpm
источник