О стиле кодирования - страница 3

 

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

 
Mathemat >>:

В принципе нормальный код, выполняющий те же вычисления, что конструкция со вложенными if. Но вот где-то я слышал, что return в функции должен быть один. Наверно, для того, чтобы в них не запутаться. Я этому правилу не следую жестко.

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


Да, есть такое мнение. Но оператор return это не одно и то же что и GOTO. На практике я ни разу не сталкивался с непредвиденными выбрасами return. Скорее наоборот, программа с использованием таких операторов и условий становиться более читабельной и структырной (все проверки идут последовательно с верху вниз, образуя как бы колонку). К тому же оператор return в отличии от if() гарантирует выход из фукции, а этого как раз и надо в подовляющем числе случаев, ведь нет смысла просчитывать данные дальше, если какое-то условие несоблюдается.

 

Очень понравилось последнее правило: "Никогда не пользуйтесь операцией «копировать и вставить»". Но я ему, увы, не следую. Ну как же это так - пользовать редактор среды разработки и не юзать "Copy&Paste", экономящий кучу времени?!

Оказывается, нет, не экономит: замечаю, что именно из-за этого совсем нередко нахожу трудно отлавливаемые логические ошибки.

P.S. Движок форума не позволяет оформить вот этот фрагмент из моего первого поста

// open
// .pairsToOpen
// .combineAndVerify( )
// Собирает из двух валют символ и выполняет все проверки, нужные для его открытия.
// Возвращает валидность пары для открытия.
// Последний аргумент - [...]
bool
combineAndVerify( string quoted, string base, double& fp1 )

именно так, как он сделан у меня: первые три строки выглядят у меня иначе, более структурированно. Ок, не мытьем, так катаньем:


Как я комментирую функции

 

Вот еще несколько правил, которые пришли на ум недавно и которые я уже реализовал у себя:


1. Глобальные переменные (ГП) объявляем не все в начале кода, а по мере надобности, перед соответствующими функциями, использующими их.

2. Кроме того, перед каждой функцией описываем, какие ГП она при фактическом вызове использует (входные) и модифицирует (выходные). А после функции можно также пояснить, какая ГП уже больше не будет использоваться.

3. Все эти комменты, вместе с пустыми строками-разделителями между функциями, да еще и с ограничением "длина функции не более 20 строк", увеличивают объем файла кода раза в 1.5-2. Тяжелее при компиляции он от этого не становится, да и не бумага у нас тут, чтобы на этом экономить.

4. Для чего целесообразны ГП? Допустим, мы вычисляем какую-нибудь переменную variable сложного типа в функции foo( ..., <type>& variable ), передавая ее по ссылке. Тогда, если мы многократно пользуем эту переменную в разных частях кода, нам придется каждый раз вызывать и функцию foo( ). Вроде бы ничего страшного - кроме того, что мы каждый раз тратим время на вычисление этой переменной, да еще и в каждой функции, использующей variable, добавляем пару строк (на объявление variable и на вызов функции). Зачем? Если это и есть так называемое повторное использование кода, то оно какое-то неоптимальное: помимо того, что мы делаем функцию foo( ) слишком уж частой в использовании, мы еще и ломаем структуру вызовов функций, делая пользовательскую функцию foo( ) функцией "вне категорий", а ее вызовы неиерархичными. Проще объявить variable переменной "вне категорий", т.е. глобальной.

Лично я предпочту строгую иерархичность функций такому сомнительному повторному использованию кода. Об иерархичности я уже говорил: каждая функция n-го порядка вызова вызывается только функцией (n-1)-го порядка, причем только "своей". Смотрите мой пример, поясняющий иерархию функции, в картинке с зеленым фоном выше.

5. Но, конечно, код не всегда оптимален в смысле иерархичности, и иногда приходится вызывать "чужие" функции. В этом случае перед именем "чужой" функции можно в скобках /* */ вписать ее место в иерархии функций.


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

 
Vinin >>:
По размеру функции. Стараюсь что бы функция помещалась на один экран. Что бы можно было видеть ее всю.

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

комментариев должно быть не менее 30% от объема кода

( научился этому в 80x, разглядывая исходные коды операционных систем UNIX, RT11 )

через пол года код забудется - если надо поправить - комментарии дают быстрое въезжание в тему

( как то был реальный опыт на производстве - когда свой же код читал через 5 лет

благодаря комментарием за одни день все вспомнил и к вечеру внес изменения)

Стараюсь выравнивать код для читабельности не экономлю на пробелах и отступах

сравните два примера ! какой код лучше читается ?


1)

