Чому погано писати щось мовою X, як ніби ви пишете програму мовою Y з точки зору використання загальної парадигми кодування [закрито]


25

Нещодавно я поставив запитання на запитання про щось, що написано на C ++, але замість того, щоб отримати відповідь на проблему, що склалася, коментарі пішли з розуму на мій стиль кодування, навіть коли я вказав, що це WIP фрагмент коду і що я мав намір прибрати його пізніше, коли в мене був запущений базовий корпус. (Я отримав стільки голосів вниз, що я вирішив поставити запитання, оскільки моя репутація щодо ТА вже майже не відповідає)

Це змусило мене замислитися, чому люди сприймають таке жорстке ставлення "ти нобій, піди ебати себе". Мене звинувачували в написанні C ++ так, ніби це Java. Щось, що я не можу зрозуміти, і що все ще мене бентежить.

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

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

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

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

[ред.] Я хотів би уточнити, що пропозиція гната [1] не з’явилася в пошуку, який я проводив, перш ніж я почав задавати своє запитання. Однак, хоча його пропозиція охоплює один аспект питання, питання, з яким він пов'язує, не відповідає серцю мого питання, лише його частиною. Моє запитання стосується більше відповіді на мій стиль кодування та професійні аспекти обробки різних стилів кодування та (очевидного) рівня майстерності. Що стосується мого попереднього запитання щодо SO та його відповіді як конкретного випадку. [/ редагувати]

Питання тоді: навіщо знущатися над тим, хто не використовує ваш стиль кодування?

Для мене питання / підрозділи:

  • Чому було б поганою практикою програмування використовувати більш схильний до помилок код у прототипних ситуаціях, якщо рефакторинг робить його більш надійним після цього?
  • Як може програма, написана на C ++, була такою, якою вона написана на Java? Що робить це поганою програмою (враховуючи, що я вказав намір поточного стилю та заплановану роботу щодо вдосконалення?)
  • Як я став би поганим професіоналом, якби вирішив використовувати конструкцію, яка використовується в певній парадигмі програмування (наприклад, OOP / DP)?

[1] Розвивайте швидко та неполадко, потім виправляйте помилки чи будьте повільні, обережні для кожного рядка коду?


5
Вам може бути краще задати людям у The C ++ Lounge це питання. Одягніть спочатку свій вогнестійкий костюм.
Роберт Харві

48
C ++ люди - незвичайна порода серед програмістів. Ваш інструментарій Java - це розумна, добре зрозуміла скринька інструментів із знайомими інструментами в м'якій шкіряній футлярі, яка працюватиме в будь-якому магазині інструментів. C ++ - це цілий інструментальний інструмент з пилкою, сівалкою та деякими інструментами, які ніхто не впізнає, з якими натовп C ++ може працювати як ніндзя. Це засмучує їх, коли хтось заходить і кладе якийсь інструмент назад на полицю в неправильне місце. Вони "міра двічі, один раз відрізана" програмістів.
Роберт Харві

13
Можливо, це та сама реакція, що і у вас на код Java, написаний як FORTRAN: весь код в одному класі, відсутні колекції, лише масиви фіксованого розміру, з окремими intзмінними, щоб відстежувати фактичну довжину.
кевін клайн

14
Якщо ви пишете C ++, як Java, ви, ймовірно, закінчите занадто багато купових виділень, що зробить вашу програму ефективнішою, ніж могла. Мови, як правило, розроблені та оптимізовані для просування певних моделей, і якщо ви порушите ці зразки, для вас все буде гірше.
Gort the Robot

5
Ви опублікували код в Інтернеті, щоб отримати певну форму допомоги. Я усвідомлюю, що ви не хотіли / не очікували всіх відгуків про ваш стиль, але чи не хочете б взагалі допомоги? Ти береш добро з поганим. Програмістам доводиться шукати несправності в коді; це ми робимо.
JeffO

Відповіді:


26

Не бачачи коду, про який йде мова, є кілька способів написання Java-коду в C ++, деякі гірше інших.

  1. На крайньому рівні, викладаєте своє джерело, як Java: все в одному файлі, все в межах визначення класу тощо:
    class HelloWorldApp {
    public:
        void main() {
            cout << "Hello World!" << endl;
        }
    };
    Ось так було б викладено джерело Java. Це технічно законно в C ++, але розміщення всього у файлі заголовка і все вбудоване (визначаючи це в декларації класу) - жахливий стиль і вб'є вашу компіляцію. Не робіть цього.
  2. Надмірно OO - Для спрощення в Яві це Королівство іменників , де все є об'єктом. Хороший (тобто ідіоматичний) код C ++, швидше за все, використовує вільні функції, шаблони тощо, замість того, щоб намагатися забити все в об'єкт.
  3. Ні RAII - Ви вже згадували про це - використовуючи вказівники та ручне очищення замість смарт-покажчиків. C ++ дає такі інструменти, як RAII та розумні покажчики, тому хороший (тобто ідіоматичний) код C ++ використовує ці інструменти.
  4. Немає розширених C ++ - Основи Java та C ++ досить схожі, але, як тільки ви ввійдете в більш досконалі функції (шаблони, бібліотека алгоритмів C ++ тощо), вони починають розходитися.

