LINUX.ORG.RU

60 антипаттернов для С++ программиста

 , , , ,


10

4

Постоянно писать «как делать правильный код» надоедает. Поэтому для разнообразия и развлечения написал мини-книгу «60 антипаттернов для С++ программиста». Этакие вредные советы в духе «Книга для непослушных детей и их родителей».

На самом деле там, не только вредные советы, но и разбор почему они собственно вредны. Будет полезно почитать новичкам в программировании. Думаю, каждый знает кого-то, кому будет полезно почитать этот материал :). Впрочем, опытные программисты тоже смогут найти интересное для себя и узнать/освежить знания про некоторых тонкие моменты C++.

Там много букв. Приглашаю запастись кофе/энергетиком и приступать. Буду рад обсуждениям и дополнениям, основанном на вашем опыте.

Ещё я этот текст переработал для бумажного издания. Оно в подготовке для печати. Смысл там в целом тот же, но пришлось многое переделать или расписать подробнее. Ведь нельзя в бумажной книге дать 100500 ссылок на сторонние ресурсы «читать здесь про xxx подробнее». Надеюсь, успеем напечатать к осенним конференциям и будем раздавать на стенде, например по кодовым словам. Приходите на стенд и говорите, что с linux.org.ru и что там на тему бумажной книги :)

Парочка вредных советов для примера:

  • Пишите ваши .h-файлы так, чтобы они зависели от других заголовков, и при этом не включайте их в свой заголовочный файл. Пусть тот, кто инклудит, догадается, какие заголовки нужно заранее заинклудить перед использованием вашего файла. Развлеките коллег квестами!
  • Пишите код так, как будто его будет читать председатель жюри IOCCC и он знает, где вы живёте (чтоб приехать и вручить вам приз).

P.S. PDF, если кому-то так удобнее.

Мне кажется я что то уже такое видел, не Ваше ли? Полистал бегло, понравилась толерантность сдержанность - вместо «категорически нельзя делать вот так вот» пояснение что бывают случаи когда вот так вот все таки можно;-)

Спасибо!

AntonI ★★★★★
()
Ответ на: комментарий от AntonI

Спасибо.

Было. Но это расширенная версия, как по количеству «советов» так и по полноте пояснений.

Andrey_Karpov_2020
() автор топика
Последнее исправление: Andrey_Karpov_2020 (всего исправлений: 1)

Спасибо!

ЗЫ

будем раздавать на стенде, например по кодовым словам. Приходите на стенд и говорите, что с linux.org.ru и что там на тему бумажной книги :)

Ключевым словом должно было быть Андрей-спамер. Сорян, на ЛОРе вы сами заработали себе эту репутацию.

filosofia
()
Ответ на: комментарий от Andrey_Karpov_2020

Прочитал по диагонали до середины, остальное в оглавлении. Вроде все по делу. Буду своим даунам показывать.

UPD найс у меня телефон «опечатку» исправил с джунов на даунов.

filosofia
()
Последнее исправление: filosofia (всего исправлений: 1)
Ответ на: комментарий от seiken

А причём здесь шаблоны? Весь реальный большой проект из шаблонов? Не верю.

Из сплошных шаблонов будут вспомогательные библиотеки. Это другое.

Andrey_Karpov_2020
() автор топика
Последнее исправление: Andrey_Karpov_2020 (всего исправлений: 1)

Насчет везде int (№8?) - есть нюанс, int это самый быстрый целочисленный тип. На лоре есть люди для которых это важно, и которые вообще живут на 32х битных платформах и им эти size_t не уперлись ни разу.

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

AntonI ★★★★★
()
Ответ на: комментарий от AntonI

В контексте loop’чиков по вектору самый быстрый выглядит примерно так:

for (int i = 0, n = v.size(); i < n; ++i) {
  // something touching v[i]
}

И да - там где вектор «длинным» быть не может из физических / бизнес соображений - size_t не впился, от слова совсем. Даже (тем более) на 64-ёх битах.

Но даже в 32-ух битах есть нюансы связанные с тем что signed int «не переполняется», а size_t - unsigned.

bugfixer ★★★★★
()
Ответ на: комментарий от Andrey_Karpov_2020

интересная граница.

Видимо, где-то на 1-2 MLOC точно заканчивается возможность одного человека удержать все исходники в голове и для того чтобы дорасти до 5 MLOC нужны уже методы управления выше уровнем?

max_lapshin ★★★★★
()
Ответ на: комментарий от alex1101

2 нюанса:

  1. v.size() при прочих равных может привести к лишнему memfetch на каждой итерации.

  2. type of v.size() гарантировано не int.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)

Вредный совет N1. Только C++

Нас невозможно сбить с пути!

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

Ещё скажите что нет. :)

Вредный совет N26. Напишу всё сам

Та шож ты делаеш, афтар?!

Не пользуйтесь стандартной библиотекой языка. Что может быть интереснее, чем написать свои строки и списки с уникальным синтаксисом и семантикой?

Не, ну не до такой же степени, конечно. Хотя в stdlib кроме строк да списков всякого говна хватает.

Вредный совет N27. Удалите stdafx.h

Чо?

как в среде Visual Studio

Чо?! А, ну да, афтар даже что-то про бумажную книгу говорил. Люди! Не ведитесь! Вас там покусают, и вы станете виндузятниками!