extern string gslM001rus="Все что касается индикации" ;
// 
extern bool gpInfoParameter =false ; // выводить параметры
extern bool gpInfoLevel =true ; // выводить параметры
extern bool _gDeleteObjectGrafic =0 ; // 1-Удалять объекты на графике при завершении 0-не удалять
extern double FlatSBuy =0.0010 ; // =0.00050; // пипов на пробой ТОЛЬКО ДЛЯ ИНДИКАТОРА!!!
extern double FlatSSell =0.0010 ; // =0.00050; // пипов на пробой ТОЛЬКО ДЛЯ ИНДИКАТОРА!!!
extern int DayHistory =50 ; // Сколько дней в истории показывать
// флет азии 
extern int iTimeEndFlatAsiaHour = 5 ; // Конец утреннего флета
extern int iTimeEndFlatAsiaMin = 15 ; // Конец утреннего флета
// Время длины флета измеряется минутами от окончания и назад
// 360 минут эт о6 часов назад от 5:15 получаем 23:15 вчерашнего дня
extern int iTimeEndFlatAsiaSizeMin = 360 ; // + количество минут  флета// 
extern string sTimeBreakFlatAsia ="20:00:00" ; // Время до которого разумно ждать пробой и выставление ордеров
extern int pУровниHighLowDAY =1 ; // выводить уровни HIGH LOW
extern color ЦветПятницыHIGH =DeepSkyBlue ;
extern color ЦветПятницыLOW =DeepSkyBlue ;
extern color ЦветHIGHDAY =DarkViolet ;
extern color ЦветLOWDAY =DarkViolet ;
extern color lColorFAH =OrangeRed ;
extern color lColorFAL =SandyBrown ;
extern color lColorSignalSELL =Red ;
extern color lColorSignalBUY =Red ;

 


2)


extern string gslM001rus="Все что касается индикации"      ;
//                                                                  
extern bool   gpInfoParameter         =false               ; // выводить параметры
extern bool   gpInfoLevel             =true                ; // выводить параметры
extern bool   _gDeleteObjectGrafic    =0                   ; // 1-Удалять объекты на графике при завершении 0-не удалять
//                                                            
extern double FlatSBuy                =0.0010              ; // =0.00050;  // пипов на пробой ТОЛЬКО ДЛЯ ИНДИКАТОРА!!!
extern double FlatSSell               =0.0010              ; // =0.00050;  // пипов на пробой ТОЛЬКО ДЛЯ ИНДИКАТОРА!!!
extern int    DayHistory              =50                  ; // Сколько дней в истории показывать

//                                                         
// флет азии                                               
//                                                         
extern int    iTimeEndFlatAsiaHour    = 5                  ; // Конец утреннего флета
extern int    iTimeEndFlatAsiaMin     = 15                 ; // Конец утреннего флета
// 
// Время длины флета измеряется минутами от окончания  и назад
//   360 минут эт о6 часов назад от 5:15 получаем 23:15 вчерашнего дня
//
extern int    iTimeEndFlatAsiaSizeMin = 360                ; // + количество минут  флета
//                                                            
//                                                              
//                                                            
extern string sTimeBreakFlatAsia      ="20:00:00"          ; // Время до которого разумно ждать пробой и выставление ордеров
//                                                         
extern int    pУровниHighLowDAY       =1                   ; // выводить уровни HIGH LOW
//
extern color  ЦветПятницыHIGH         =DeepSkyBlue         ;
extern color  ЦветПятницыLOW          =DeepSkyBlue         ;
extern color  ЦветHIGHDAY             =DarkViolet          ;
extern color  ЦветLOWDAY              =DarkViolet          ;
extern color  lColorFAH               =OrangeRed           ;
extern color  lColorFAL               =SandyBrown          ;
extern color  lColorSignalSELL        =Red                 ;
extern color  lColorSignalBUY         =Red                 ;
//
//
 
                                                    
 
Mathemat >>:

if(param1!=1)return;

if(param2!=2)return;

...

if(param5!=5)return;

Print("Наконец-то дошли!");

В принципе нормальный код, выполняющий те же вычисления, что конструкция со вложенными if. Но вот где-то я слышал, что return в функции должен быть один. Наверно, для того, чтобы в них не запутаться. Я этому правилу не следую жестко.

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

Предпочитаю так же выход один!

легче контролировать


Если надо вернуть значение то


вместо

if ( a > c )

return (3);

if ( l < b )

return (5);

...

...

if ( h != b )

return (100);

---

предпочитаю


if ( a > c )

codret = 3;

if ( l < b )

codret = 5;

...

...

if ( h != b )

codret = 100;


// особенно если перед return делаются некие дополнительные общие для всех выходов действия

... например тут занимаемся еще чем то

retrun( codret);

}


 

немного из области оформления коментариев...

для разделения текстов на блоки использую линию из символов с кодом U0151. Для тех кто не знает - набирается так:

  1. зажимаем Alt
  2. на цифровой клавиатуре нажимаем последовательно цифры кода символа 0 потом 1 потом 5 потом 1
  3. отпускаем Alt

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

// обычная линия
// -----------------------------------------------------------------------------------

// сплошная линия
// —————————————————————————————————

// —————————————————————————————————
// Вот такие часто делаю ЗАГОЛОВКИ
// —————————————————————————————————

 

еще хитрая отбивочная линия для блока текста комментариев - выглядит абсолютно симметрично, но есть первая-открывающая и вторая-закрывающая:


/*///—————————————————————————————————————————
это

блок многострочного комментария
...................

/*///—————————————————————————————————————————

 

Юра, твой пример с одним return, конечно, логичен. Но обрати внимание, что при этом всегда пробегаются все if - в отличие от случая со многими return, когда выход из функции получается сразу по достижении строки с условием.

ForexTools, спасибо, твои наработки по оформлению принял на вооружение.

Причина обращения: