Програмування чисто при написанні наукового коду


169

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

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

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

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

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

Чи потрібно тестування одиниць для написання менших фрагментів коду? Як щодо OOP? Які підходи корисні для швидкого написання хорошого, чистого коду при виконанні "наукового програмування" на відміну від роботи над великими проектами?

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

Можливо, це занадто широко, і якщо так, я вибачаюся, але дивлячись на книги з програмування, вони, здається, часто звертаються до великих проектів. Мій код не потребує OOP, і він вже досить проклятий, тому він не схожий на "о, але файл буде зменшено на тисячу рядків, якщо ми це зробимо!" Хочеться знати, як «почати все з початку» та чітко програмувати ці менші, швидші проекти.

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


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

Є винятки. Далі, мабуть, існують стандарти наукового програмування, що виходять за рамки простих стандартів. Я також про це запитую. Йдеться не про те, чи слід ігнорувати нормальні стандарти кодування під час написання наукового коду, це про написання чистого наукового коду!


Оновлення

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

Я також встановив pylint і запустив його на весь свій код. Один файл спочатку отримав негативну оцінку; Я навіть не впевнений, як це було можливо. Головний мій файл розпочався з оцінки ~ 1,83 / 10 і тепер становить ~ 9,1 / 10. Весь код тепер досить добре відповідає стандартам. Я також наткнувся на це власними очима, оновивши імена змінних, що пішли ... е-е-м ... помилково, і шукав розділи для рефактора.

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

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

Я також значно оновив документацію, про яку я вже писав, і додав додаткові файли, такі як таблиця Excel, документація та пов'язаний папір до сховища github. Це ніби зараз справжній проект програмування.

Отже ... я думаю, це все, щоб сказати: дякую .



9
Ви можете знайти відповідь на те, чи варто писати одиничні тести для науково-дослідних кодів? корисний.
Марк Бут

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

7
Коли ви говорите "окрім використання контролю версій та створення нового файлу для кожної нової ітерації та записування всього цього в текстовий файл десь" за "і" ви маєте на увазі "або", тому що якщо ви використовуєте контроль версій, ви не повинні Не можна копіювати вставкові версії. Справа в тому, що контроль над версіями зберігає всю стару версію для вас
Річард Тінгл

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

Відповіді:


163

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

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

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

Ваша основна проблема полягає у читанні, тому ось декілька порад щодо покращення:

Імена змінних:

Вчені люблять використовувати стислі позначення. Усі математичні рівняння зазвичай використовують одні літери як змінні, і я не здивуюсь, коли у вашому коді можна побачити багато та безліч дуже коротких змінних. Це дуже шкодить читабельності. Коли ви повернетесь до свого коду, ви не пам’ятатимете, що представляють ті y, i та x2, і ви витратите багато часу, намагаючись розібратися в цьому. Спробуйте замість того, щоб чітко називати свої змінні, використовуючи імена, які точно представляють, якими вони є.

Розділіть свій код на функції:

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

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

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

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

Глобальні змінні:

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

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

Контроль версій

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

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


56
Відмінна порада. Однак я не можу підтримати коментар "це не так вже й погано". Це так погано. Наукові сценарії низької якості є великою проблемою для відтворюваності в аналізі даних та частим джерелом помилок в аналізі. Писати хороший код цінний не лише для того, щоб ви могли його зрозуміти пізніше, але й для того, щоб уникнути помилок в першу чергу.
Джек Едлі

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

11
@cHao проблема полягає не в тому, що ці змінні підключаються до формули (отже, поради "перейменуйте їх всередині функції"), а коли вони читаються та маніпулюють поза нею, і коли вони починають конфліктувати з іншими змінними внизу лінії (наприклад, я бачив людей, які потребують трьох змінних "x", називають їх x1, x2, x3)
BgrWorker

4
"Я піду проти здорового глузду ..." Ні, ти не є. Ти йдеш проти пануючої догми, яка сама проти здорового глузду. ;) Це все ідеально обгрунтована порада.
jpmc26

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

141

Тут фізик. Був там.

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

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

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

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

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

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

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


32
«Писати чистий код точно так само, як писати чітку статтю». Я цілком схвалюю це, добре кажучи!
юндесант

