LINUX.ORG.RU

[c++] Этика написания кода

 


0

0

Где можно почитать про сабж? Как именовать классы, из каких соображений разбивать код на файлы, почему не принято использовать CamelCode, как вообще оформлять код?

Вот как обычно делают?

if ( a==b ) b=b+1;
if (a==b) ++b;
if (a == b)
   b++;
if (a == b) {
   b++;
}
if ( a == b )
{
   b++;
}
★★★★★
Ответ на: комментарий от Obey-Kun

>Переписал одну софтинку с учётом этих правил — читабельность поднялась.

как мерял читабельность? теми-же глазами, которыми переписывал?

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

Переписывал руками, мерил глазами :). Может, мне ещё двойное слепое тестирование на большой выборке провести?

Я же говорил, что пока что для себя пишу.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

> Может, мне ещё двойное слепое тестирование на большой выборке провести?

Обязательно рандомизированное и с плацебо-контролем! 8))

kemm
()
Ответ на: комментарий от LamerOk

Также интересует этика размещения комментариев к классам и функциям, к действиям.

doxygen

Я не совсем это имел в виду. Но doxygen мы в любом случае стоит использовать — там, где много матана, с лейтехом всё должно лучше пониматься.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Но doxygen мы в любом случае стоит использовать

O_O

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Ian

> А я бы написал:

> if( a == b )

> {

> b++;

> }


А можно и так:

if
(
a
==
b
)
{
b++
;
}

Чё уж там мелочиться...

anonymous
()
Ответ на: комментарий от Obey-Kun

>Вон в тех программах на C#, что я видел, в именах повсеместно используют CamelCase, причём переменные именуют с маленькой буквы, а классы с большой

Потому что так веками повелось http://java.sun.com/docs/codeconv/

Karapuz ★★★★★
()
Ответ на: комментарий от Obey-Kun

>Но doxygen мы в любом случае стоит использовать

Стоит, и латех ни при чём. doxygen в контексте этой темя - это стандарт на оформление комментов и контрольный список для их содержимого. Такие комментарии имеет смысл писать даже если дока не будет генерироваться.

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

> В плюсах использовать goto вообще не надо. Есть риск, например, получить видимую в скопе переменную, которая никак не была инициализирована.

1. (уже ответили)

2. выход из вложенного цикла требует goto

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

>posix каким образом к C++ относится?

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

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

>выход из вложенного цикла требует goto

На эту тему была дискуссия: http://www.linux.org.ru/view-message.jsp?msgid=3520569 Вкратце: я предлагал использовать goto для выхода из вложенных циклов, но меня переубедили.

legolegs ★★★★★
()
Ответ на: комментарий от Obey-Kun

> все переменные — с маленькой буквы;

+1

> все константы — только большими буквами;


+1

> имена классов и типов — с большой буквы;


+1

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


если в смысле "не использовать _ первым символом" - то +1. если "не использовать _ при именовании переменных/методов/етц" - то -1.

еще добавлю - методы классов и функций с маленькой буквы, вроде getThisVar() или syncThisObject() или transform_array().

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

На эту тему была дискуссия: www.linux.org.ru/view-message.jsp?msgid=3520569 Вкратце: я предлагал использовать goto для выхода из вложенных циклов, но меня переубедили.

Ни разу не убедительно — goto в твоем бенче показало лучшее время, и вероятно и будет показывать, так как разработчики компилятора воспринимают этот случай как стандартный.

Предолжение Мигеля было интересно (особенно в случае концептуальности именно пути), однако:

1. его надо написать на шаблонах, чтобы оно не тормозило

2. вероятность его тормозов все равно >0

3. оно не аргумент для запрета goto

  while(i...) {
    while(j...) {
      switch(...) {
        case 'a' : goto apple;
        case 'b' : goto banana;
  } } }
  std::cout << "sorry";
  // half a page code here
  goto end;
apple: 
  std::cout << "apple found with " << f(i,j);
  // half a page code here
  goto end;
banana:
  std::cout << "banana found with " << g(i,j);
  // half a page code here
  goto end;
end:

понятно, что все по меткам можно запихать внутрь цикла, но это — нечитабельное тупое поклонение авторитету

З.Ы. правильное решение — реализация «статических» исключений средствами метапрограммирования

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

я в той теме промолчал только потому, что мне показалось, что все ясна победа goto

чтобы реализовать мой пример через return, тебе придется придумать никому не нужный enum BlaBlaBla {apple, banana}, возвращать его из функции, а потом делать по нему свитч, да еще и не забыть добавить в свитч один из вариантов, когда ты его добавишь в цикл!

кроме опасности, оно еще и тормозит -- в цикле ты знаешь куда надо прыгать, но нет -- мы будет это вспоминать в свиче. может жцц и соптимизирует это, но нафига?

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

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

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

>я в той теме промолчал только потому, что мне показалось, что все ясна победа goto

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

>тебе придется придумать никому не нужный enum BlaBlaBla {apple, banana}

Он нужный, ибо:

