Як я можу уникати того, щоб завжди відчувати себе так, якби я повністю переобладнав свою програму з нуля, я б зробив це набагато краще? [зачинено]


91

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

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


87
нормально, програма більше
Ewan



43
Ласкаво просимо до програмування. Якщо ви не дивитесь на старий код і думаєте "ургу", тоді вам слід почати хвилюватися, оскільки це означає, що ви перестали вчитися.
Калтор

9
Чесно кажучи, побачивши це питання, я засміявся - адже буквально кожен програміст, про який я коли-небудь говорив, включаючи і себе, відчуває це почуття постійно, в усі часи. Якщо ви хотіли зайти в поле, де ви відчували, що кінцевий продукт, який ви створили, не мав вад - програмування було неправильним вибором.
Зіббобз

Відповіді:


4

Це почуття є цілком нормальним і очікуваним. Це означає, що ти вчишся. Майже щоразу, коли я починаю новий проект, я починаю в одному напрямку і врешті-решт проектую його по-різному.

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

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

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


100

Це дуже поширений досвід

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

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

"У кожного є план, поки їм не вдаряться в обличчя".

Що з цим робити

До певної міри вам доведеться навчитися приймати, що ваш код ніколи не буде ідеальним. Одне, що мені допомогло в цьому, - це мислення «Якщо я ненавиджу код, який я написав місяць тому, це означає, що я навчився і став кращим програмістом».

Спосіб полегшити проблему - постійно шукати можливі вдосконалення під час постійної роботи та рефакторації. Не забудьте досягти хорошого балансу між рефакторингом та додаванням нових функцій / виправлення помилок. Це не допоможе з великими проблемами дизайну, але, як правило, ви отримаєте більш відшліфовану базу коду, якою ви можете пишатися.


18
Єдине, що я хотів би додати до цієї відповіді, це вивчити та дотримуватися принципів TDD під час написання коду. Потім ці тести забезпечують безпечне середовище для перефактурування та перезапису, оскільки ви продовжуєте удосконалюватись як розробник і хочете внести зміни до існуючого коду.
Девід Арно

10
@DavidArno в чому сенс рефакторингу присутніх тестів? Це як модернізувати систему та зробити резервну копію перед ... 0 розвагою.
Джуріс

3
@ Džuris, :) Правда, якщо вам подобаються виклики, не пишіть тести
Девід Арно,

6
@ Džuris Це як вистрибувати з літака, носити парашут!
JollyJoker

3
@jamesqf - Це неправильна характеристика того, що роблять тести TDD та unit - наприклад, вони можуть сказати вам, що ваша модель чи алгоритм реалізовані правильно і що ви нічого не зламали під час рефактора. Вони не можуть сказати вам, що ваша модель насправді корисна. Це так само правдиво в науковому середовищі, як і в будь-якому іншому.
Мураха P

46

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

Але ви повинні мати можливість трансформувати існуючий код, щоб застосувати ці вдосконалення, не починаючи з нуля.


4
Ця практика також допоможе вам навчитися писати модульний код і його можна буде легше відновити. Всі лекції в світі не навчили мене цієї звички настільки, як потрібно розбивати старі великі функції на керовані шматки, тому мені не доведеться переписувати з нуля. З кожним новим проектом я в цьому краще.
JKreft

Найкращий вихідний пункт, на мій погляд, дізнатися про рефакторинг - це: Рефакторинг - це нові функції
Wildcard

9

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

Навіть у цьому блаженному випадку ви можете вивчити нові мовні функції, які допомогли б зробити кращий дизайн.

Однак зазвичай вам не пощастить: вимоги будуть меншими, ніж зоряними та неповними, і хоча ви думали, що ви їх зрозуміли, виявляється, що є сфери, щодо яких ви зробили недійсні припущення.

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

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

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

Зрештою, прийміть, що зміна є постійною, і ігноруйте тугу, яка говорить "Я міг би зробити це краще". Будь гордий і щасливий, що ти взагалі поставив рішення.


Або, по-іншому: навчіться проектувати для гнучкості з самого початку, не вводячи зайві накладні витрати. В ідеалі гнучкість випливає з простоти. Тоді ваш дизайн має шанс пройти перевірку змін вимог.
cmaster

3

Як я можу уникати того, щоб завжди відчувати себе так, якби я повністю переобладнав свою програму з нуля, я б зробив це набагато краще?

