Мое мировоззрение, как программиста, сформировалось еще во времена консольных приложений и текстовых пользовательских интерфейсов, на смену им пришли графические оконные GUI, а сейчас я наблюдаю уже третий виток технологий, связанный с глобальной сетью. Каждый раз, конечно же, приходилось менять не только любимый язык программирования, но и весь технологический стек, с наработками, заготовками и достаточно обширными библиотеками, кои сейчас гордо зовутся фреймворками. Резать приходилось по живому, нещадно и решительно.
В последнее время веб-браузер стал почти синонимом пользовательского интерфейса, и ни у кого уже не возникает сомнений, что традиционные оконные приложения, устанавливаемые в персональный компьютер, уже отходят в историю. Хоть за ними и останется небольшой процент ПО, но и за консольными приложениями он ведь тоже остался навсегда.
Наблюдая за становлением третьего, на моей памяти, поколения технологий и специалистов, могу отметить, что повторяются как “велосипеды”, так и “грабли”. Именно поэтому, я не мог не написать этой статьи. Имея большой соблазн, спуститься в самую конкретику и разобрать по винтикам несколько современных языков и технологий, их связки и особенности стыковки, но оставим это для других статей и сконцентрируемся на принципах, остающихся неизменными во всех инкарнациях информационных систем. Каждый из принципов я поясню на нескольких примерах, уже привязанных к вебу.
1. Не нужно измышлять хитростей там, где можно сделать просто.
1.1. Например, не стесняйтесь отказаться от ООП там, где старое доброе процедурное программирование быстрее и эффективнее. Разворачивать классы и объекты в памяти имеет смысл в таких задачах, когда инстанс приложения будет жить хоть какое-то продолжительное время. А когда скрипт запускается чтобы за доли секунды отдать ресурс, то разветвленные концептуальные классы совсем ни к чему. В конце концов, выдача ресурсов веб-сервером, это нечто сродни stdout, выданный кусок уже не изменить. Хотя, в серверных задачах, как демоны, пакетная и отложенная обработка, кравлеры, вычисления и т.д., ООП конечно же нужен.
1.2. Кто сказал, что для наследования и переопределения, обязательно нужны объекты? Вполне подойдет иерархическая файловая структура или иерархические запросы к базе.
1.3. Если Вас беспокоит, что код выглядит не круто, а даже совсем просто, но поставленную задачу все ровно выполняет, то стоит пересмотреть свои представления о программировании. Совсем не обязательно в одном проекте применить все известные паттерны и концепции.
1.4. Общественное помешательство на шаблонизаторах мне не вполне понятно, ведь большинство скриптовых веб-языков сами являются шаблонизаторами. Самый яркий пример – это PHP: переменные подставляет, циклы и ветвление есть, а главное, что все это не требует дополнительного парсинга шаблонов. При внедрении акселераторов, шаблоны будут прекомпилироваться в байт-код так же, как и все другие части программы.
1.5. Сейчас многие руководствуются принципом “скачать из интернета и прикрутить”, но даже если времени мало, то хоть просмотрите скачанный код, возможно, это натолкнет на мысль, как то же самое сделать более просто. Ведь нет ни какой гарантии, что автор скачанного кода имел больше опыта, таланта и времени, чем Вы. Ну и конечно же, если Вы относитесь серьезно к системе, которую пишете, то должны знать, понимать и чувствовать каждую строку кода в ней.
2. Выберите и зафиксируйте инструментарий на продолжительное время, если хотите разнообразия в функционале.
Это эмпирический принцип, который, тем не менее, всегда срабатывает. Возможно, некие академики выведут его из фундаментальных законов мироздания, а нам же пока ни кто не мешает использовать его на интуитивном уровне. Я думаю, что большинство из вас смогут привести массу примеров, когда более четкие и жесткие языки и технологии становятся платформой для более разнообразного софта. В меньших масштабах мы можем просто вводить корпоративные стандарты, внутренние спецификации, форматы и протоколы.
3. Неуместное и не адекватное использования инструментов встречается чаще, чем плохие инструменты.
У каждого языка и технологии есть круг задач, для которых он подходит как нельзя лучше, а для других задач наверняка есть свои адекватные средства решения.
4. Невозможно и не нужно отделять данные, логику и представление на одном слое абстракции.
Это удивительно, но еще до изобретения MVC, и уж тем более, до его массового внедрения программисты понимали, что в каждом модуле всегда есть три части: логика, данные и отображение (или код, структуры памяти и интерфейс). Но вот в последнее время я наблюдаю злоупотребление этим принципом, мол “сказали разделять, то мы и разделим”. А разделять не всегда и получится. Даже если выделить слой представления (отображения), то в нем всегда найдется место всем трем частям: логике отображения, данным отображения и шаблонам отображения. Поэтому делить можно вечно, а Змей Горыныч, все равно будет о трех головах. Та же ситуация и с выделением модели и контроллера, в них опять можно будет выделить все три компоненты. Упорная борьба с этим фактом приводит многих к порождению неимоверного количества кода, классов, конструкций и примочек. Я не говорю, что MVC не работает, просто не нужно его использовать так фанатично, повсеместно и энергично. Помните, борьба с проблемой может только ее усугубить, не лучше ли принять и даже использовать этот факт. В конце концов, правильное понимание вопроса породило такие классы систем как СУБД, сервера приложений и GUI. Заметьте, в формулировке я написал именно “на одном слое абстракции”. Поясню: СУБД оперирует и данными и логикой и отображением на уровне реляционной абстракции (или же других информационных моделей), сервер приложений оперирует на уровне абстракции предметной области (или на уровне метапрограммирования), интерфейс пользователя оперирует совершенно другим аспектом той же задачи. То есть, разделать нужно не данные, логику и представление (их-то нужно скорее выделять, чем разделать), а абстракции или аспекты задачи.
5. Нет идеального кода, нужно довольствоваться какой-то степенью универсальности.
Мне, как идеалисту и перфекционисту, осознать это было сложнее всего. Мне бы волю, то программный код бы совершенствовался до умопомрачения, вплоть до того, как программа не начала бы решать все мыслимые и не мыслимые задачи и стала бы называться просто “программой”. Доведение до абсурда может быть завершено только на протяжении бесконечного времени, а оптимизация кода должна устремить его длину к нулю. Такая программа просто обязана решить все задачи программирования раз и навсегда. Но на практике нужно совсем другое, а именно – решить прикладную задачу, которая не так уж и требует идеального кода. Конечно, код должен радовать своей красотой, но не увлекайтесь.
6. Любой экстремизм плох.
Если помочь тому, кто ошибается, довести заблуждение до абсурда, то он сам от него откажется в пользу разумного. Простое — надежнее сложного, хорошее — выгоднее плохого, а качественное — в конечном итоге, дешевле некачественного. Только гордыня и страхи не дают увидеть простых путей, не нужно прилагать сверхусилий для достижения целей, лучше отказаться от ошибок и желаемое совпадет с реальностью.
7. Развитие системы ведет к ее ограниченности.
Любая система, в том числе и информационная, для развития требует принятия решений, но каждое решение приводит не только к появлению функционала, но и к созданию ограничений. Поэтому, вводя допущения и (assumptions) принимая решения, всегда думайте, к каким ограничениям это ведет и готовы ли вы к ним.
Это все. Надеюсь, кому-то пойдет впрок.