1. самодокументируемость: сразу видно какие вообще фрукты бывают.

2. компиляторы умеют предупреждать, когда в switch перечислены не все элементы enum.

B в первую очередь в твоём коде выкинуть в функции надо "// half a page code here"

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

Что скажешь о книге Лафоре «Объектно-ориентированное программирование в C++»? Мне тоже Страуструп несколько не нравится — как-то бессвязно всё. Больше похоже на справочник, а не на руководство.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от legolegs

> B в первую очередь в твоём коде выкинуть в функции надо "// half a page code here"

// this page of code is intentionally left blank

dilmah ★★★★★
()
Ответ на: комментарий от Obey-Kun

> что при ++i операций с памятью происходит на одну меньше, чем при использовании i++

Вообще говоря, это все должен решать компилятор. И уж тем более это решать компилятору, если использование идет в контексте if (a==b) b++;

no-dashi ★★★★★
()
Ответ на: комментарий от Obey-Kun

>Что скажешь о книге Лафоре «Объектно-ориентированное программирование в C++»

Не читал Лафоре. Попробуй Мейерса почитать, только учти что его Effective C++ и More Effective C++ уже немного устарели, Effective STL посвежее будет, но там уклон в STL. Саттер еще в той же канве пишет. Если нужен ООП то хорошо почитать "Приемы объектно-ориентированного проектирования. Паттерны проектирования" от GoF. Это все короткие книжки страниц по 300-400. Более толстые технические книги это или энциклопедии/альманахи или непонятные аутпуты людей не могущих излагать мысли.

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

> Более толстые технические книги это или энциклопедии/альманахи или непонятные аутпуты людей не могущих излагать мысли.

Угу, канонический талмуд Страус-трупа - классика жанра. Ещё в этом ключе можно "порекомендовать" Programming Perl великого лингвиста Ларри. Обязательно нужно прочесть, чтобы навсегда избавится от желания заюзать перл.

anonymous
()
Ответ на: комментарий от Absurd

