Эпилог
Если бы люди могли учиться у истории, какие уроки она могла бы нам преподать!
Но страсть и компания слепят наши очи, и свет, даваемый опытом, – как кормовой огонь, освещает только волны позади нас.
Сэмюэль Тейлор Колридж
Воспоминания
Компьютерный мир постоянно изменяется, причем во все возрастающем темпе. Программисты вынуждены овладевать новым: новыми языками, новыми инструментами и новыми системами и, конечно, изменениями, не совместимыми со старым. Программы становятся все объемнее, интерфейсы все сложнее, а сроки все жестче.
Однако есть некоторые неизменные моменты, позволяющие осмыслить уроки прошлого, что может помочь в будущем. Основные вопросы, освещенные в этой книге, базируются как раз на этих неизменных концепциях.
Простота и ясность – первые и наиболее важные среди этих основ, поскольку все остальное так или иначе из них следует. Делайте все самым простым способом. Выбирайте наиболее простой алгоритм, который выглядит достаточно быстрым, и наиболее простую структуру данных, позволяющую решить поставленную задачу; объединяйте их простым, понятным кодом. Не усложняйте ничего до тех пор, пока в этом не возникнет настоятельной необходимости, – например, пока замеры производительности не покажут неудовлетворительных результатов. Интерфейсы должны быть ограничены и лаконичны, по крайней мере до тех пор, пока не станет совершенно очевидно, что преимущества от нововведений перевесят недостатки дополнительного усложнения.
Универсальность нередко идет рука об руку с простотой, поскольку является, по сути, возможностью решить проблему раз и навсегда (так сказать, "в общем виде"), а не возвращаться к ней снова и снова для рассмотрения специфических случаев. Зачастую это является и хорошим подспорьем для обеспечения переносимости: лучше найти одно общее решение, которое будет работать во всех системах, чем разбираться в отличительных особенностях каждой системы.
Далее стоит назвать эволюцию. Невозможно написать совершенную программу с первой попытки. Глубокое и всестороннее осознание проблемы рождается только из сочетания размышлений и опыта; с помощью чисто умозрительных заключений не удастся создать хорошей системы, как не удастся сделать этого и чистым хакерством. Очень важна реакция пользователей; наиболее эффективным будет цикл развития системы, включающий в себя создание прототипа, экспериментирование, обратную связь с пользователем и дальнейшие усовершенствования. Программы, которые мы пишем для себя, часто не развиваются; достаточным образом; большие программы, которые мы покупаем у других, изменяются слишком быстро без нужного улучшения.
Интерфейсы являются одним из камней преткновения в программировании, и аспекты, связанные с ними, проявляются во многих местах. Наиболее очевидный случай – библиотеки, но существуют еще интерфейсы между программами и между пользователями и программами. В проектировании интерфейсов идеи простоты и универсальности имеют особое значение. Делайте интерфейсы как можно более последовательными, чтобы их можно было без труда выучить и использовать; к этому надо подойти очень тщательно. Эффективным способом является абстрагирование: представьте себе идеальный компонент, библиотеку или программу; постарайтесь, чтобы ваш интерфейс как можно более полно соответствовал такому идеалу; спрячьте детали реализации – от греха подальше.
Роль автоматизации часто недооценивается. Гораздо эффективнее заставить компьютер выполнять вашу работу, чем делать ее вручную. Мы увидели примеры применения автоматизации при тестировании, отладке, анализе производительности и, что особенно важно, в написании кода, когда для решения конкретной задачи программы могут писать программы, которые было бы трудно написать вручную.
Нотация также зачастую недооценивается; и не только в качестве способа, которым программист сообщает компьютеру, что надо сделать. Способ записи представляет собой основу для реализации широкого: спектра инструментов, а также обусловливает структуру программы, предназначенной для написания программ. Мы все хорошо владеем большими языками общего назначения, которые служат нам для создания основной части наших программ. Однако, как только задания становятся настолько специализированными и хорошо понятными, что запрограммировать их можно почти механически, стоит задуматься о том, чтобы создать нотацию, в которой задание выражалось бы естественно, и язык, реализующий эту нотацию. Регулярные выражения – один из наших любимых примеров, но возможностей создания рабочих языков для специализированных приложений существует бесчисленное множество. Для того чтобы дать хорошие результаты, языки эти вовсе не должны быть сложны.
У рядового программиста может иногда возникнуть ощущение, что он является винтиком в огромной машине: ему приходится использовать навязанные ему языки, системы и инструменты, выполняя задания, которые должны были бы быть уже сделаны для него и за него. Однако, по большому счету, наша работа оценивается по тому, как много мы можем сделать с помощью того, что у нас есть. Применяя идеи, изложенные в этой книге, вы обнаружите, что с вашим кодом стало удобнее работать, отладка стала гораздо менее болезненным процессом, да и в своих программах вы стали более уверены. Мы надеемся, что эта книга дала вам что-то, что сделает программирование более продуктивным и успешным для вас.