вторник, 29 июля 2008 г.
RT/CT, Часть 1
Это очень интересная и сложная тема, в которую вливаются вопросы ORM и IoC. Основные вопросы — архитектурные (скорость работы, кэши, перекачка в память из памяти), дизайн ("вот как у нас тут всё делается") и затраты ("сейчас это сделаем — потом будем только донастраивать").
В первую очередь речь идет о новых разрабатываемых системах, т.к. в наследованном или коробочном ПО вопрос "что где хранить" уже как-то решен и используется как есть. Если же разрабатывается новый продукт или запускается новый проект, всегда присутствует соблазн попробовать сделать что-то по новому и учесть допущенные ранее ошибки.
Самый простой на мой взгляд вопрос RT/CT возникает при разработке любых типов данных, завязанных на справочники: работа с датой и временем, списки стран и городов, флаги, валюты, единицы измерения и т.д. Часть из них уже встроены в операционную систему или используемый фрэймворк, но чаще нет, либо чего-то не хватает. Если разрабатывается крупная система со своей БД, то ответ часто прост: всё будем хранить в БД. Но тоже не всегда.
Возьмем в качестве примера не совсем реальную ситуацию — работа с датой/временем и календарем (т.к. обычно всё уже и так есть). Нужны названия месяцев и дней недели на разных языках, списки праздничных дней, региональные форматы вывода — их можно хранить в базе. А вот схемы расчета когда какой месяц настает (для Израиля и многих мусульманских стран нетривиально) — это чистый код... который настоящие "хардкорные" программисты оформят в виде хранимой процедуры, конечно. "Хардкорные" потому, что всё чаще "серьёзные" задачи автоматизации приходится решать "обычным" программистам облегченными средствами веба, динамических языков, а также java и .NET. Оформить календари в виде кода очень заманчиво: это просто, удобно в отладке и тестировании в духе Calendars.Gregorian.GetMonth(), опять же подсказка в редакторе работает, а благодаря средствам контроля версий такой код находится в большей безопасности. С другой стороны, без дополнительных усилий такие календари и месяцы не будут доступны средствам, опирающимся только на базу — в первую очередь разные генераторы отчетов. Ок, ок — конечно, генераторы сами умеют отображать даты, — я говорил, что пример нереальный.
Поэтому пример второй: единицы измерения, где та же потребность в названиях, форматах отображения и непростые методы расчета значений. Пользуясь нереальным предыдущим примером, можно обрисовать идеал реализации и предугадать возможные ошибки. Дата/время в базе выражаются универсальным независимым от страны или языка числом (миллисекунд с 1 января 1970 года). Соответственно для каждой физической величины (в том числе и времени) нужно было бы ввести универсальное представление числом, а все-все методики пересчета, отображения и конвертации отразить в коде и ресурсах. И перетащить/внедрить всё это в генератор отчетов. И было бы ошибкой переносить какие-то структурные и алгорифмические вещи, подверженные ошибкам, расширению функционала и постоянным улучшениям, в базу данных. Как сказал кто-то умный, ведь данные живут десятилетиями, в то время как код редко "живет" дольше пяти лет (а чаще и года не живет).
Хорошо, но что если нам необходимо в runtime добавить еще одну единицу измерения (завести её в формочке нашей новой учетной системы) и... сохранить?
Возьмем пример третий, посложнее: адрес. У адреса сложная иерархическая структура, которую проблемно спрятать. Да и использование числового значения, вроде широты/долготы, не кажется разумным или осуществимым. Ну... пожалуй, этот пример слишком сложный.
среда, 2 июля 2008 г.
Пара слов об архитектуре и дизайне
В любой деятельности человек, прежде всего, стремиться к тому, чтобы в основе её лежали правильные соображения. Результатом «правильных соображений» может оказаться что угодно. У каждого свои взгляды на то, что считать правильным, и как правильно вести дела. Это и становится причиной большинства конфликтов. Программные системы не являются исключением.
Когда говорят о правильных тенденциях в программном обеспечении, используют понятия архитектуры и дизайна.
Современный взгляд на архитектуру и дизайн программных систем состоит в том, что это в чем-то пересекающиеся понятия. Принято считать, что не существует единых и общепризнанных определений дизайна и архитектуры. В разных источниках встречается различные определения. От совсем простых:
Architecture is the organizational structure of a system.
IEEE Std. 610.12-1990
Архитектура – это организационная структура системы.
Стандарт IEEE 610.12-1990
Design – (1) The process of defining the architecture, components, interfaces, and other characteristics of a system or component. (2) The result of the process in (1).
IEEE Std. 610.12-1990
Дизайн – (1) Процесс задания архитектуры, компонентов, интерфейсов и других характеристик системы или компонента. (2) Результат этого процесса в (1).
Стандарт IEEE 610.12-1990
И расширенных:
The software architecture of a program or computing system is the structure or structures of the system, which comprise software components the externally-visible properties of those components and the relationships among them.
Len Bass, Paul Clements, Rick Kazman: Software Architecture in Practice, Addison-Wesley, 1998
Архитектура программной или вычислительной системы – это структура системы (или набор структур, её составляющих), которая включает в себя программные компоненты, видимые извне свойства этих компонентов и отношения между ними.
Лен Басс, Пол Клеменс, Рик Кацман, «Программная архитектура на практике», Addison-Wesley, 1998
Design is the activity of making explicit proposals for a change from an existing system to some future system which more closely approximate
mankind's concept of the ideal.
Tom Maver, Professor of
Дизайн – это деятельность по выдвижению явных предложений о переходе от существующей системы к некоторой будущей системе, которая бы лучше соответствовала человеческому пониманию идеала.
Том Мавер, профессор университета Статклайд в Глазго
До совсем уж сложных:
Software architecture is a set of concepts and design decisions about the structure and texture of software that must be made prior to concurrent engineering to enable effective satisfaction of architecturally significant explicit functional and quality requirements and implicit requirements of the product family, the problem, and the solution domains.
Jazayeri, Ran, van der Linden: Software Architecture for Product Families: Principles and Practice, Addison Wesley Longman, 2000
Программная архитектура – это набор понятий и проектных решений в отношении структуры и строения программного обеспечения, которые должны быть приняты до начала параллельного проектирования, чтобы обеспечить эффективное удовлетворение внешних функционально значимых и качественных архитектурных требований, а также безусловных требований к данному семейству продуктов, проблемных областей или решений.
Джэзаери, Ран, Ван дер Линден, «Программная архитектура для семейств продуктов: принципы и практика», Addison Wesley Longman, 2000
Design is the process of applying various techniques and principles for the purpose of defining a device, a process, or a system in sufficient detail to permit its physical realization.
Roger S. Pressman: Software Engineering: A Practioners Approach, McGraw-Hill, 1992
Дизайн – это процесс применения различных техник и принципов в целях задания устройства, процесса или системы в детализации, достаточной для их физической реализации.
Роджер С. Прессман, «Разработка программного обеспечения: подход практиков», McGraw-Hill, 1992
Пересечение понятий архитектуры и дизайна проявляется в ответе на вопрос о том, что же конкретно является результатом применения дизайна. Учитывая, что дизайн – это неотъемлемое свойство системы, порожденное применением практик определенного дизайна, довольно сложно сформулировать, как этот результат соотносится с архитектурой. К примеру, использование классов – это дизайн или архитектура? Проект начинается с архитектуры, но и на стадии завершения она всё еще с нами, только теперь может отличаться от первоначальной.
И хотя для большого количества понятий можно достаточно точно разделить, что в них относится к дизайну, а что влияет на архитектуру, остается множество вещей, доказательство принадлежности которых к тому или другому – сплошная софистика.
В то же время, разделение проектных решений на архитектурные и дизайнерские, вопрос не праздный. В отношении дизайна, как результата, бытует мнение, что дизайн – это архитектура в малом. И если архитектурой призваны заниматься эрудированные умники с чистыми волосами, то дизайн – удел странноватых программистов. Так принято. Часто случается, что архитектор системы самоустраняется сразу же после утверждения основных диаграмм и переходит на другой проект, и на другой проект, и на другой проект, оставляя непродуманные решения на совесть программистов. Часто случается, что программисты убивают на корню любую, даже самую продуманную, архитектуру, внося ужасные ошибки и делая неумные дизайнерские ходы.
Также часто можно услышать, что где-то пожертвовали дизайном ради эффективности (под которой понимается скорость исполнения алгоритмов), или ради скорости разработки. Жертвуют ли архитектурой?
Архитектурой жертвовать нельзя. Как следует из определений, архитектура задается еще до начала параллельной разработки. Соответственно, нарушение архитектурных соглашений легко может привести к тому, что проект рассыплется, как Шалтай-болтай. Из другого определения видно, что архитектура – это набор свойств и соглашений, видимых извне. Нарушения в данной области приведут к тому, что продукт принципиально не сможет быть интегрирован с окружением и другими системами так, как это задумывалось. С такой точки зрения, разделение на архитектуру и дизайн также означает приоритетность определенных установок для команды проекта. Вероятно, архитектуру можно определить и так:
Проектные решения, которыми жертвуют только при пересмотре взглядов на проект в целом.
И в отличие от ошибок в программировании, возможно порожденных неправильным дизайном, архитектурные ошибки стоят разработчикам гораздо дороже первых.
Не имея архитектуры, кажется нельзя даже подступиться к проекту. По крайней мере, очень сложно вести параллельную разработку. Видимо, архитектура – первое, что приходит в голову.
В то же самое время, дизайн имеет отношение к выбранному языку, инструментам и программному коду. Дизайн определяет культуру программирования и квалификацию разработчиков.
Поэтому архитектор, приступая к проекту, должен сам для себя ограничить меру ответственности, чтобы не заступать на территорию дизайна и не тормозить тем самым ход разработки.
Вспоминаю, как в первый день руководитель отдела кадров знакомил меня с сотрудниками, представляя: «Наш новый главный архитектор». К концу того же дня один из моих новых коллег обратился ко мне, плохо понимая, в чем состоят мои обязанности. «В общем и целом, — заметил он, разглядывая стены и потолок, — здание выглядит неплохо. И что Вы намерены с ним делать?»
Стив Виноски, «Все начинается с архитектуры», Открытые системы, №1, 2004
В общем и целом, архитектура программного обеспечения (ПО), также как и архитектура здания, призвана сделать продукт эстетичным, прочным и долговечным. Архитектура должна не позволить развалиться проекту, открытому всем ветрам изменений, и найти уязвимые места, даже если «здание выглядит неплохо». Архитектура не должна быть слишком сложной для имеющихся средств реализации. А также понятной для тех, кто будет строить.
Сравнение процесса создания программ с процессом возведения сооружений очень глубоко проникло в умы и отразилось в терминологии. Употребляются такие слова как architecture, build, framework и т.д. Очевидно, что подобное сравнение импонирует разработчикам. Вот некоторые особенности современного строительства, которые очень хотелось бы видеть в разработке ПО:
· Всё строится из готовых стандартных блоков;
· Много формальных методов для проектирования и собственно строительства;
· Наличие большого числа метрик для объективной оценки качества;
· Предсказуемость процесса во времени и затратах;
Ничто из этого на момент 2008 года не имеет ничего общего с разработкой ПО. Сравнение со строительством также переносит на программное обеспечение некоторые сомнительные следствия:
Алан Кей
Алан Кей - изобретатель самого словосочетания "объектно-ориентированный". Еще до поступления в 1966 году в аспирантуру университета штата Колорадо по теме «Математика и молекулярная биология», Алан отслужил на тренировочной базе Рандольф (Randolph), где работал с компьютером Burroughs 220. Burroughs 220 – ламповый компьютер фирмы Burroughs Corporation, расположенной в Детройте. Разработан в 1957 году компанией Electrodata Corporation и назывался Electrodata Datatron 220 до того, как Electrodata была поглощена Burroughs. В разное время стоил от $601 000 до $325 000 и выполнял умножение за 2, а деление почти за 4 микросекунды.
Эта история по-разному перевирается различными изданиями. Здесь приводится версия журнала PC Magazine и самого Алана, которая кажется наиболее правдоподобной.
В 50-х не существовало единых стандартов на форматы документов. Еще до Алана Кея на базе Рандольф работал неизвестный программист, который создал под Burroughs 220 некоторое количество полезного программного обеспечения. Получаемые данные записывались на бобины с магнитной лентой. К сожалению, они не имели никакого смысла для компьютеров Burroughs других тренировочных баз, поскольку на них не было того уникального ПО. Вместо того чтобы распространить свои программы на другие машины, неизвестный гений нашел другое решение: он стал записывать на бобины данные в виде программ, которые содержали и данные, и алгоритмы обработки. Может показаться, что он придумал себе лишнюю работу.
В действительности, им было использовано очень прогрессивное решение, которое обладает следующими преимуществами:
1. Данные полностью переносимы в пределах определенной аппаратной платформы.
2. Изменения в формате данных не затрагивают существующие бобины. Данные по-прежнему доступны, и для этого не требуется дополнительного программирования.
Сущность преимуществ остается непонятной, пока мы смотрим на программное обеспечение, как на конструирование. Ну что нам стоит поддерживать несколько форматов наших же данных? По-видимому, Кей в то время также не оценил подхода. По долгу службы, в 1961 году, ему пришлось поддерживать имеющееся решение, и он слегка изменил его. Теперь на все машины Burroughs все же ставилась небольшая программа, предоставляющая пользовательский интерфейс для загрузки модулей, как он назвал имеющийся гибрид данных и программ. И только работая над кандидатской диссертацией в 1966 году, он понял всю оригинальность идеи.
В понимании Алана Кея, модули, переименованные им в объекты, представляли собой почти физически отдельные сущности, объединяющие данные и код, и обменивающиеся асинхронно друг с другом посредством передачи сообщений. Самым близким аналогом таких объектов могут служить изолированные процессы в современной многопользовательской операционной системе (ОС). Объекты в нотации Кея могли бы совместно работать в распределенной сети. Для того времени это было слишком революционно.
Объектно-ориентированное программирование, придуманное Кеем, вводит два основных принципа. Первый – принцип рекурсивного дизайна:
The basic principal of recursive design is to make the parts have the same power as the whole.
Alan С. Key: The Early History of Smalltalk, 1993, ACM 0-89791-571-2/93/0004/0069
Основной принцип рекурсивного дизайна – стремится сделать так, чтобы части обладали возможностями целого.
Алан Кей, «Ранняя история SmallTalk», 1993, Издания компьютерного сообщества, статья №0-89791-571-2/93/0004/0069 (далее [KEY01])
Принцип постулирует, что программный объект должен обладать возможностями целого компьютера. Объектный анализ вычислительной машины с такой точки зрения говорит, что компьютер состоит из компьютеров меньшего масштаба. Для программной системы это выражается в том, что вся система, также как и её функциональные части, доступна в виде объекта. Самоподобие определяет структуру системы в процессе ее разработки, а это есть дизайн.
Второй принцип определен следующим образом:
…everything we can describe can be represented by the recursive composition of a single kind of behavioral building block that hides its combination of state and process inside itself and can be dealt with only through the exchange of messages.
…все, что мы можем описать, может быть представлено в виде рекурсивной композиции единственного типа поведенческих блоков, которые скрывают в себе комбинацию состояния и выполняющего процесса, и работа с которыми может вестись только посредством обмена сообщениями.
[KEY01]
Этот принцип вводит очень важную абстракцию, позволяющую не только инкапсулировать сложность, но и строить повторно используемые объекты. В современном понимании второй принцип Кея реализуется в компонентах. Компоненты – это очень спорное понятие, не меньше чем само объектно-ориентированное программирование.
Интерфейс компонента – это видимая извне, публикуемая, характеристика. Поэтому использование компонентного подхода наряду с декларацией основных интерфейсов определяют архитектуру будущей системы.
Рассмотрим подробнее следствия из указанных принципов, какими они видятся на современном этапе развития технологий, и подчеркнем некоторые распространенные, в какой-то степени ошибочные, представления. Собственно, при более подробном изучении вопроса оба принципа выражают одну и ту же точку зрения.
Применение практики рекурсивного дизайна оказывает серьезное влияние на программный проект. Самым простым следствием оказывается тот факт, что приходится писать больше программного кода. Это происходит потому, что рекурсивно стыкуемые элементы обязаны иметь понятный и унифицированный интерфейс. Применение разных критериев качества к «внешним» и «внутренним» компонентам системы становится признаком плохого дизайна, поскольку теперь нет по отдельности «внешнего» и «внутреннего».
Вторым следствием является более согласованная структура системы. Очевидно, что абстракция самого верхнего уровня, выражаемая объектом «Система» (System), «Приложение» (Application) или «Окружение» (Environment), предоставляет наиболее полный и доступный для понимания программный интерфейс. Для прикладного программиста он определяет «лицо» системы. Настолько же высокие требования теперь должны быть представлены и ко всем другим составляющим. Результатом этого оказывается структура, отдельные элементы которой более доступны для непосредственного программного манипулирования и анализа, чем при разработке закрытых модулей. Такую структуру проще понять и проще подвергнуть тестированию.
Объединение данных с кодом, который их обрабатывает, до сих пор вызывает много споров между сторонниками ООП и защитниками процедурного программирования. Ранние пользователи С++, перешедшие на него с Си или процедурного Паскаля, отмечали полезность ухода от глобальных переменных модулей и функций. Превращение структур в классы означало для них избавление от ошибок несогласованного изменения общих данных. Основные доводы противников классов и инкапсуляции, как с той курицей, сводятся к высказываниям, вроде «если мы с Гошей программируем на Си очень аккуратно и согласованно, то у нас всё получается быстрее и лучше, чем со всеми этими «правильными» классами и объектами».
Изучая психологию детей на основе работы Сеймура Паперта (детский психолог, создатель языка LOGO для обучения программированию очень маленьких детей от пяти лет), Кей пришел к выводу о большом значении интерактивной среды программирования, которая бы обеспечивала возможность непосредственного взаимодействия с объектами программируемой системы. Созданная им впоследствии среда для Smalltalk позволяла программировать систему «в горячем режиме», т.е. добавлять и изменять код, не уничтожая существующие в системе объекты и потоки исполнения.
В данный момент Алан Кей не считается авторитетом в среде объектно-ориентированного программирования. Он работает на компанию Walt Disney и разрабатывает новые виды аттракционов для детей и взрослых.