43
Це те, що більшість професійних програмістів забувають сказати, оскільки це так очевидно. Ваш код готовий, коли його можна прочитати та змінити іншим програмістом. Не тоді, коли він працює і дає правильний вихід. ОП потрібно витратити і додатково годину на переробку сценарію та коментування свого коду, щоб зробити його читабельним.
УЄФІ

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

3
@UEFI Ні, це більшість професійних програмістів навіть не усвідомлюють. Або не байдуже.
jpmc26

2
Погодьтеся на 100%. Статистик звернувся до програміста, тож я займаюся неабиякою науковою програмою на роботі. Ясний код із змістовними коментарями - рятівник, коли вам доведеться повернутися до цього коду через 1, 4 чи 12 місяців. Читання коду говорить вам, що код робить. Читання коментарів говорить вам про те, що повинен робити код.
рейлигдог

82

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

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

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

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


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

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

18
Зі сторони, керування версіями також дуже добре працює для документів LaTeX, оскільки формат піддається текстовому різницю. Таким чином, ви можете мати сховище як для своїх паперів, так і для коду, який їх підтримує. Я пропоную вивчити контроль розподілених версій, наприклад, Git. Існує трохи кривої навчання, але як тільки ви це зрозумієте, у вас є чудовий чистий спосіб змінити свій розвиток, і у вас є кілька цікавих варіантів використання платформи на зразок Github, яка пропонує безкоштовні облікові записи команди для вчених .
Ден Брайант

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

7
"Між контролем версій та тестуванням одиниць написання, коди, звичайно, стануть набагато чистішими." Це НЕ вірно. Я можу це засвідчити особисто. Жоден із цих інструментів не зупиняє вас на написанні шаленого коду, і, зокрема, написання шалених тестів на вершині шаленого коду просто ускладнює прибирання. Тести - це не чарівна срібна куля, і говорити так, як вони є, це жахливо робити будь-якому розробнику, який ще вивчає (який є у всіх). Контроль версій, як правило, ніколи не завдає шкоди самому коду, як це робить погане тестування.
jpmc26

29

(окрім використання контролю версій та створення нового файлу для кожної нової ітерації та записування всього цього в текстовий файл десь, що, ймовірно, допоможе сильно ситуацію)

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

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

Чи потрібно тестування одиниць для написання менших фрагментів коду? Як щодо OOP? Які підходи корисні для швидкого написання хорошого, чистого коду при виконанні "наукового програмування" на відміну від роботи над великими проектами?

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

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


4
+1 для повідомлень про фіксацію; вони схожі на коментарі, які не можуть застаріти, оскільки вони прив’язані до версії коду, коли вони були дійсно застосовні. Щоб зрозуміти ваш старий код, простіше переглянути історію проекту (якщо зміни здійснюються з розумною деталізацією), ніж читати застарілі коментарі.
Дурний фрік

Subversion, git і Mercurial не підлягають зміні. Я наполегливо рекомендую використовувати Git (або Mercurial) з локальним сховищем для Subversion. З соло-кодером недоліки Subversion є меншою проблемою, але це не чудовий інструмент для спільного розвитку, і це може статися при дослідженні
mcottle

2
@mcottle, я особисто віддаю перевагу git, але я не вважав, що це правильне місце, щоб розібратися в деталях про відмінності, тим більше, що вибір є однією з активних релігійних війн. Краще закликати ОП використовувати щось, ніж відлякувати їх далеко від району, і рішення не є постійним у будь-якому випадку.
Пітер Тейлор

21

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

Якщо ви пишете сценарії для виконання наукових обчислень, у вас, ймовірно, є документи з рівняннями або алгоритмами, які ви використовуєте. Якщо ви використовуєте нові ідеї, які ви відкрили самостійно, сподіваємось опублікувати їх у власних документах. У цьому випадку діє правило: Ви хочете, щоб ваш код читав якнайбільше опублікованих рівнянь. Ось відповідь на Software Engineering.SE з більш ніж 200 звернень, які виступають за такий підхід і пояснюють, як це виглядає: Чи є привід для коротких імен змінних?

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

ContactGeometry.cpp:

// t = (-b +/- sqrt(b^2-4ac)) / 2a
// Discriminant must be nonnegative for real surfaces
// but could be slightly negative due to numerical noise.
Real sqrtd = std::sqrt(std::max(B*B - 4*A*C, Real(0)));
Vec2 t = Vec2(sqrtd - B, -sqrtd - B) / (2*A);