Що ви можете зробити, це створити прототип, що викидається, перш ніж почати робити "справжній" проект. Швидкий і брудний. Потім, коли ви отримаєте прототип для доведення концепції, ви познайомитесь з системою та як правильно робити речі.

Але не дивуйся, якщо через N років ти повернешся до цього коду і подумаєш «який безлад».


3
Або ви показуєте прототип своєму начальнику, він каже: "Блискуче, це все зробиться". переміщує вас на інший проект, і ваш прототип стає виробництвом.
RyanfaeScotland

2
Ця порада настільки поширена, що про неї є приказка. "Побудувати одного, щоб викинути". І ця порада настільки зловживається, що про неї є приказка: "Якщо ви побудуєте одну, щоб викинути, ви, ймовірно, викинете два".
Ерік Ліпперт

2
@EricLippert Мій досвід був жахливим у зворотному напрямку - якщо ми створимо його, щоб викинути, він неминуче доставляється замовнику.
Джон

2
@Jon: Так, це може статися, особливо коли помилки управління "користувальницький інтерфейс виглядає так, як він працює", там фактично є будь-який код. Однак, мій досвід завжди був, як колись із моїх колег говорили, що "у нас є достатньо часу для того, щоб побудувати його неправильно вдвічі, але недостатньо часу, щоб правильно його побудувати один раз". :-)
Ерік Ліпперт

@EricLippert Саме це є причиною останнього побудови графічного інтерфейсу, а НЕ побудови графічного інтерфейсу для прототипу;)
BЈович

3

Запам’ятайте цю мантру:

Ідеальний - ворог добра .

Ідеальне рішення не завжди є ідеальним рішенням. Ідеальним рішенням є той , який отримує статус «досить добре» з найменшою кількістю роботи.

  • Чи відповідає він усім вимогам щодо функціональності та продуктивності?
  • Це вільно від критичних помилок, які ви не можете виправити в поточній архітектурі?
  • Оцініть, скільки роботи ви вкладете в підтримку цього додатка в майбутньому. Невже зусилля для переписування будуть більшими, ніж багаторічні зусилля, які вони заощадять?
  • Чи є можливість, що ваш новий дизайн насправді може погіршити ситуацію?

Якщо ви відповідаєте "так" на всі ці питання, то ваше програмне забезпечення є "досить хорошим", і немає жодних вагомих причин переписати його з нуля. Застосуйте уроки дизайну, які ви засвоїли, до свого наступного проекту.

Цілком нормально, щоб кожен програміст мав пару безладних програм у своєму минулому. За мою кар'єру розробника програмного забезпечення це траплялося кілька разів, коли я переглянув якийсь код, запитав "Який ідіот написав цей безлад?", Перевірив історію версій і помітив, що це я кілька років тому.


3

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

Заманливо думати, що ідеальне планування дасть вам ідеальний дизайн / архітектуру програмного забезпечення, однак, виявляється, це категорично помилково. З цим є дві великі проблеми. По-перше, "на папері" та "коді" рідко збігаються, і причина полягає в тому, що легко сказати, як це потрібно зробити, а не насправді робити це . По-друге, непередбачені зміни вимог стають очевидними в процесі розробки, про які не можна було міркувати з самого початку.

Ви чули про рухливий рух? Це спосіб мислення, де ми цінуємо "реагування на зміни", а не "слідуючи за планом" (серед іншого). Ось маніфест (це швидке читання). Ви також можете прочитати про Великий дизайн переднього фронту (BDUF) та які підводні камені.