Вообще сказать, мне язык для вполне конкретных целей нужен — для моделирования мерзлоты. От лёгкого (известна зависимость f(x,z,t), надо найди несколько её точек на заданном диапазоне с заданной допустимой ошибкой для t=0) до тяжёлого (двухмерное пространство 3000x3000 ячеек, в нём есть известные источники тепла + есть теплопоток из недр и с поверхности, задана изначальная увлажнённость и свойства грунта, состав влаги, высчитать как оно будет изменяться во времени... там мильён зависимостей — идёт миграция, фазовые переходы, изменение размеров ячеек (пучение), образование прослоев льда и т.д., это очень диффуры и прочего, нынешняя модель на C# очень медленна при том, что там всего 300x300 ячеек).

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

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

>И из-за полного отсутствия опыта я даже и не знаю, какая парадигма программирования в данном удобнее/эффективнее

Ну вообще обычно в матлабе прототипируют такие вещи, а потом переносят на Си.

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

Вот пример программы — http://pastebin.mozilla-russia.org/102300. Индусский код как он есть, видимо. Учусь пока. Не знаю, какую я тут парадигму использовал. Классифицируешь?

Задача такая. Известна формула T(x,z). Также известно, что функция в каждой плоскости представляет собой кривую (т.е. не бывает такого, чтобы она имела решение на площади). Найти в квадрате со стороной 250, идущем от нуля, несколько точек таких, что T(x,z)==константе (T_NEEDED). Для каждой точки есть допустимая ошибка: |T(x0,z0)-T_NEEDED|<=MAX_MISTAKE.

Сделал так: иду по Z от 0 до 250 с постоянным шагом. Для каждого z иду по X от 0 до 250 с постоянным шагом и смотрю, пока не пересеку функцию. Я её пересёк в том случае, когда в начале шага значение T(x,z) было больше (меньше) нужного, а в конце стало меньше (больше) нужного. Как только мы пересекли функцию, разбиваем шажок пополам и выбираем половинку с меньшей ошибкой до тех пор, пока не добъёмся допустимой ошибки. Все значения заносим в массив. В конце выводим содержание массива на стандартный вывод.

Как тут вообще можно бы было использовать ООП? А обобщённое программирование?

А как (не в обычном массиве же!) тут лучше хранить данные, кстати (из соображений производительности)?

P.S.: Конкретно в этом случае функция такая, что для каждого z существует единственный x, так что шаг по X я сделал равным 250. Но это только частный случай. Результат исполнения: http://pic.ipicture.ru/uploads/091024/32UyPcap5b.png (там несколько кривых, для разных T_NEEDED).

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Absurd

> Ну вообще обычно в матлабе прототипируют такие вещи, а потом переносят на Си.

Да, мне уже говорили. Но если оно и подойдёт для более простых случаев (которые я так бы и делал, если бы опыт не нужен был), то для тяжёлой модели, о которой я говорил — нифига, она слишком комплексная.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

>Задача такая. Известна формула T(x,z). Также известно, что функция в каждой плоскости представляет собой кривую (т.е. не бывает такого, чтобы она имела решение на площади). Найти в квадрате со стороной 250, идущем от нуля, несколько точек таких, что T(x,z)==константе (T_NEEDED). Для каждой точки есть допустимая ошибка: |T(x0,z0)-T_NEEDED|<=MAX_MISTAKE

Метод градиентного спуска изобретаешь?

>Как тут вообще можно бы было использовать ООП?

Чего ты с помошью него хочешь достичь?

>А обобщённое программирование?

Если кода слишком много и он однотипный, то можно попытаться написать eDSL на exprеssion-темплейтах. Но это *немного* сложно.

>А как (не в обычном массиве же!) тут лучше хранить данные, кстати (из соображений производительности)?

Чем тебя массив не устраивает? O(1) к любому элементу, совместим с чистым Си, элементы хранятся в памяти рядом отчего caсhe-miss происходит редко, накладные расходы на каждый элемент - ноль байт. Ресайзить только надо с запасом.

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

> Метод градиентного спуска изобретаешь?

OH SHI--

> Чего ты с помошью него хочешь достичь?

Большего удобства написания. Или лучшей читабельности.

> O(1) к любому элементу

Вопрос снят.

Так что, не скажешь, какая парадигма использована в этой програмке? :S

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

> Метод градиентного спуска изобретаешь?

И метод золотого сечения заодно. Ну не было у нас ни теории алгоритмов, ни программирования, ничего...

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

>> O(1) к любому элементу

>Вопрос снят.

Что тебя не устраивает?

>Так что, не скажешь, какая парадигма использована в этой програмке?

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

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

> Что тебя не устраивает?

Напротив, всё устраивает. Ошибочно думал, что это у vector O(1) при записи в конец, а при записи в массив порядок выше.

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

Помимо того факта, что стоило бы использовать золотое сечение, а не деление пополам, есть что-нибудь важное?

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

>Ошибочно думал, что это у vector O(1) при записи в конец, а при записи в массив порядок выше.

Там у тебя треды, а два треда одновременно не могут делать push_back в конец вектора, надо мютекс захватывать.

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

>Помимо того факта, что стоило бы использовать золотое сечение, а не деление пополам, есть что-нибудь важное?

Нет.

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

UPD: Делать for по double-переменной я бы не стал. Изучал черную магию с флоатами я давно, но насколько я помню умножение для флоатов это более предпочтительная операция чем сложение, так что ИМХО лучше делать цикл по int и конвертировать его в double + умножать на масштабный коэффициент.

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

Ясно. Тогда просто использую for, аналогичный тому, что в main'е.

Чем посоветуешь предварить чтение книги Александреску и Саттера «C++ Coding Standards : 101 Rules, Guidelines, and Best Practices»? Хотелось бы пошаговое объяснение всего, кроме того, что устарело и почти не используется.

BTW, а нужны ли в подобном плюсы вообще? Может, лучше брать Белую Библию, пока не поздно?

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Absurd

Да, и такой вопрос — в том коде по правилам хорошего тона надо занести внутрь double T те константы, которые нужны только в ней?

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

> Хотелось бы пошаговое объяснение всего, кроме того, что устарело и почти не используется.

ИРЛ "устарело" используется почти везде.

LamerOk ★★★★★
()
Ответ на: комментарий от Obey-Kun

>Чем посоветуешь предварить чтение книги Александреску и Саттера «C++ Coding Standards : 101 Rules, Guidelines, and Best Practices»?

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

>а нужны ли в подобном плюсы вообще?

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

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

> UPD: Делать for по double-переменной я бы не стал.

Лорчую. Любое плавающе как счетчик цикла - косяк.

LamerOk ★★★★★
()
Ответ на: комментарий от Obey-Kun

>в том коде по правилам хорошего тона надо занести внутрь double T те константы, которые нужны только в ней?

В Unreal-е константы с плавающей запятой вообще определяются через #define.

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

Ну... то, что устарело и лучше бы не использовалось.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

> Как тут вообще можно бы было использовать ООП? А обобщённое программирование?

Да никак, это все тебе нафик не нужно. Пиши безо всяких объектов. У тебя задача - чисто вычислительная. Плюсы тебе просто не нужны - это оверкилл.

> А как (не в обычном массиве же!)


Почему не в массиве? У тебя много и часто меняется количество данных по ходу работы?

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

В Unreal-е константы с плавающей запятой вообще определяются через #define.

Да, часть констант так и буду делать, наверное. Шустрее же.

Obey-Kun ★★★★★
() автор топика

Касательно выбора языка... надо будет мне переписать это же на чистом С и на пайтоне (поискав замену OpenMP) и сравнить производительность.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

>> В Unreal-е константы с плавающей запятой вообще определяются через #define.

>Да, часть констант так и буду делать, наверное. Шустрее же.

Для начала амовые листинги сравни. MSVS раньше очень анально реализовывала const double-ы, но сомневаюсь что в новых гыцацах будет разница между const и #define.

Absurd ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.