ContactGeometry_Sphere.cpp:

// Solve the scalar Jacobi equation
//
//        j''(s) + K(s)*j(s) = 0 ,                                     (1)
//
// where K is the Gaussian curvature and (.)' := d(.)/ds denotes differentiation
// with respect to the arc length s. Then, j is the directional sensitivity and
// we obtain the corresponding variational vector field by multiplying b*j. For
// a sphere, K = R^(-2) and the solution of equation (1) becomes
//
//        j  = R * sin(1/R * s)                                        (2)
//          j' =     cos(1/R * s) ,                                      (3)
//
// where equation (2) is the standard solution of a non-damped oscillator. Its
// period is 2*pi*R and its amplitude is R.

// Forward directional sensitivity from P to Q
Vec2 jPQ(R*sin(k * s), cos(k * s));
geod.addDirectionalSensitivityPtoQ(jPQ);

// Backwards directional sensitivity from Q to P
Vec2 jQP(R*sin(k * (L-s)), cos(k * (L-s)));
geod.addDirectionalSensitivityQtoP(jQP);

9
Плюс один для того, щоб зробити їх «кодом, щоб прочитати якомога більше схожих на опубліковані рівняння». Вибачте, прихильники довгих, змістовних імен змінних. Найбільш змістовні назви в науковому кодексі часто є бридкими, короткими і бридкими саме тому, що саме ця конвенція використовується в науковому журналі, який намагається реалізувати. Для важкого рівняння коду, який реалізує рівняння, знайдені в журналі, найчастіше найкраще залишатися наближеним до номенклатури в роботі, і якщо це суперечить зерну добрих стандартів кодування, важко.
Девід Хаммен

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

1
@DavidHammen Крім того, підтримка Python для UTF-8 у вихідних файлах та прості правила змінних імен полегшує оголошення λабо φзамість негарних lambda_чи phy...
Mathias Ettinger

1
@tonysdg У вас вже є посилання; її називають "Hammen, et al. (2018)" (або що завгодно). Це пояснить значення змінних набагато детальніше, ніж будь-який блок коментарів коли-небудь міг. Причина, щоб імена змінних були близькими до позначень у документі, саме в тому, щоб полегшити зв'язок того, що знаходиться в папері, з тим, що в коді.
Ніхто

17

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

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

З цією метою, якщо ви хочете чогось конкретного, орієнтованого на дослідників, а не на загальних розробників програмного забезпечення, я не можу досить рекомендувати організацію Software Carpentry . Якщо ви можете відвідати один з їхніх семінарів , чудово; якщо все, що у вас є час / доступ, - це прочитати деякі їх статті про найкращі практики наукових обчислень , це теж добре. З останнього:

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

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

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

Концепція практичних рекомендацій, які вони рекомендують:

  1. Пишіть програми для людей, а не комп’ютерів
  2. Нехай комп’ютер виконує роботу
  3. Внесіть додаткові зміни
  4. Не повторюйте себе (або інших)
  5. Плануйте помилки
  6. Оптимізуйте програмне забезпечення лише після правильної роботи
  7. Дизайн та призначення документа, а не механіка
  8. Співпрацювати

У цьому документі детально описується кожен із цих питань.


16

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

Особиста відповідь:
Я дуже багато творять сценарії і в наукових цілях. Для менших сценаріїв я просто намагаюся дотримуватися загальних добрих практик програмування (тобто, використовуючи контроль версій, практикую самоконтроль зі змінними назвами). Якщо я просто пишу щось для швидкого відкриття або візуалізації набору даних, я не турбуюся з OOP.

Загальна відповідь:
"Це залежить". Але якщо ви намагаєтеся розібратися, коли використовувати програмування або парадигми, ось про що слід подумати:

  • Масштабованість: сценарій буде самостійним, чи він врешті-решт буде використаний у більшій програмі? Якщо так, то чи більше програмування використовує OOP? Чи може код у вашому сценарії легко інтегруватися у більшу програму?
  • Модульність: загалом ваш код повинен бути модульним. Однак OOP розбиває код на шматки дуже особливим чином. Чи має такий тип модульності (тобто розбиття сценарію на класи) має сенс для того, що ви робите?