На жаль, корпоративна версія "Agile" - це купа хибних (сертифіковані майстри scrum, важкий процес на ім'я "Agile", примушування scrum, примушування 100% покриття коду тощо), і зазвичай призводить до зміни процесів асиніну, оскільки менеджери думаю, що 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): і можу також стверджувати, що він надзвичайно добре працює для даного домену.

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

Як я можу уникати того, щоб завжди відчувати себе так, якби я повністю переобладнав свою програму з нуля, я б зробив це набагато краще?

З огляду на вищесказане, має бути дещо очевидним, що ідеального дизайну насправді неможливо досягти, тому переслідувати ідеальний дизайн - це дурні ігри. Ви дійсно можете лише наблизитися. Навіть якщо ви думаєте, що можете переробити з нуля, мабуть, все ще є приховані вимоги, які не проявили себе. Крім того, переписування займає щонайменше стільки, скільки потрібно для розробки оригінального коду. Це майже напевно не буде коротшим, оскільки, ймовірно, новий дизайн матиме власні непередбачені проблеми, плюс вам доведеться знову реалізувати всі функції старої системи.

Інша річ, яку слід врахувати, - це те, що ваш дизайн дійсно має значення лише при зміні вимог .Не має значення, наскільки дизайн поганий, якщо нічого ніколи не змінюється (якщо припустити, що він повністю функціональний для поточних випадків використання). Я працював над базовою лінією, в якій було 22000 операторів комутації ліній (функція була ще довшою). Це був жахливий дизайн? Чорт забирай, це було жахливо. Ми це виправили? Ні. Це працювало чудово, як було, і ця частина системи ніколи насправді не спричиняла збоїв чи помилок. Це торкнулося лише один раз за два роки, коли я був над проектом, і хтось, як ви здогадалися, вставив ще один випадок у вимикач. Але не варто витрачати час на те, щоб виправити щось, що торкається так рідко, це просто не так. Нехай недосконала конструкція буде такою, якою вона є, і якщо вона не зламалася (або постійно ламалася), тоді не виправляйте її. Тож, може, ти зможеш зробити краще ... але чи варто було б переписати? Що ви здобудете?

HTH.


2

Я повністю згоден з відповіддю, поданим Андреасом Камерлохером, але я здивований, що ніхто ще не запропонував вивчити та застосувати деякі найкращі практики кодування. Звичайно, це не срібна куля, але використання відкритого орієнтованого підходу, моделей дизайну, розуміння того, коли ваш код пахне тощо, зробить вас кращим програмістом. Дослідіть, що найкраще використовувати бібліотеки, рамки тощо. Напевно, ще багато чого, я просто дряпаю поверхню.

Це не означає, що ви не будете дивитися на свій старий код як на загальний сміття (ви насправді побачите найдавніші програми ще більше сміття, ніж ви без цього знання), але з кожним новим програмним забезпеченням, яке ви пишете, ви побачите ви вдосконалюєтесь. Зауважте також, що кількість найкращих методів кодування з часом збільшується, а деякі просто змінюються, так що ви насправді ніколи не досягнете досконалості. Прийміть цей або зовсім шлях.

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


1

Щоб додати до інших відмінних відповідей тут, одна річ, я вважаю корисною, це знати, куди ви хочете потрапити .

Рідко можна давати рушій для власного капітального рефакторингу. Але ви часто можете робити менші шматочки рефакторингу під час руху "під радаром" під час роботи над кожною областю кодової бази. І якщо у вас є мета, ви можете скористатися цими можливостями рухатися, крок за кроком, у правильному напрямку.

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

Крім того, відчуття, ніби ти міг би зробити краще - хороший знак ! Це показує, що ви дбаєте про якість своєї роботи, і що ви її критично оцінюєте; тож ви, мабуть, навчаєтесь та вдосконалюєтесь. Не дозволяйте цим речам вас хвилювати - але не переставайте їх робити!


1

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

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

Так, ви спробуєте TDD, Refactoring, функціональне програмування, шаблон сховища, пошук подій, MV щось, сценарій Java (<- зробіть це, це божевільно), прив'язка моделі, No Sql, контейнери, Agile, SQL (<- зробіть це це потужно).

Немає жодної виправлення. Навіть експерти все ще хапаються за соломинку.

Ласкаво просимо, і будьте попереджені, це самотнє місце; але абсолютно захоплююче


1

Я трохи піду проти зерна. Це неймовірно часто , але це не прийнятно . Це свідчить про те, що ви не розпізнаєте хороших способів організації свого коду під час його написання. Відчуття виходить від того, що ваш код не є простим .

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

  1. Будьте чіткі щодо того, які припущення робить якийсь конкретний блок коду. Накиньте помилки, якщо їх не виконано. Подумайте про це поодиноко , не залежно від подробиць про те, що робить решта програмного забезпечення. (Те, що решта програмного забезпечення робить, впливає на те, які припущення виконуються та які випадки використання ви підтримуєте, але це не впливає на те, чи ви видаєте помилку, коли припущення порушено.)
  2. Перестаньте вірити, що дотримання правил, моделей та практик призведе до хорошого коду. Викиньте мислення та практики, які не є очевидними та відвертими. Цей був величезний. OO і TDD зазвичай викладаються таким чином, що не ґрунтуються на практичних міркуваннях, як набір абстрактних принципів, яких слід дотримуватися під час написання коду. Але це абсолютно не корисно для насправді розробки хорошого коду. Якщо ви взагалі використовуєте OO або TDD, його слід використовувати як рішення проблем, які ви розумієте . Іншими словами, їх слід використовувати лише тоді, коли ви дивитесь на проблему і думаєте: "Гаразд, це має повний сенс і є надзвичайно очевидним як хороше рішення". Не раніше.
  3. Коли я пишу код, зосередьтеся на двох питаннях:
    • Чи використовую я функції та бібліотеки так, як вони були розроблені для використання ? Це включає використання його для тих чи інших проблем, які він мав вирішити, або, принаймні, дуже подібних.
    • Це просто ? Чи зможуть згодом мої колеги і я легко слідувати логіці? Чи є речі, які не відразу очевидні з коду?

Мій код тепер є більш "процедурним", під яким я маю на увазі, що він організований за тими діями, які він здійснює, а не тим, які структури даних він використовує. Я використовую об'єкти мовами, де автономні функції не можуть бути замінені на льоту (C # і Java не можуть замінити функції на льоту, Python може). Зараз у мене є тенденція створювати більше корисних функцій, які просто відштовхують якусь дратівливу панель, щоб я міг прочитати логіку свого коду. (Наприклад, коли мені потрібно було обробити всі комбінації елементів у списку, я підсунув петельне покажчик до методу розширення, який повертаєTuples, щоб оригінальна функція не була захаращена тими деталями реалізації.) Я передаю набагато більше речей у якості параметрів функціям зараз, замість того, щоб функція доходила до якогось іншого об'єкта, щоб отримати його. (Абонент отримує або створює його замість цього і передає.) Тепер я залишаю більше коментарів, які пояснюють речі, які не очевидні лише з огляду на код , що полегшує дотримання логіки методу. Я пишу тести лише в обмежених випадках, коли мене хвилює логіка чогось, що я щойно зробив, і уникаю використання макетів. (Я роблю більше тестування вводу / виводу на ізольованих фрагментах логіки.) Результатом є код, який не є ідеальним , але це насправді здається нормальним, навіть через 2 або 3 роки. Це код, який досить добре реагує на зміни; незначні речі можна додавати або вилучати чи змінювати, не розвалюючись усією системою.

До певної міри вам доведеться пройти період, коли все стоїть безлад, щоб у вас був певний досвід. Але якщо все ще настільки переплутано, що ви хочете все це відкинути і почати спочатку, щось не так; ти не вчишся.


0

Пам'ятаючи, що ваш час обмежений. І ваш майбутній час також обмежений. Що стосується роботи чи школи чи особистих проектів, коли мова заходить про робочий код, ви повинні запитати себе: «чи переписує це найкраще використання мого обмеженого та цінного часу?». Чи, може, "це найбільш відповідальне використання мого обмеженого часу"?

Іноді відповідь буде однозначно так . Зазвичай ні. Іноді це буде на паркані, і вам доведеться використовувати свій розсуд. Іноді добре використовувати свій час просто через те, що ти навчишся робити це.

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


0

Це абсолютно нормальна частина навчання. Ти розумієш помилки, коли йдеш.

Саме так вам стає краще, і вам не слід цього уникати.


0

Ви можете дати собі досвід знати, що спокусливий потяг до переписування зазвичай непродуктивний. Знайдіть старий, волохатий, неелегантний проект з відкритим кодом середньої складності. Спробуйте переписати його з нуля і подивіться, як ви робите.

  • Ваш дизайн з нуля закінчився настільки елегантним, як ви сподівалися?
  • Чи є ваше рішення справді такою ж точною проблемою? Які особливості ви залишили без уваги? Які крайові випадки ви пропустили?
  • Які важко зароблені уроки в оригінальному проекті ви стирали, прагнучи до елегантності?
  • Після того, як ви знову додасте ці недоліки до свого дизайну, чи це так чисто, як без них?

Врешті-решт ваш інстинкт перейде від мислення "я міг би переписати цю систему набагато краще" до думки "чіткість цієї системи може свідчити про певну складність, яка не відразу видно".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.