Если
вам когда-нибудь приходилось разбираться в чужой программе, или даже в
своей собственной, но написанной несколько лет назад, да еще когда
поджимает время, вы скорее всего знаете, какая это неприятная и сложная задача.
Порой бывает легче
весь код написать заново (а многие так и делают). Конечно, существует поговорка
"настоящие программисты не пишут комментарии: если программу было трудно
написать, в ней должно быть трудно что-то понять и еще труднее
что-либо изменить". О комментариях мы еще поговорим, печально то, что очень
многие следуют этому принципу в самой программе. "Неважно", думают они, "как это
написано, главное побыстрее проверить, работает ли это вообще". Самые прилежные
из них впоследствии переписывают отдельные куски кода, но таких
единицы. Большинство же, убедившись в работоспособности алгоритма,
оставляют все как есть и переходят к новым задачам. Как
показывает многолетняя практика, это большая ошибка. Усилия, потраченные на
"причесывание" кода, окупаются с лихвой. Но по-настоящему ценится
умение писать сразу такой код, который не нуждается в причесывании. Это
умение не приходит само по себе, а вырабатывается постепенно, в нем надо
постоянно практиковаться. И когда вы говорите себе "а, это ведь просто небольшая
утилитка для удобства, вот когда получу настоящий заказ - буду писать красиво",
вы тем самым приучаете себя к неправильному стилю написания
программ.
Однажды я прочитал такую интересную мысль: программы надо
писать не для компьютера, а для людей. Следует сразу
рассчитывать на то, что этот код будут смотреть сотни или даже тысячи
программистов. Компилятор же нужен просто для проверки орфографии.
Вот несколько практических советов и рекомендаций.
Профессионалам многие из них покажутся очевидными, но для новичков, я
считаю, будут очень полезны.
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-членам классов давать суффикс "_" - ну вот не нравится и
все тут... Я здесь привел самые, на мой взгляд, нужные и, прошу прощения за
тавтологию, "правильные" правила; те, которые встречаются практически во всех
документах такого типа. Так что дам еще один, последний, совет: подходите ко
всем правилам, необходимость которых для вас не очевидна, с некоторой
толикой здравого смысла.
Но такое решение не всегда приемлемо - у созданного
таким
образом окна на тайтлбаре может находится только кнопка закрытия, и его
заголовок отличается от заголовков других окон (он меньше). Для того, чтобы
исправить эти недостатки, сначала создаем невидимое окно со стилем
WS_EX_TOOLWINDOW, а затем дочернее окно, которое будет выполнять роль
основного окна приложения. Это будет выглядеть следующим
образом:
|Небольшое
дополнение:Если вам нужно убирать кнопку с таскбара только
тогда, когда ваше приложение минимизировано (например, чтобы реализовать
функцию "минимизировать в системный трей"), то все становится гораздо проще.
Достаточно в обработчике 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)? - Дрон