Хочеться знати, як «почати все з початку» та чітко програмувати ці менші, швидші проекти.

№1: Ознайомтеся з тим, що там:
Навіть якщо ви "просто" розробляєте сценарії (і ви дійсно просто піклуєтесь про науковий компонент), вам слід трохи часу ознайомитись з різними концепціями та парадигмами програмування. Таким чином, ви можете мати краще уявлення про те, що слід / чого не потрібно використовувати та коли. Це може здатися трохи страшним. І у вас все ще може виникнути питання: "З чого я починаю / з чого починаю дивитись?" Я намагаюся пояснити хороший вихідний пункт у наступних двох пунктах кулі.

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

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

№4: Шукайте консорціуми:
я не знаю, в якій науковій галузі ви перебуваєте. Але залежно від того, чим займаєтесь у науковому світі, спробуйте шукати консорціуми, робочі групи чи учасників конференції. Потім подивіться, чи існують якісь стандарти, над якими вони працюють. Це може призвести до деяких стандартів кодування. Наприклад, я роблю багато геопросторових робіт. Переглядаючи доповіді конференції та робочі групи привели мене до Відкритого геопросторового консорціуму . Одна з речей, яку вони роблять, - це робота над стандартами геопросторового розвитку.

Я сподіваюся, що це допомагає!


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


Я думаю, що №3 є найважливішим питанням - досвідчений програміст може розповісти ОП потрібні їм концепції (№1), як краще організувати сценарії та як використовувати контроль версій (№2).
Док Браун

16

Я рекомендую дотримуватися принципу Unix: Тримайте це просто, тупо! (KISS)

Або, по-іншому: робіть по одній справі, і робіть це добре.

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

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

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

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

Анекдот
Я одного разу провів кілька місяців рефакторингу коду, який мав функції приблизно по 500 рядків. Після того як я закінчив, загальний код став приблизно на тисячу рядків коротшим; Я отримав негативний вихід у вигляді рядків коду. Я заборгував компанії ( http://www.geekherocomic.com/2008/10/09/programmers-salary-policy/index.html ). І все-таки я твердо вірю, що це була одна з моїх найцінніших робіт, яку я коли-небудь робив ...

Деякі функції можуть бути довгими, оскільки вони виконують кілька чітких речей одна за одною. Це не сухі порушення, але їх також можна розділити. Результатом цього є часто функція високого рівня, яка викликає безліч функцій, які реалізують окремі кроки оригінальних функцій. Це, як правило, збільшує розмір коду, але додані імена функцій творить чудеса, роблячи код більш читабельним. Тому що тепер у вас функція вищого рівня, усі її кроки явно названі. Крім того, після цього розколу зрозуміло, який крок діє, на яких даних. (Аргументи функції. Ви не використовуєте глобальних змінних, чи не так?)

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

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

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


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

@Jaquez Ах, зовсім забув про це. Дякую, що нагадали. Я оновив свою відповідь, щоб включити її :-)
cmaster

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

11

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

  • Немає необхідності вести список змін, які були внесені або чимало копій файлу тощо, оскільки саме так слід контролювати контроль версій.
  • Більше немає файлів, втрачених через перезаписи тощо (до тих пір, поки ви просто дотримуєтесь основ; наприклад, уникайте "переписування історії")
  • Немає необхідності в застарілих коментарях, мертвому коді тощо, щоб вони трималися навколо "про всяк випадок"; Після того, як вони зобов'язані контролювати версії, сміливо стримуйте їх. Це може бути дуже визвольним!

Я б сказав, не передумуйте: просто використовуйте git. Дотримуйтесь простих команд (наприклад, лише однієї masterгілки), можливо, використовуйте графічний інтерфейс, і вам слід добре. Як бонус ви можете використовувати gitlab, github тощо для безкоштовного публікації та резервного копіювання;)

Причиною, що я написав цю відповідь, було звернутися до двох речей, які ви можете спробувати, що я не бачив згаданого вище. Перший - використовувати твердження як легку альтернативу одиничному тестуванню. Тестові одиниці, як правило, знаходяться «поза» функції / модуля / що б не тестували: вони зазвичай надсилають деякі дані у функцію, отримують результат назад, а потім перевіряють деякі властивості цього результату. Це, як правило, гарна ідея, але може бути незручним (особливо для коду "викинути") з кількох причин:

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

У тверджень немає цих недоліків, оскільки вони перевіряються під час нормального виконання програми. Зокрема:

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

Ви згадуєте швидкість як фактор, і в цьому випадку перевірка тверджень може бути небажаною в цьому циклі (але все-таки корисна для перевірки налаштування та подальшої обробки). Однак майже всі реалізації тверджень надають спосіб їх вимкнення; наприклад, у Python їх, очевидно, можна відключити, запустивши -Oпараметр (я цього не знав, оскільки раніше ніколи не відчував потреби відключати жодне зі своїх тверджень). Я рекомендував би залишити їх наза замовчуванням; якщо ваш цикл кодування / налагодження / тестування сповільнюється, можливо, вам буде краще провести тестування з меншим набором даних або виконати меншу кількість ітерацій симуляції під час тестування чи будь-чого іншого. Якщо ви припиняєте відключення тверджень у нетестових запусках з міркувань продуктивності, перше, що рекомендую вам зробити, - це виміряти, чи вони насправді є джерелом уповільнення! (Дуже легко обманути себе, коли мова йде про ефективні вузькі місця)

Моєю останньою порадою буде використання системи побудови, яка керує вашими залежностями. Я особисто використовую Nix для цього, але чую хороші речі і про Guix . Є також такі альтернативи, як Докер, які з наукової точки зору набагато менш корисні, але, можливо, трохи більш звичні.

Такі системи, як Nix, лише останнім часом стають (трохи) популярними, і деякі можуть вважати їх надмірними для «викидання» коду, як ви описуєте, але їх користь для відтворюваності наукових обчислень величезна. Розглянемо сценарій оболонки для запуску експерименту, наприклад (наприклад run.sh):

#!/usr/bin/env bash
set -e
make all
./analyse < ./dataset > output.csv

Ми можемо замість цього переписати його в «Nix», наприклад так run.nix:

with import <nixpkgs> {};
runCommand "output.csv" {} ''
  cp -a ${./.} src
  cd src
  make all
  ./analyse < ./dataset > $out
''

Між ними ''...''є bash-код, такий самий, як у нас раніше, за винятком того, що він ${...}може бути використаний для "сплайсингу" у вмісті інших рядків (у цьому випадку ./.він розшириться до шляху каталогу, що містить run.nix). with import ...Лінія імпортує Нікс в стандартну бібліотеку , яка забезпечує runCommandдля запуску коду Баш. Ми можемо запустити експеримент за допомогою nix-build run.nix, який видасть такий шлях /nix/store/1wv437qdjg6j171gjanj5fvg5kxc828p-output.csv.

То що ж це купує у нас? Nix автоматично встановить "чисте" середовище, яке має доступ лише до речей, про які ми прямо вимагали. Зокрема, він не має доступу до таких змінних, як $HOMEбудь-яке системне програмне забезпечення, яке ми встановили. Це робить результат незалежним від деталей нашої поточної машини, як-от вмісту ~/.configабо версій програм, які ми встановили; AKA матеріал, який заважає іншим людям повторювати наші результати! Ось чому я додав цеcpкоманда, оскільки проект за замовчуванням не буде доступний. Може здатися прикрою, що програмне забезпечення системи не доступне для сценарію Nix, але це також іншим шляхом: нам не потрібно нічого, встановленого в нашій системі (крім Nix), щоб використовувати його в сценарії; ми просто просимо про це, і Nix піде і вибере / компілює / все необхідне (більшість речей буде завантажено у вигляді бінарних файлів; стандартна бібліотека також величезна!). Наприклад, якщо ми хочемо купувати певні пакети Python та Haskell, для деяких конкретних версій цих мов, а також для деяких інших мотлоху (бо чому б ні?):

with import <nixpkgs> {};
runCommand "output.csv"
  {
    buildInputs = [
      gcc49 libjson zlib
      haskell.packages.ghc802.pandoc
      (python34.withPackages (pyPkgs: [
        pyPkgs.beautifulsoup4 pyPkgs.numpy pyPkgs.scipy
        pyPkgs.tensorflowWithoutCuda
      ]))
    ];
  }
  ''
    cp -a ${./.} src
    cd src
    make all
    ./analyse < ./dataset > $out
  ''