За винятком №1, жодна з них не робить програму C ++ поганою програмою, але це також не той код, над яким я вважаю за краще працювати як програміст на C ++. (Мені також не сподобається працювати з неідіоматичним або стилем С-стилю, неідіоматичним Python тощо). Мова має власні інструменти та ідіоми та філософію, і хороший код використовує ці інструменти та ідіоми, а не намагатися використовувати. найнижчий загальний знаменник або намагається відтворити підхід іншої мови. Написання неідіоматичного коду на певній мові / проблемній області / що завгодно не робить когось поганим програмістом, це просто означає, що вони мають більше дізнатися про цю мову / проблемний домен / що завгодно. І в цьому немає нічого поганого; Є дуже довгий перелік речей, про які я маю дізнатися більше, і зокрема, C ++ має абсолютну кількість речей.

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

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

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


11
є ідіоматичний перл?
храповик виродка

21
@Onno Коли ви запитуєте: "Як забити цей гвинт у стіну, не згинаючись?" всі скажуть вам не користуватися молотком.
Sjoerd

9
@Onno У C ++ вказівники і newвважаються powertools. Автоматичне зберігання - це ручний інструмент.
Sjoerd

9
@Onno: Ви повинні усвідомити, що курси програмування на C ++, як правило, відстають у прийнятті сучасних ідіом, і те, що вважається хорошим C ++, також сильно розвинулося з часу винайдення C ++.
Барт ван Іґен Шенау

7
Через історію C ++ та величезну кількість кодерів, які вивчали мову ще до того, як з'явилися багато вдосконалених особливостей мови, там є багато хитрої мови C ++, яку досі пишуть люди, які пишуть, як це робили десятиліття тому. Твердість щодо таких речей, як RAII, полягає в тому, щоб змусити всіх використовувати сучасні методи, щоб ми могли перестати бачити ті самі передбачувані невдачі.
Gort the Robot

42

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

  • Я кричу, якщо ви пишете for ($i = 0; $i < 42; $i++) { … }в Perl, але не в PHP
    (в Perl, змінні повинні бути оголошені, і такі петлі повинні повторюватися за діапазон)
  • Я заплачу, якщо ви пишете new Foo()на C ++ без поважних причин, але не на Java
    (у C ++ немає збирання сміття, тому слід використовувати RAII. Noobs просочить пам'ять інакше)
  • Я скажу, якщо ви оголосите всі свої змінні у верхній частині своєї функції, за винятком C89, Pascal або JavaScript.
  • Я зіткнуся з facepalm, якщо ви перекладете всі свої функції до класу на Python, але не на Java
    (Python - це багатопарадигмічна мова, а не змушує "OOP" та підтримує функції на верхньому рівні)
  • Я буду плакати, якщо ви return nullв Scala, але не будь-якою мовою, подібною до С
    (тому що у Scala є Optionтип)
  • Я поскаржусь, якщо ви пишете рекурсивний алгоритм на Java, але не в OCaml
    (оскільки стек Java швидко переповнюється, тоді як OCaml має оптимізацію хвостових викликів)

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

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

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

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

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


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

4
@Onno Мої основні моменти (які відповідають на запитані вами запитання) - це те, що ви не можете переносити звички з однієї мови і вважати, що це найкраща практика на іншій, і що спроба написати чистий код з самого початку є кращою для чищення це згодом. Очищення коду - якнайкраще, - перш ніж попросити інших допомогти (див. Sscce.org поради щодо хороших фрагментів коду). Скидання коду сміття на SO із "будь ласка виправте це" неприйнятно, особливо якщо ви знаєте краще.
амон

2
Але стосовно питання, на яке ви натякаєте: відповідь jm666 містить ключовий момент: гуру думає, "чому б ви запитали про X, якщо ви самі не хочете стати X-гуру?" . Можливий спосіб знешкодити, це зазначити, що ви все ще знаходитесь на самому початку кривої навчання і вивчите це пізніше, але наразі майте це більш безпосереднє питання. Однак це проблема зв'язку, а не проблема програмування.
амон

6
Обидва C ++ і C # є optional<T>і Nullable<T>відповідно. Крім того, практично кожен просочує пам'ять у C ++ без RAII, noob чи ні.
DeadMG

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

12

Я не хардкор C ++ розробник, але ...

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

Слід пам’ятати, що помилка в C ++ зазвичай означає «невизначене поведінку». У безпечній мові найгірше, що може статися, - це виняток, який негайно припиняє програму. У C ++ вам пощастить, якщо ви отримаєте сегмент за замовчуванням. Цілком можливо, що ваша програма продовжує робити щось тонко неправильно. Він також може поводитися правильно протягом певного періоду часу і виявляти помилки набагато пізніше, або він може вести себе правильно весь час, але зрештою з'їдає всю вашу пам'ять.

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

Як може програма, написана на C ++, була такою, якою вона написана на Java? Що робить це поганою програмою?

Я не думаю, що на це є відповідь, яка не буде в основному спекулятивною та самовираженою. Якщо ви хочете, щоб я взяв на себе це, у Java, як правило, є декілька анти-малюнків, як-от факт, що все повинно бути об'єктом. Де на інших мовах ви б передати покажчик, функтор, або функцію, в Java ви зазвичай знайти тонни беззмістовних і вузько-корисні ThingDoers, FooFactoriesі IFrobnicatorsякі є просто функціями в маскуванні.

Так само, де в інших мовах ви можете передати простий кортеж або безіменну структуру, у Java для з’єднання навіть просто двох об'єктів у простому контейнері даних потрібно заздалегідь визначити клас класу NamedThing 30+ із сетерами, getters та Javadocs. Відносна відсутність функцій Java змушує програмістів робити об'єктно-орієнтовані подвійні обертання, щоб іноді робити щось. Отриманий код рідко ідіоматичний за межами Java.

Тоді є той факт, що в C ++ вам потрібен дуже спрощений графік об'єктів для управління пам’яттю вручну; зазвичай об'єкт належить саме одному іншому об'єкту. У Java вам не потрібно дотримуватися таких жорстких обмежень, оскільки збирач сміття забезпечує, що речі будуть очищені, коли на них більше не буде посилань. Так що, безумовно, існує ризик неправильного управління пам'яттю, якщо ви просто транслітеруєте код з Java на C ++.

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


1
Значна частина цього полегшена за допомогою Java 8 - Ламбдас їде в основному, щоб врятувати день :-)
Martijn Verburg,

@MartijnVerburg Погодився, величезний крок вперед там. Але технологічні проблеми - це легко вирішити! Старі звички важко вмирають, а клейми ще важче. Чорт забирай, деякі люди підуть так далеко, що скаржитися Java не потребує жодної з цих "нових" функцій, і що це на шляху до наступного C ++.
Доваль

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

6

Трохи не в темі відповідь ...

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

Я в світі perl - коли побачу щось на кшталт:

$imax=$#array;
$str=""
for($i=0; $i<$imax; $i++) {
    $str = "$str" . $array[$i];
}

замість:

my $str = join '', @array;

обов'язково прокоментують це - (читайте: навчіть автора) про joinфункцію.

У будь-якому випадку, занадто багато критики взагалі є контрпродуктивною, і один з найкращих прикладів є наступним: (захоплено з: http://perl-begin.org/humour/#How_can_I_switch_off_the_T.V..3F )

(Цей біт був анонімно опублікований на пастові 23 березня 2011 року. Він розміщується тут для нащадків після деякого редагування.) - також трохи відредагований

Питання: як я можу увімкнути телевізор?

Що хоче почути ОП?

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

Відповідь експерта #perl: По-перше, що ви маєте на увазі під "увімкнути"? Визначте це спочатку. Не вставте телевізор, пульт телевізора та вітальню теж.

... після нопасти:

Ваша кімната потворна. А телевізор виглядає жахливо. Використовуйте Mr. Clean на екрані та спочатку очистіть свою вітальню. Використовуйте три очисних швабри замість двох. Використовуйте HDMI і ніколи не використовуйте роз'єми scart (?), Якщо ви цього не хочете. У пульті телевізора є нечитабельні кнопки, спочатку очистіть. Ви новачок, тому читайте:

http://experts.blog/how_to_design_a_future_3D_TV.html http://experts.blog/the_basics_of_tv_repairing.html http://experts.blog/viruses_in_living_room_short_essay.html http://experts.blog/global_chip_replacement_guide.html

Гість IRC: Але я не хочу бути телевізійним експертом.

Відповідь: Чому ви хочете тоді увімкнути телевізор ?!


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

1

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

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

Як може програма, написана на C ++, була такою, якою вона написана на Java? Що робить це поганою програмою (враховуючи, що я вказав намір поточного стилю та заплановану роботу щодо вдосконалення?)

У Java вам не доведеться думати про те, кому належить певний об'єкт, ви просто передаєте посилання і забуваєте про нього так, як це нічого. Однак у С ++ має бути чітке визначення того, хто є власником об'єкта та хто відповідає за його прибирання.

Як би я був поганим професіоналом, якби вирішив використовувати конструкцію, яка використовується в певній парадигмі програмування (наприклад, OOP / DP)

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

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


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

1
@Onno: Чесно кажучи, ніхто не знає і не хвилює, наскільки ви добре особисто стежите за цим матеріалом. Переважна більшість людей, які пишуть C ++, схожий на Java або C, навіть не настільки прискіпливі. Їм набагато краще навчитися робити речі правильно з першого разу, ніж писати собі записку, щоб повернутися та виправити її згодом, адже досвід показує, що вони практично ніколи цього не роблять.
cHao
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.