Доброе время суток!
Сегодня мы с вами поговорим о такой вещи, как стиль
программирования.
/ / / / С++ / / / / / / / / / / / / / / /
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/
ЛЕГКО ЧИТАЕМЫЙ КОД И НАДЕЖНОСТЬ ПРОГРАММ
Если
вам когда-нибудь приходилось разбираться в чужой программе, или даже в
своей собственной, но написанной несколько лет назад, да еще когда
поджимает время, вы скорее всего знаете, какая это неприятная и сложная задача. Порой бывает легче
весь код написать заново (а многие так и делают). Конечно, существует поговорка
"настоящие программисты не пишут комментарии: если программу было трудно
написать, в ней должно быть трудно что-то понять и еще труднее
что-либо изменить". О комментариях мы еще поговорим, печально то, что очень
многие следуют этому принципу в самой программе. "Неважно", думают они, "как это
написано, главное побыстрее проверить, работает ли это вообще". Самые прилежные
из них впоследствии переписывают отдельные куски кода, но таких
единицы. Большинство же, убедившись в работоспособности алгоритма,
оставляют все как есть и переходят к новым задачам.
Как
показывает многолетняя практика, это большая ошибка. Усилия, потраченные на
"причесывание" кода, окупаются с лихвой. Но по-настоящему ценится
умение писать сразу такой код, который не нуждается в причесывании. Это
умение не приходит само по себе, а вырабатывается постепенно, в нем надо
постоянно практиковаться. И когда вы говорите себе "а, это ведь просто небольшая
утилитка для удобства, вот когда получу настоящий заказ - буду писать красиво",
вы тем самым приучаете себя к неправильному стилю написания
программ.
Однажды я прочитал такую интересную мысль: программы надо писать не для компьютера, а для людей. Следует сразу рассчитывать на то, что этот код будут смотреть сотни или даже тысячи программистов. Компилятор же нужен просто для проверки орфографии.
Вот несколько практических советов и рекомендаций. Профессионалам многие из них покажутся очевидными, но для новичков, я считаю, будут очень полезны.
1. Обязательно соблюдайте отступы. Хотя Visual C++ и делает отступы
автоматически, иногда они все же нарушаются. С их помощью сразу видна
структура программы.
Кстати, многие знают, что для того, чтобы подвинуть блок
текста вправо, нужно выделить его и нажать Tab, но почему-то даже не
догадываются, что если нажать Shift-Tab, текст сдвинется влево! Попробуйте, это
очень удобно. Лучше вместо символа табуляции использовать пробелы
(Tools|Options|Tabs|Insert Spaces). Тогда ваши программы в любом редакторе будут
с корректными отступами.
2. Про
комментарии в коде я ничего говорить не буду... ну, почти ничего. Все, что можно было сказать,
уже сказано до меня. Все равно лень людям их писать. Одно только
вам посоветую: если уж сильно неохота сочинять комментарии 50/50 с кодом - все-таки постарайтесь
самые ключевые и/или неочевидные моменты отмечать.
И запомните: неряшливый и запутанный код
нужно не комментировать, а переписывать!
3. Именованные константы пишите в верхнем регистре, чтобы можно было мгновенно отличить их от переменных. Например, MAX_ELEMENTS и BORDER_WIDTH, а не Max_Elements и border_width.
4. Имена переменных начинайте с маленькой буквы, названия типов - с заглавной.
5. Глобальные переменные по написанию должны отличаться от обычных. Как правило, для этого используют префикс "g_": g_RefCount, g_BaseDir. Вообще, их количество следует минимизировать. Статические переменные можно обозначать суффиксом "s_", члены классов- "m_".
6. Переменным, имеющим длительный период существования, следует давать длинные имена. Локальным и временным переменным можно давать имена покороче.
7. Помните, что объект всегда подразумевается, т.е. не нужно повторять имя объекта в его методе. Например, MyObject->GetObjectColor() - эту функцию следует назвать просто GetColor().
8. Вкладывайте смысл в имена функций. Используйте слово "find" когда где-то что-то ищется, "get" когда что-то хотите получить, "set"- установить. "Initialize" или "init" - инициализация, "compute" - вычисление, "open/close" - открытие/закрытие, и т.д. Также в паре следует использовать следующие имена: add/remove, create/destroy, start/stop, insert/delete, increment/decrement, old/new, begin/end, first/last, up/down, min/max, next/previous, old/new, open/close, show/hide. Т.е. если вы одну функцию назвали AddTitle(), то противоположную по действию надо назвать не DestroyTitle() или DeleteTitle(), а RemoveTitle().
9. Перед именами переменных, представляющих количество чего-то, ставьте префикс "n": nColors, nItems. Переменные, обозначающие порядковый номер чего-то, дополняйте суффиком "No": RecordNo, LineNo.
10. Не злоупотребляйте сокращениями. Согласитесь, что, например, смысл GetListAverage() гораздо легче понять, чем GetLstAvg() (ведь это, в принципе, может обозначать и GetLastAvenger() ;-).
11. Избегайте логических переменных, обозначающих отрицание. Found, а не notFound; Good, а не notGood. Вообще, хорошим стилем считается дополнять логические переменные префиксом "is": isFound, isGood. Это же относится к функциям, возвращающим значение true/false, напр. IsKindOf().
12. Константы из типов-перечислений (enum) должны содержать имя типа. COLOR_BLUE, а не BLUE; FILE_ERROR_ALREADY_EXISTS, а не ALREADY_EXISTS.
13. Всегда приводите типы к нужным явно, не полагаясь на автоматику.
14. Переменные, связанные между собой по
смыслу, можно объявлять одной строкой:
int x,y,z;
Record
first,last, next, previous;
Никак не связанные переменные лучше объявлять на
разных строках, даже если они одного типа.
15. В пустых циклах хорошо явно прописывать continue. Этим вы показываете, что оставили цикл пустым нарочно, а не по ошибке. Пример: while ( *p++ = *q++ ) continue;
Ну, хватит пожалуй. Если кто-то особенно заинтересовался
этим вопросом, он может посмотреть более чем 70 подобных правил в Geosoft's C++ Programming Style
Guidelines.
Должен заметить, что далеко не со всеми положениями этого
документа я согласен. Например, я не считаю нужным обязательно начинать
имена функций с маленькой буквы, - действительно важно различать переменные и
типы, а функцию от типа отличить гораздо легче. Или еще, например, правило всем
private-членам классов давать суффикс "_" - ну вот не нравится и
все тут... Я здесь привел самые, на мой взгляд, нужные и, прошу прощения за
тавтологию, "правильные" правила; те, которые встречаются практически во всех
документах такого типа.
Так что дам еще один, последний, совет: подходите ко
всем правилам, необходимость которых для вас не очевидна, с некоторой
толикой здравого смысла.
/ / / ВОПРОС-ОТВЕТ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
|Q Как в VC++ 6.0 можно сделать окно, которое не будет видно на Taskbar'e? - Kirill
(): BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)|A Самый простой способ - это создать основное окно с расширеным стилем окна WS_EX_TOOLWINDOW:
hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, szWindowClass, szTitle, < BR > WS_OVERLAPPEDWINDOW,0,0,100,100,NULL, 0, hInstance, NULL);При использовании MFC следует перекрыть метод PreCreateWindow
Но такое решение не всегда приемлемо - у созданного таким образом окна на тайтлбаре может находится только кнопка закрытия, и его заголовок отличается от заголовков других окон (он меньше). Для того, чтобы исправить эти недостатки, сначала создаем невидимое окно со стилем WS_EX_TOOLWINDOW, а затем дочернее окно, которое будет выполнять роль основного окна приложения. Это будет выглядеть следующим образом:
//...
HWND hWnd1,hWnd2;
hInst = hInstance;
hWnd1 =
CreateWindowEx(WS_EX_TOOLWINDOW , szWindowClass1, szTitle, 0, 0, 0, 100, 100,
NULL, 0, hInstance, NULL); // cоздаем невидимое
окно
// создаем окно, которое будет основным; указываем hWnd1 в
кач.родителя:
hWnd2 = CreateWindowEx(0, szWindowClass2, szTitle,
WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, hWnd1, 0, hInstance, NULL);
ShowWindow(hWnd1,
FALSE); // скрываем 1-ое окно
UpdateWindow(hWnd1);
ShowWindow(hWnd2, nCmdShow);
// делаем дочернее окно видимым
UpdateWindow(hWnd2);
- Bad Sector
|Небольшое дополнение:Если вам нужно убирать кнопку с таскбара только тогда, когда ваше приложение минимизировано (например, чтобы реализовать функцию "минимизировать в системный трей"), то все становится гораздо проще. Достаточно в обработчике OnSysCommand поставить реакцию на минимизацию окна ( т.е. когда параметр nID равен SC_MINIMIZE вызывать ShowWindow(hWnd, SW_HIDE) ). А при получении соответствующего сообщения от иконки в трее, не забывать восстановить окно. (про работу с системным треем см. выпуск No.11)
/ / / В ПОИСКАХ
ИСТИНЫ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/ / / / / /
Q| В Visual C++ 6.0 создаётся ImageList с помощью
ImageList_LoadImage. Потом две загруженные картинки рисуются в окошке - сначала
одна, потом поверх неё другая (используется маска) - функция ImageList_Draw.
Проблема в том, что рисуется только в 16 стандартных цветах. Картинка 24-битная.
Пробовал и с 256 и 16-цветными, с использованием палитры - эффект тот же. Если
не сложно, подскажи, как её нарисовать в 16M цвете (использую только API, без
MFC)? - Дрон
Всего вам доброго и не скучайте !
©Алекс Jenter
mailto:jenter@mail.ru
Красноярск, 2000.