Це ж nix-build run.nixбуде виконувати це, витягуючи все, про що ми попросили спочатку (і кешувати все це у випадку, якщо ми хочемо цього пізніше). Вихід (будь-який названий файл / каталог $out) буде зберігатися Nix, тобто це шлях, який він випливає. Він ідентифікується за допомогою криптографічного хешу усіх запитуваних нами входів (вміст сценарію, інші пакунки, імена, прапорці компілятора тощо); ці інші пакети ідентифікуються хешами їх вхідних даних і так далі, що у нас є повний ланцюг провінцій для всього, від версії до версії GCC, яка склала версію GCC, яка склала bash, і так далі!

Сподіваюся, я показав, що це купує нам багато для наукового коду, і це досить легко почати. Вчені також починають сприйматись дуже серйозно, наприклад (найкращий хіт Google) https://dl.acm.org/citation.cfm?id=2830172, тому це може бути цінним навиком культивування (як і програмування)


2
Дуже детальна корисна відповідь - мені дуже подобаються інші відповіді, але твердження звучать як дуже корисний перший крок.
Хізер

9

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

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


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

Для тих, хто хоче прочитати більше, це також відоме як грамотне програмування.
llrs

6

Верхні відповіді вже хороші, але я хотів би безпосередньо звернутися до деяких ваших питань.

Чи потрібно тестування одиниць для написання менших фрагментів коду?

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

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

Скажімо, у вас є додаток, де Бібліотека A здійснює квадратування чисел, а Бібліотека B застосовує теорему Піфагора. Очевидно, що B залежить від A. Вам потрібно щось виправити в бібліотеці A, і скажімо, ви вводите помилку, яка нарізає куби замість того, щоб розбивати їх.

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

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

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

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

Як щодо OOP?

OOP - це спосіб мислення про окремі сутності, наприклад:

Коли Customerхоче придбати гроші Product, він розмовляє з тим, Vendorщоб отримати його Order. Тоді Accountantзаповіт заплатить Vendor.

Порівняйте це з тим, як функціональний програміст думає про речі:

Коли замовник захоче purchaseProduct(), він talktoVendor()так йому зробить sendOrder(). Тоді бухгалтер буде payVendor().

Яблука та апельсини. Жоден з них об'єктивно не кращий за інший. Цікавим є те, що для OOP Vendorзгадується двічі, але це стосується того ж самого. Однак для функціонального програмування є talktoVendor()і payVendor()дві окремі речі.
Це демонструє різницю між підходами. Якщо між цими двома діями існує велика кількість загальної логіки, що залежить від постачальника, OOP допоможе зменшити дублювання коду. Однак якщо між ними немає спільної логіки, то об'єднання їх в єдине Vendorє марною роботою (і, отже, функціональне програмування є більш ефективним).

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

Які підходи корисні для швидкого написання хорошого, чистого коду при виконанні "наукового програмування" на відміну від роботи над великими проектами?

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

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

Тут повертається той самий аргумент.

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

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

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

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

Принципи OOP осторонь, головна причина, по якій я пишу класам, щоб зберігати кілька значень даних, полягає в тому, що це спрощує оголошення параметрів методу та повернення значень. Наприклад, якщо у мене є маса методів, які використовують місцеположення (лат / лон-пара), я швидко втомлюся від необхідності набирати текст float latitude, float longitudeі буду вважати за краще писати Location loc.

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

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

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

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

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

Клас завжди такий же великий, як сума його полів. Беручи приклад Locationзнову, який складається з двох floatзначень, тут важливо зауважити, що один Locationоб’єкт займе стільки пам’яті, скільки два окремих floatзначення.

У цьому сенсі не має значення, використовуєте ви OOP чи ні. Слід пам’яті однаковий.

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

Подумайте про це так: чи пишу я рецепт торта англійською чи іспанською мовами, це не змінює факту, що для випікання торта знадобиться 30 хвилин (= виконання). Єдине, що змінюється мовою рецепта - це те, як кухар змішує інгредієнти (= складання байтового коду).

Спеціально для Python вам не потрібно чітко попередньо компілювати код перед тим, як викликати його. Однак, якщо ви не виконаєте попередню компіляцію, компіляція відбуватиметься при спробі виконання коду. Коли я кажу "час виконання", я маю на увазі саме виконання, а не компіляцію, яка могла би передувати виконання.


6

Переваги чистого наукового коду

  • ... дивлячись на книги з програмування, вони, здається, часто звертаються до великих проектів.

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

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

  • Чому вони відкрили цей файл?
  • Що вони шукають?

З мого досвіду,

Чистий код повинен спростити перевірку результатів

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

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

Чистий код може слугувати прикладом коду для майбутніх кодерів

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

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

Рекомендації

"Цитувати" математичні формули, використовуючи коментарі.

  • Додайте коментарі до "цитування" математичних формул, особливо якщо ви використовували оптимізацію (трійкові ідентичності, серії Тейлора тощо).
  • Якщо ви отримали формулу з книги, додайте коментар John Smith Method from Some Book 1st Ed. Section 1.2.3 Pg 180 , якщо ви знайшли формулу на веб-сайті або в папері, цитуйте це також.
  • Я рекомендую уникати коментарів "тільки посилання", переконайтесь, що ви посилаєтесь на метод по імені десь, щоб люди могли його переглядати, я натрапив на деякі "лише посилання" коментарі, які перенаправлені на старі внутрішні сторінки, і вони можуть бути дуже засмучуючими. .
  • Ви можете спробувати ввести формулу у вашому коментарі, якщо її все ще легко читати в Unicode / ASCII, але це може стати дуже незручним (коментарі до коду - це не LaTeX).

Використовуйте коментарі розумно

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

Використовуйте описові назви змінних

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

Напишіть код для запуску програми проти відомих хороших та відомих поганих даних.

Чи потрібно тестування одиниць для написання менших фрагментів коду?

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

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

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

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

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

Використовуйте контроль версій

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

Переваги:

  1. Він забезпечує резервну копію у випадку відмови вашого жорсткого диска
  2. Він надає історію, яка не дає вам турбуватися, якщо нещодавня проблема, яка виникла, була викликана випадковим зміною файлу, серед інших переваг.
  3. Це дозволяє використовувати розгалуження, що є хорошим способом роботи над довгостроковим / експериментальним кодом, не впливаючи на споріднену роботу.

Будьте обережні, коли копіюєте / вставляєте код

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

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

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



6

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

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

Що тобі вигідно?

  • контроль версій приємний тим, що дозволяє дуже легко створити резервну копію вашої роботи. Станом на 2018 рік, github - це дуже популярне місце для цього (і ви завжди можете перемістити його пізніше, якщо потрібно - git дуже гнучкий). Дешевим і простим замінником резервного копіювання є автоматичні процедури резервного копіювання у вашій операційній системі (Time Machine для Mac, rsync для Linux тощо). Ваш код повинен бути в декількох місцях!
  • Тестові одиниці приємні, тому що якщо ви їх пишете спочатку, ви змушені думати, як перевірити, що насправді робить код, що допоможе вам розробити більш корисний API для вашого коду. Це корисно, якщо ви коли-небудь потрапите до написання коду, який буде використаний пізніше, і допоможе вам змінити алгоритм, оскільки ви знаєте, що він працює в цих випадках.
  • Документація. Навчіться писати належну документацію мовою програмування, якою ви користуєтеся (наприклад, javadoc для Java). Пишіть на майбутнє вам. У цьому процесі ви побачите, що хороші імена змінних полегшують документування. Ітерація. Приділіть ту саму увагу, як поет робить вірші.
  • Використовуйте хороші інструменти. Знайдіть IDE, який допоможе вам і добре засвоїте його. Рефакторинг, як перейменування змінних на краще ім'я, набагато простіший.
  • Якщо у вас є однолітки, можете скористатися експертною оцінкою. Сторонній погляд і розуміння вашого коду - це ось тепер і зараз версія майбутнього, про яку ви пишете. Якщо ваш одноліток не розуміє вашого коду, ви, ймовірно, не пізніше.

Як ця відповідь не отримала відгуку? Це є зараз. Наша група визнала експертну оцінку одним з найефективніших інструментів, набагато важливішим, ніж одиничні тести, якщо мова йде про науковий код. Помилитися, перекладаючи складний набір рівнянь у статті наукового журналу, легко кодувати. Вчені та інженери часто намагаються створити надзвичайно бідних програмістів; рецензування може вловлювати архітектурні негаразди, які ускладнюють підтримку / розуміння / використання коду.
Девід Хаммен