Все знают,

Да щас.

Придайте коду оригинальность, используя конструкции вида 1[array] = 0.

Блин, всё время забываю. Спасибо, что напомнили.

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

Во-первых, https://rsdn.org/forum/humour/1600906.1 (см. цитируемое зелёненьким). Впрочем, афтар тоже пишет:

Естественно, виноват не сам по себе оператор goto, а его необдуманное использование.

Но дальше он же пишет:

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

И хрен ты, афтар, угадал: например, при кодогенерации не помню уже каких парсеров у меня в генерируемом коде были массивы меток. Ну и например bison-овский таблично-управляемый автомат ЕМНИП тоже кучу меток содержал (во вручную написанном движке, а не в скармливаемых движку сгенерированных таблицах); полагаю, это вопрос эффективности.

А ещё лучше и короче старый добрый C-style cast: (Type)(expr).

Не могу не согласиться. :) Общего правила для себя так и не выработал, но как минимум ради narrowing (int)long ломать себе пальцы об эту плюсовую дичь точно не буду.

Вредный совет N43. Не инициализируй

Я бы иной раз и рад, например когда int c; if (b) init c; ...; if (b) use c;, да дурной компилятор ругается.

Модификаторы доступа private и protected для параноиков.

Гы. :)

Вредный совет N56. Больше классов!

Гораздо вреднее и распространённее идиотизм каждому классу добавлять парный интерфейс. Впрочем это среди жаверов.

Вредный совет N61.

Везде обман. :(

pr849
()
Последнее исправление: pr849 (всего исправлений: 2)

Полистал, выглядит интересно, почитаю вечером.

PS:

Можно еще «советов» добавить, с которыми я сталкиваюсь, когда учу студентов программировать.

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

Никогда не читай стандарт, ищи ответы по синтаксису языка на форумах.

Если очень нужно изменить const, то измени ее через ссылку!

Экономь память, не заводи новые переменные!

… много их

soomrack ★★★★★
()
Ответ на: комментарий от pr849

Вредный совет N27. Удалите stdafx.h

Действительно странно. Первым делом его удаляю, ведь у меня его нет. Его я видел исключительно в проектах для Visual Studio C++.

grem ★★★★★
()

Вообще сложно даже привести какие-то примеры уместного использования goto.

Легко: выход из всех вложенных циклов наружу без нагромождения дополнительных «переменных для проверки нужно ли выйти наружу».

Но за книжку спасибо.

grem ★★★★★
()
Последнее исправление: grem (всего исправлений: 1)

Постоянно писать «как делать правильный код» надоедает

Но вы сделали то же самое, только в более глупой форме.

Вот читать core guidelines почему-то не надодедает. А от вашего стиля слегка блевотное ощущение.

unsigned ★★★★
()
Ответ на: комментарий от grem

Легко: выход из всех вложенных циклов наружу без нагромождения дополнительных «переменных для проверки нужно ли выйти наружу».

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

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

soomrack ★★★★★
()
Ответ на: комментарий от unsigned

Но вы сделали то же самое, только в более глупой форме.

ИМХО, и да, и нет.

Я бы предпочел читать в формате «best practices», «code guideline», «clean code» и аналогичных. Но! Разные люди по разному открыты к восприятию информации, особенно в «трудном» возрасте. Возможно эта форма изложения найдет своего читателя. Чем больше разных форм – тем, в целом, лучше.

soomrack ★★★★★
()
Ответ на: комментарий от bugfixer
for (int i = 0, n = v.size(); i < n; ++i) {
  // something touching v[i]
}

Если речь только о прохождении по списку, и позиция не нужна в теле цикла, такое уже давно (с C++11) моветон, а рекомендуется использовать вариант без явного использования переменной-счетчика:

for (auto &x : v) {
  // something touching x
}
seiken ★★★★★
()
Ответ на: комментарий от seiken

А заказчик тебе и говорит - у нас дефолтный компайлер VS2008. И ты такой упс… и переписываешь все эти красивые циклы без счётчика на циклы со счётчиком.

А уж во что обходы с итератором превращаются…

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от AntonI

Еще когда-то был свод правил настоящего программиста:

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

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

  3. Настоящий программист никогда не пишет тестов, т.к. тесты пишут неуверенные в себе люди, а настоящий программист всегда уверен в своем коде.

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

soomrack ★★★★★
()
Ответ на: комментарий от seiken

А, ок.

Буст я бы не стал поминать всуе, а вот насчет сравнения скорости

for(auto &x: L) ...

и варианта @bugfixer конечно интересно. Насколько компайлер может развернуть первый вариант для массива небольшой статической длины например? Мне то первый вариант самому больше нравится, есть в нем что то питонье;-)

AntonI ★★★★★
()
Ответ на: комментарий от AntonI

А заказчик тебе и говорит - у нас дефолтный компайлер VS2008

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

Visual Studio поддерживается 10 лет с момента выхода.

Visual Studio 2022 End of Support Jan 13, 2032
Visual Studio 2019 End of Support April 2029
Visual Studio 2017 End of Support April 2027
Visual Studio 2015 End of Support October 2025
Visual Studio 2013 End of Support April 2024
Visual Studio 2012 and earlier Out of Support
fsb4000 ★★★★★
()