5

Крім хороших порад, які вже є тут, ви можете розглянути мету свого програмування, а отже, що для вас важливо.

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

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

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

У такому випадку розбиття коду на легко зрозумілі та перевірені функції за допомогою тестових одиниць дасть вам більш міцні будівельні цегли, що надасть вам більше впевненості у своїх результатах та може позбавити вас від багатьох розладів пізніше.


5

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

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

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

Лінійка розглядає написаний вами код і порівнює його з налаштованим набором найкращих практик. Якщо в лінійці є правило, що повинні бути змінні camelCase, і ви записуєте snake_caseйого, воно позначатиме це як помилку. У хороших лінійках є правила, починаючи з "оголошених змінних необхідно використовувати" до "Цикломатична складність функцій повинна бути менше 3".

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


Це повинно мати набагато більше результатів. +1
вереск

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

4

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

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

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

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

У будь-якому випадку, я б не турбувався про те, щоб не використовувати OOP або інші методи, поки ваші сценарії невеликі. Багато описуваних вами проблем - це лише загальні професійні організаційні навички, тобто не втрачаючи старий файл - це те, з чим доводиться стикатися у всіх сферах.


4

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

Я інколи маю в два-три рази більше рядків коментарів, ніж я кодую, особливо коли поняття або методики для мене нові і я можу пояснити собі.

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


4

Які якості важливі для цього виду програми?

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

Це, мабуть, не має значення, наскільки це ефективно.

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

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

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

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

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


4

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

Наприклад, можливо, вам доведеться мати справу з великою кількістю перетворень координат у вашому полі (ECEF, NED, lat / lon, WGS84 тощо), тому така функція, як і convert_ecef_to_ned()повинна, переходить у новий проект, який називається CoordinateTransformations. Покладіть проект під контроль версій і розмістіть його на серверах вашого відділу, щоб інші люди могли використовувати його (і, сподіваємось, вдосконалити). Потім через декілька років у вас має бути надійна колекція бібліотек з вашими проектами, що містить код, специфічний для певної проблемної / дослідницької області.

Ще кілька загальних порад:

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

Не дозволяйте іншим людям вдосконалювати це. Цілком ймовірно, що вони не розуміють мету коду, і вони просто зіпсують справи.
mathreadler

@mathreadler Ну, якщо вони загальні бібліотеки утиліт, то іншим буде дещо важко зіпсувати це ідея.
jigglypuff

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

@mathreadler Тому що, як правило, існує лише один спосіб координувати перетворення або одиничні перетворення, наприклад.
jigglypuff

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

3

Далі мої думки і дуже сильно вплинув на мій власний шлях.

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

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

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

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

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

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


3

Хоча я думаю, що одиничні випробування мають свої достоїнства, вони мають сумнівну цінність для наукових розробок - вони часто просто занадто малі, щоб запропонувати велику цінність.

Але мені дуже подобаються інтеграційні тести для наукового коду:

Виділіть невеликий шматок свого коду, який може працювати самостійно, наприклад, трубопровід ETL. Потім напишіть тест, який надає дані, запустіть трубопровід etl (або просто крок), а потім перевірте, чи результат відповідає вашим очікуванням. Хоча в тестованому фрагменті може бути багато коду, тест надає значення:

  1. У вас є зручний гачок, щоб повторно виконати свій код, що допомагає запускати його часто.
  2. Ви можете перевірити деякі припущення у своєму тесті
  3. Якщо щось замислюється, легко додати невдалий тест і зробити виправлення
  4. Ви кодифікуєте очікувані входи / виходи, уникаючи звичайного головного болю, який виникає при спробі відгадати формат вхідних даних.
  5. ІТ-тести, хоч і не такі виразні, як одиничні тести, все ще допомагають розбити код і розірвати змушення додати деякі межі у ваш код.

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


2

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

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


2

З письмовим кодом - як і з написанням взагалі - головне питання:

Якого читача ви маєте на увазі? або Хто споживає ваш код?

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

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

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

Я думаю, вам не потрібні тести OOP або Unit для файлів розміром 150 LOC. Виділений VCS був би цікавий, коли у вас є якийсь код, що змінюється. В іншому випадку це .bakробить трюк. Ці засоби - це ліки від недуги, чого ви, можливо, навіть не мали.

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

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