Vitalii Tsybulnyk / Виталий Цыбульник

On Software Development / О софтверной разработке

About the author

    Vitalii Tsybulnyk
Vitalii Tsybulnyk is a Software Engineering Manager at Mictosoft Azure.
E-mail me Send mail

Activity

Recent comments

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008-2017

Является ли применение шаблонов проектирования частью архитектуры приложения?

В обсуждении моей статьи "Архитектура программного обеспечения с человеческим лицом" на RSDN пользователь Eye of Hell задаёт интересный вопрос, на который я решил ответить отдельным постом: Если предположить, что приложение достаточно большое (архитектура утилиты ping как правило тривиальна), то интересно, какие именно "шаблоны проектирования" имелись в виду относительно архитектуры. Если описанные в книге gang of four — то непонятно, какое они отношение имеют к архитектуре. Те шаблоны — это рецепты по решению небольших задач в рамках программы. Совсем небольших. Тоесть понятно что в Microsoft Word применяется шаблон проектирования "observer". Даже несколько тысячь раз применяется. Но является ли это (существенной) частью архитектуры приложения? Нельзя же сказать что "архитектуры photoshop состоит из шаблонов проектирования visitor, observer и facade". Или можно? Пожалуй, стоит начать ответ с того, что действительно, как резонно замечено в вопросе, существует большое количество типов шаблонов проектирования. Для демонстрации этого факта обратимся к определению термина "шаблон проектирования" на Википедия: В разработке программного обеспечения, шаблон проектирования или паттерн - повторимая архитектурная конструкция, представляющая собой решение проблемы проектирования в рамках некоторого часто возникающего контекста. Обычно шаблон не является законченным образцом, который может быть прямо преобразован в код; это лишь пример решения задачи, который можно использовать в различных ситуациях. Объектно-ориентированные шаблоны показывают отношения и взаимодействия между классами или объектами, без определения того, какие конечные классы или объекты приложения будут использоваться. «Низкоуровневые» шаблоны, учитывающие специфику конкретного языка программирования, называются идиомами. Это хорошие решения проектирования, характерные для конкретного языка или программной платформы, и потому не универсальные. На наивысшем уровне существуют архитектурные шаблоны, они охватывают собой архитектуру всей программной системы. Английская версия статьи даёт даже больше деталей: There are many types of design patterns including: structural design patterns, computational design patterns, algorithm strategy patterns, implementation strategy patterns and execution patterns. Structural patterns address concerns related to the high level structure of an application being developed . Computational patterns address concerns related to the identification of key computations. Algorithm strategy patterns address concerns related to high level strategies that describe how to exploit application characteristic on a computation platform. Implementation strategy patterns address concerns related to the realization of the source code to support (i) how the program itself is organized and (ii) the common data structures specific to parallel programming. Execution patterns address concerns related to the support of the execution of an application, including the strategies in executing streams of tasks and building blocks to support the synchronization between tasks. Некоторые из перечисленных типов шаблонов можно более уверенно отнести к предмету архитектуры приложения, некоторые скорее можно назвать деталями реализации архитектуры, чем архитектурой как таковой - это только подчёркивает упомянутый в статье факт размытости понятия архитектуры и субъективности принятия решений о включении или не включении в проект приложения различных аспектов или деталей устройства системы. Что же касается объектно-ориентированных шаблонов (aka 'Gang of Four', 'GoF'), упомянутые в вопросе, то их применение несомненно можно отнести к предмету архитектуры. Это подтверждается не только определением самих объектно-ориентированных шаблонов как шаблонов "проектирования", а не "кодирования", но и опытом применения этих шаблонов при разработке программных продуктов. Однако не стоит забывать что GoF-шаблоны - это шаблоны "мелкоузлового" проектирования, которые нельзя ставить в один ряд с "крупноузловыми" enterprise-шаблонами наподобие MVC, Client-Server или N-Tier. Если говорить на примерах архитектуры зданий, то GoF-шаблоны - это например общепринятные способы прокладки коммуникаций или планировки комнат. Автор вопроса играет словами в духе "является ли способ соединения проводов на щитке частью архитектуры многоэтажного здания" или "влияет ли положение газовой плиты на кухне квартир 3-го этажа на структуру всего дома". Думаю, любой архитектор ответит без доли сомнения, что проектирование всех этих вещей очень важно и несомненно является частью архитектуры здания. Возвращаясь к упомянутым Microsoft Word или Photoshop - как непосредственный участник процесса разработки продуктов такого уровня могу раскрыть вам небольшой секрет - в проектировании таких продуктов принимает участие не один-два, а десятки архитекторов. Из них каждый имеет свою специализацию и большинство из них занимается как раз "мелкоузловой" архитектурой, в которой применение наилучшего набора шаблонов проектирования может сыграть немалую роль. Перефразируя вопрос, можно сказать, что "архитектура Photoshop состоит из модулей A, B, C и D, организованных по enterprise-шаблону X; при проектировании модуля A были использованы GoF-шаблоны observer и facade; при проектировании модуля B был использован GoF-шаблон visitor". Надеюсь что ответил достаточно полно, однако читая между строк вопроса, мне кажется что на самом деле вопрос звучал так: "Чем больше приложение, тем менее детально оно проектируется, тем меньше проектных деталей включается в архитектуру, так ведь?". Отвечаю: нет, как раз наоборот. Фазы проектирования небольших программ (например упомянутой утилиты ping) может не быть вовсе, проект от этого врядли пострадает, и от того какой именно GoF-шаблон применит разработчик зависит не так уж много в проекте. Однако при проектировании продуктов, рассчитанных на долгие годы сопровождения и развития, в разработку которых вкладываются сотни человеко-лет, неудачное применение молодым разработчиком GoF-шаблона в критичном месте может сыграть злую шутку, поэтому такие решения должны приниматься как минимум группой разработчиков, а более вероятно архитекторами и техническими экспертами на этапе проектирования. Таких проектрых решений в продукте принимаются тысячи, это верно, однако это никак не умаляет их значимость для системы, а как раз наоборот, значимость согласованного и синхронного применения шаблонов даже на уровне "мелкоузлового" проектирования в больших и сложных системах существенно выше.

Categories: Architecture
Posted by Vitalii Tsybulnyk on Monday, January 17, 2011 5:09 AM
Permalink | Comments (3) | Post RSSRSS comment feed

Inside Windows Azure

Cloud Computing and Windows Azure were the leading subjects of PDC 2010 last fall. Fortunately, there are a lot of amazing videos of the presentations available, and Inside Windows Azure by Mark Russinovich is definitely my favorite. Mark provides a very clear 'big picture' review of Windows Azure's features and internal arrangement. He gives just the right amount of technical details to be useful to a wide audience, from cloud application developers to software product owners and company leaders. I highly recommend this video to anybody who is interested in modern IT trends in general and cloud computing in particular.

Posted by Vitalii Tsybulnyk on Friday, January 14, 2011 4:06 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Архитектура программного обеспечения с человеческим лицом

С задержкой в несколько месяцев наконец-то вышел №2 журнала RSDN за 2010-й год с моей статьёй "Архитектура программного обеспечения с человеческим лицом". Первая версия статьи была написана ровно год назад, в декабре 2009-го, и стала своеобразным итогом моего видения процесса разработки программного обеспечения в целом, и его архитектуры в частности, как гибкого, человеко-центристского, я бы даже сказал социального явления. Статья несколько раз дорабатывалась и даже переписывалась вплоть до весны 2010, когда и созрел окончательный вариант, отправленный в RSDN. Электронная версия статьи ещё не появилась на rsdn.ru, и мне не известны сроки её электронной публикации. К сожалению, RSDN не продаётся и не доставляется вне Росиийской Федерации, так что если вдруг у кого-то уже имеется бумажная копия журнала, или есть намерение приобрести, я был бы крайне признателен за сканы. Традиционная аннотация: В статье автор подводит итог и пропускает через призму собственного опыта основные человеческие аспекты архитектуры программного обеспечения. Рассматривается эволюционная природа архитектуры, особенно ярко выраженная в малых проектах и стартапах. Субъективность решений по поводу применения шаблонов проектирования в социальном контексте конкретного проекта приводит к наличию разных стилей применения этих шаблонов. Неоднозначность и многогранность роли архитектора подчёркивает и усиливает первоочерёдность человеческих факторов (личных и командных) для процесса принятия технических решений и проектирования архитектуры в проектах по разработке программного обеспечения.

Posted by Vitalii Tsybulnyk on Sunday, December 5, 2010 2:15 PM
Permalink | Comments (3) | Post RSSRSS comment feed

Software Architects Are Number One

In their November issue, CNN Money Magazine rated "Software Architect" as the number 1 job in America! What they do: Like architects who design buildings, they create the blueprints for software engineers to follow -- and pitch in with programming too. Plus, architects are often called on to work with customers and product managers, and they serve as a link between a company's tech and business staffs. What's to like: The job is creatively challenging, and engineers with good people skills are liberated from their screens. Salaries are generally higher than for programmers, and a typical day has more variety. "Some days I'll focus on product strategy, and other days I'll be coding down in the guts of the system," says David Chaiken, 46, of Yahoo in Sunnyvale, Calif., whose current projects include helping the web giant customize content for its 600 million users. Even though programming jobs are moving overseas, the face-to-face aspect of this position helps cement local demand. What's not to like: You are often outside the management chain of command, making it hard to get things done. Requirements: Bachelor's degree, and either a master's or considerable work experience to demonstrate your ability to design software and work collaboratively. Stats: Pay: Median pay (experienced) $119,000 Top pay $162,000 Opportunity: 10-year job growth (2008-2018) 34% Total jobs (current) 110,000 Quality of life ratings: Personal satisfaction B Job security B Future growth A Benefit to society C Low stress C Flexibility A

Posted by Vitalii Tsybulnyk on Thursday, October 14, 2010 12:05 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Design Guidelines for Developing Frameworks and Class Libraries

After I spent the last couple of months designing some class library for Windows Azure engineering infrastructure, I realized that design principles for frameworks and class libraries are not exactly the same as for 'off the shelf' or enterprise applications and systems. The fundamental difference is that, in the case of applications, customers don't care about your code at all, so you can use all techniques you want to make your design elegant and easy to maintain. In the case of framework/library, quite the contrary is true: your code is in some ways a user interface, which customers see, use, and care about a lot. Believe it or not, this difference significantly influences your architecture and OOD decisions in ways you may not expect. In this post, I've collected the advice I'd give to framework/library designers. Some of these suggestions are based on these sources [1-2]; however, most of them are from my own experience. Some of this advice might contradict traditional design principles, so be careful and use them for public API/frameworks only. Fundamentals 1. Framework designers often make the mistake of starting with the design of the object model (using various design methodologies) and then write code samples based on the resulting API. The problem is that most design methodologies (including most commonly used object-oriented design methodologies) are optimized for the maintainability of the resulting implementation, not for the usability of the resulting APIs. They are best suited for internal architecture designs—not for designs of the public API layer of a large framework. When designing a framework, you should start with producing a scenario-driven API specification. This specification can be either separate from the functional specification or can be a part of a larger specification document. In the latter case, the API specification should precede the functional one in location and time. The specification should contain a scenario section listing the top 5-10 scenarios for a given technology area and show code samples that implement these scenarios. 2. Common scenario APIs should not use many abstractions but rather should correspond to physical or well-known logical parts of the system. As noted before, standard OO design methodologies are aimed at producing designs that are optimized for maintainability of the code base. This makes sense as the maintenance cost is the largest chunk of the overall cost of developing a software product. One way of improving maintainability is through the use of abstractions. Because of that, modern design methodologies tend to produce a lot of them. The problem is that frameworks with lot of abstractions force users to become experts in the framework architecture before starting to implement even the simplest scenarios. But most developers don’t have the desire or business justification to become experts in all of the APIs such frameworks provide. For simple scenarios, developers demand that APIs be simple enough so that they can be used without having to understand how the entire feature areas fit together. This is something that the standard design methodologies are not optimized for, and never claimed to be optimized for. Naming Guidelines 3. The code samples should be in at least two programming languages. This is very important as sometimes code written using those languages differs significantly. It is also important that these scenarios be written using different coding styles common among users of the particular language (using language specific features). The samples should be written using language-specific casing. For example, VB.NET is case-insensitive, so samples should reflect that. Think about different languages even when you name classes, e.g. don't make mistakes like the NullReferenceException class which can be thrown by VB code, but VB uses Nothing, not null. Avoid using identifiers that conflict with keywords of widely used programming languages. 4. The simplest, but also most often missed opportunity for making frameworks self-documenting is to reserve simple and intuitive names for types that developers are expected to use (instantiate) in the most common scenarios. Framework designers often “burn” the best names for less commonly used types, with which most users do not have to be concerned. For example, a type used in mainline scenarios to submit print jobs to print queues should be named Printer, rather than PrintQueue. Even though technically the type represents a print queue and not the physical device (printer), from the scenario point of view, Printer is the ideal name as most people are interested in submitting print jobs and not in other operations related to the physical printer device (such as configuring the printer). If you need to provide another type that corresponds, for example, to the physical printer to be used in configuration scenarios, the type could be called PrinterConfiguration or PrinterManager. Similarly, names of most commonly used types should reflect usage scenarios, not inheritance hierarchy. Most users use the leaves of an inheritance hierarchy almost exclusively, and are rarely concerned with the structure of the hierarchy. Yet, API designers often see the inheritance hierarchy as the most important criterion for type name selection. For example, naming the abstract base class File and then providing a concrete type NtfsFile works well if the expectation is that all users will understand the inheritance hierarchy before they can start using the APIs. If the users do not understand the hierarchy, the first thing they will try to use, most often unsuccessfully, is the File type. While this design works well in the object-oriented design sense (after all NtfsFile is a kind of File) it fails the usability test, because “File” is the name most developers would intuitively think to program against. Classes vs. Interfaces 5. In general, classes are the preferred construct for exposing abstractions. The main drawback of interfaces is that they are much less flexible than classes when it comes to allowing for evolution of APIs. Once you ship an interface, the set of its members is fixed forever. The only way to evolve interface-based APIs is to add a new interface with the additional members. A class offers much more flexibility. 6. Abstract types do version much better, then allow for future extensibility, but they also burn your one and only one base type. Interfaces are appropriate when you are really defining a contract between two objects that is invariant over time. Abstract base types are better for define a common base for a family of types. 7. When a class is derived from a base class, I say that the derived class has an IS-A relationship with the base. For example, a FileStream IS-A Stream. However, when a class implements an interface, I say that the implementing class has a CAN-DO relationship with the interface. For example, a FileStream CAN-DO disposing. Methods vs. Properties There are two general styles of API design in terms of usage of properties and methods: method-heavy APIs, where methods have a large number of parameters and the types have fewer properties, and property-heavy APIs, where methods with a small number of parameters and more properties to control the semantics of the methods. 8. All else being equal, the property-heavy design is generally preferable. 9. Properties should look and act like fields as much as possible because library users will think of them and use them as though they were fields. 10. Use a method, rather than a property, in the following situations:  - The operation is orders of magnitude slower than a field access would be. If you are even considering providing an asynchronous version of an operation to avoid blocking the thread, it is very likely that the operation is too expensive to be a property. In particular operations that access the network or the file system (other than once for initialization) should likely be methods, not properties.  - The operation returns a different result each time it is called, even if the parameters don’t change. For example, the Guid.NewGuid method returns a different value each time it is called.  - The operation has a significant and observable side effect. Notice that populating an internal cache is not generally considered an observable side effect.  - The operation returns an array. Properties that return arrays can be very misleading. Usually it is necessary to return a copy of an internal array so that the user cannot change the internal state. This may lead to inefficient code. Events 11. Consider using a subclass of EventArgs as the event argument, unless you are absolutely sure the event will never need to carry any data to the event handling method. If you ship an API using EventArgs directly, you will never be able to add any data to be carried with the event without breaking compatibility. If you use a subclass, even if initially completely empty, you will be able to add properties to the subclass when needed. Enums 12. Use enums if otherwise a member would have two or more Boolean parameters. Enums are much more readable when it comes to books, documentation, source code reviews, etc. Consider a method call that looks as follows. FileStream f = File.Open (“foo.txt”, true, false); This call gives the reader no context with which to understand the meaning behind true and false. The call would be much more usable if it were to use enums, as follows: FileStream f = File.Open(“foo.txt”, CasingOptions.CaseSensitive, FileMode.Open); Some would ask why we don’t have a similar guideline for integers, doubles, etc. Should we find a way to “name” them as well? There is a big difference between numeric types and Booleans. You almost always use constants and variables to pass numeric values around, because it is good programming practice and you don’t want to have “magic numbers”. However, if you take a look at real life source code, this is almost never true of Booleans. 80% of the time a Boolean argument is passed in as a literal constant, and its intention is to turn a piece of behavior on or off. We could alternatively try to establish a coding guideline that you should never pass a literal value to a method or constructor, but I don’t think it would be practical. I certainly don’t want to define a constant for each Boolean parameter I’m passing in. Methods with two Boolean parameters, like the one in the example above, allow developers to inadvertently switch the arguments, and the compiler and static analysis tools can't help you. Even with just one parameter, I tend to believe it's still somewhat easier to make a mistake with Booleans ... let's see, does true mean "case insensitive" or "case sensitive"?   Sources 1. MSDN 'Design Guidelines for Developing Class Libraries' 2. Krzysztof Cwalina, Brad Abrams 'Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries'

Posted by Vitalii Tsybulnyk on Thursday, August 26, 2010 2:07 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Какие бывают архитекторы и архитектуры

Мне кажется, что роль Архитектора - это пожалуй одна из самых значимых и одновременно самых неоднозначных ролей в процессе разработки ПО. Это связано с очевидной важностью, но тем не менее неоднозначностью самого понятия "архитектура". Согласно RUP архитектура - это "высший уровень концепта системы в её рабочем окружении. Архитектура программной системы (в определённый момент времени) - это её организация или структура наиболее значимых компонент, взаимодействующих через интерфейсы, а эти компоненты в свою очередь составлены из более мелких компонентов и интерфейсов." Однако Мартин Фаулер считает это определение абсолютно надуманным [1], т.к. по его мнению у программных систем нет "высшего концептуального уровня", пользователь имеет обсолютно другое видение концепции системы, чем разработчики, пользователя абсолютно не волнует "структура наиболее значимых компонент". По мнению Фаулера "архитектура - это высший уровень концепта, который сложился у разработчиков о системе в её рабочем окружении. При этом учитывается видение разработчиков уровня эксперта, и именно это делает компоненты такими значимыми - так сказали эксперты." Таким образом, более корректным определением могло бы быть “В наиболее успешных софтверных проектах разработчики-эксперты, работающие над проектом, имеют общее пронимание строения этой системы, которое называется ‘архитектура’. Это понимание включает в себя деление системы на компоненты и их взаимодействие между собой через интерфейсы. Эти компоненты обычно состоят из более мелких компонент, однако архитектура включает в себя только те компоненты и интерфейсы, которые поняты всеми разработчиками." Такое определение лучше, поскольку оно отражает социальную природу арихитектуры, т.к. она не столько зависит от ПО как такового, сколько от того, каков групповой консенсус по поводу этого ПО [1]. Существует и другой стиль определения архитектуры: “арихитектура - это набор решений об устройстве системы, которые должны быть приняты на ранних стадиях проекта”, однако Фаулер не соглашается и с этим, т.к. "архитектура - это набор решений, которые хотелось бы сделать правильно на ранних стадиях проекта, однако это не значит что они окажутся верными с большей вероятностью, чем любые другие". Тем более, что согласно такому определеню, например выбор языка программирования был бы частью архитектуры для большинства проектов, хотя это не так. Всё это демонстрирует сложности формулировки точного определения понятия архитектуры. Говоря проще, "архитектура - это всё наиболее важное в проекте, что бы это ни было" [1]. Так мы приходим к заключению, что раз архитектура - это важные вещи, то Архитектор - это человек, занимающийся наиболее важными для проекта вещами. И вот на этом этапе Фаулер выделяет два типа архитекторов [1]:  - Architectus Reloadus (по прообразу персонажа из фильма "Matrix Reloaded") - это человек, принимающий в проекте все важные решения. Он делает это потому, что принятие ключевых решений одним человеком повышает целостность системы, и возможно ещё потому, что он не считает остальных членов команды достаточно компетентными для принятия таких решений. Зачастую такие решения должны быть приняты вначале цикла разработки, чтобы у всех остальных был план, которому можно следовать.  - Architectus Oryzus (если кто-то знает латынь, помогите с переводом) - этот вид архитекторов осведомлён о том, что происходит в проекте, выявляя важные загвоздки и устраняя их до того как они превратятся в серьёзные проблемы. Наиболее важная часть работы таких архитекторов - это интенсивное сотрудничество: работа с разработчиками над кодом, работа с бизнес-аналитиками над техническим смыслом и последствиями реализаций требований и идей на нетехническом языке и т.п. Ценность архитектора этого типа "обратно пропорциональна количеству решений, которые он принимает" [1]. Не менее интересную крассификацию архитектур и архитекторов предлагает Люк Хохман [2]. Он разделяет софтверную систему на два измерения:  - tarchitecture (техтектура или “техническая архитектура”), за неё обычно отвечает традиционный архитектор или технический руководитель - tarchitect (техтектор)  - marketecture (маркетектура или “меркетинговая архитектура”), её определяет продукт-менеджер, бизнес-менеджер или програм-менежер - marketect (маркетектор). Техтектура преобладает, когда разработчики думают об устройстве системы. Маркетектура - это бизнес перспектива этого устройства. Хотя техтектура и маркетектура влияют друг на друга, маркетектура доминирует: маркетектурные вопросы - начиная от юзабилити, апгрейдабилити,  саппортабилити и заканчивая развёртываемостью и надёжнотью (т.н. нефунциональные требования) - меняются радикально от рынка к рынку и влияют на техтектуру более значительно, чем техтектурные вопросы о внутреннем устройстве системы влияют на её бизнес-ценность. Я бы даже усилил это утверждение: по-настоящему хороший продукт начинается тогда, когда маркетекрута полностью перестаёт подчиняться техтектуре, а техтектура в свою очередь действует исключительно в рамках предложенной маркетектуры.   Источники  1. Martin Fowler 'Who Needs an Architect?' 2. Luke Hohmann 'The Difference between Marketecture and Tarchitecture'

Posted by Vitalii Tsybulnyk on Saturday, August 22, 2009 7:21 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Рефакторим базу данных

Последние годы техника рефакторинга настолько прочно вошла в методологии процессов разработки ПО и инструментарий разработчиков, что всё чаще и чаще звучат утверждения о начале эры принципиально новых, эволюционных подходов к проектированию архитектуры. Пожалуй, одной из немногих областей, которая ещё прочно держит позиции предварительного проектирования, является структура базы данных. Действительно, изменение структуры базы данных по ходу жизненного цикла сопряжено с рядом существенных струдностей и затрат: это и миграция данных, и необходимость каскадного изменения кода приложений, использующих базу данных, и ряд других объективных трудностей. Однако, прогресс не стоит на месте, мыслители и идеологи рефакторинга и гибких методолий конечно же не мирятся с таким упущением. Наглядное тому подтверждение - некоторые книги и статьи Мартина Фаулера и его соратников. Одна из первых таких публикаций - это статья Фаулера 'Evolutionary Database Design', которая собственно и натолкнула меня на написание данного поста. Прежде чем говорить о применении техник рефакторинга по отношению к базам данных, нужно упомянуть некоторые ограничения, выход за рамки которых может существенно затруднить или даже сделать невозможными эти техники: 1. База данных исполюзуется в одном приложении или системе, это не интегрированная база данных для многих систем. 2. База данных не должна работать бесперебойно 24/7 Если данные условия соблюдены для вашего случая, можете смело рассчитывать применять к своей базе данных все те же подходы, которые уже успрешно применяете для всего остального кода проекта. Вот некоторые детали реализации рефакторинга применительно к базе даннных: 1. DBA и девелоперы должны очень тесно сотрудничать, т.к. рефакторинг базы данных с большой вероятностью влечёт изменения кода. Устраните все физические, психологические и бюрократические препятствия на пути их сотрудничества. Лично я всегда предпочитал DBA и девелопера в одном лице, котя конечно же это далеко не всегда целесообразно и возможно. 2. У каждого участника процесса есть своя копия базы данных для експериментов по нахождения оптимального рефакторинга. 3. Тестовая база данных - это не просто схема, она также содержит тестовые данные, близкие к реальным. Рефакторинг базы данных - это не только изменение схемы, он зачастую требует миграции и т.п. работы с данными. Чем больше данных содержит ваша тестовая база данных, тем более гладко пройдёт рефакторинг на продакшн базе. 4. Все изменения в базе данных по ходу работы над проектом - это рефакторинги, поэтому применяйте к ним те же шаги и правила, что применяете к обычному рефакторингу (см. Martin Fowler 'Refactoring: Improving the Design of Existing Code') 5. Автоматизируйте свой рефакторинг по окончанию работы над ним: сохраните скипт, производящий ваш рефактронг, с тем чтобы простым запуском этого скрипта вы могли выполнить рефакторинг на любой из копий базы данных, включая продакшн. 6. Сообщайте о изменнениях в базе всем разработчикам, лучше через автоматическую отправку е-мейла. 7. Выделяйте в своей системе явно выраженный слой доступа к данным, это позволит свести к минимуму последствия рефакторинга базы для остального кода (воспльзуйтесь одним из паттернов, описанных Фаулером в 'Patterns of Enterprise Application Architecture'). Ну и напоследок, хороший предварительный дизайн базы данных - это бесспорно очень хорошее начало для любого проекта. Однако последующие изменения неизбежны, и в нех нет абсолютно ничего страшного. Эволюционное изменение базы данных по ходу проекта не только уменьшит для вас затраты на предварительный дизнайн, но и избавит ваших разработчиков от необходимости подстраиваться под неудачный или устаревший дизайн базы данных. Следуйте приведённым выше рекомендациям и изменение базы данных превратиться для вас из страшилки для новичков в обыденную работу над доведением системы до идеала.

Posted by Vitalii Tsybulnyk on Tuesday, August 11, 2009 4:25 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Проектирования больше нет?

Martin Fowler (Мартин Фаулер) бесспорно является одним из самых уважаемых авторов в области современного проектирования и архитектуры программных продуктов. Его бестселлеры 'Refactoring: Improving the Design of Existing Code' и 'Patterns of Enterprise Application Architecture' - это, пожалуй, наиболее ценные книги, прочитанные мною за всю мою профессиональную жизнь. Недавно мне в руки попала замечательная статья Мартина с броским названием 'Is Design Dead?' (в русском переводе "Проектирования больше нет?"), о которой сегодня и пойдёт речь. Основная идея статьи - обсудить изменения в подходах к проектированию программных систем в связи с переходом к гибким (Agile) методологиям. Провокационное название статьи отражает тот факт, что многие Agile методологи (в первую очередь XP) преподносят дизайн системы как нечто возникающее эволюционно, в процессе непосредственного кодирования: Методология XP бросила вызов многим устоявшимся представлениям о разработке программного обеспечения. Пожалуй, наиболее противоречивой идеей является отказ от предварительного проектирования в пользу более эволюционного подхода. Для приверженцев новой методологии, это отказ от техник проектирования (например, UML), их принципов и паттернов. Незачем беспокоиться о проектировании, считают они. Достаточно внимательно "вслушиваться" в свой код, и проектирование образуется само собой. Фаулер, как выдающийся специалист в области проектирования, конечно же не соглашается с таким утверждением: В большинстве случаев, эволюционное проектирование - это нечто ужасное. В конце концов, все равно вместо дизайна системы вы получаете просто набор из специфических решений, каждое из которых затрудняет дальнейшие изменения в программном коде. Часто это вообще нельзя считать дизайном (и, уж конечно, такой дизайн никак нельзя назвать хорошим). Как говорит Кент, дизайн существует для того, чтобы дать возможность оперативно вносить в систему любые изменения. Если дизайн плох, то такая возможность исчезает. В результате вы будете иметь дело с энтропией программного продукта, и со временем и без того плохой дизайн системы станет еще хуже. Теперь вам будет не только сложнее вносить в систему изменения, но и отыскивать и исправлять ошибки, которые начинают множиться с катастрофической быстротой. Все это - кошмар разработок в стиле "code and fix", когда с течением времени исправление ошибок обходится все дороже и дороже. Однако одновременно являясь ярым приверженцем Agile и автором "библии" рефакторинга, Фаулер признаёт и рекламирует их эффективность: В методологии XP имеется много спорных моментов. Одним из ключевых таких моментов является то, что она базируется на эволюционном, а не предварительном проектировании. В основе этого утверждения лежит кривая стоимости изменений в программном продукте. XP строится на предположении, что эту кривую можно сгладить до такой степени, чтобы можно было применять эволюционное проектирование. Такое сглаживание, с одной стороны, возникает при использовании методологии XP, а с другой, оно же в ней и используется. Это еще раз подчеркивает тесную взаимосвязь между практиками ХР: нельзя использовать те части методологии, которые предполагают существование сглаживания, не используя те практики, которые это сглаживание осуществляют. У практик, с помощью которых осуществляется сглаживание, есть множество составляющих. В основе всех их лежит Тестирование и Непрерывная интеграция. Именно надежность кода, которую обеспечивает тестирование, делает возможным все остальное в этой методологии. Подобный эффект имеет и рефакторинг. В статье Фаулер пытается найти компромис, балланс между традиционными (и бесспорно необходимыми) методиками проектирования с одной стороны и Agile с другой: Джим Хайсмит ... использует аналогию с обычными весами. На одной чаше лежит предварительное проектирование, на другой - рефакторинг. В более традиционных подходах к разработке ПО перевешивает предварительное проектирование, так как предполагается, что передумать вы не можете. Если же стоимость изменений снизится, то часть проектирования можно делать и на более поздних стадиях работы, в виде рефакторинга. Это вовсе не означает отказа от предварительного проектирования. Однако теперь можно говорить о существовании баланса между двумя подходами к проектированию, из которых можно выбрать наиболее подходящий. Все эти основополагающие практики (непрерывная интеграция, тестирование и рефакторинг) создают новую среду, в которой эволюционное проектирование выглядит вполне убедительно. Впрочем, мы еще не выяснили, где же у этих весов точка равновесия. Лично я уверен, что не смотря на поверхностное впечатление, методология ХР - это не просто тестирование, кодирование и рефакторинг. В ней найдется место и для предварительного проектирования. Частично оно производится еще до написания первой строчки кода, но большая его часть приходится на то время, которое предшествует реализации конкретной задачи в течение итерации. Впрочем, такая ситуация представляет собой новое соотношение сил между предварительным проектированием и рефакторингом. Собственно, вся статья и посвящена нахожденю этого компромисса. Показывается полезность и органичность предварительного проектирования в XP, преимущества и критерии простого дизайна перед сложным при условии следования всем остальным практикам XP, показывается эффективное сосуществование принципа YAGNI ("You Aren't Going to Need It" - "Это вам не понадобится") и рефакторинга, применимость и ценность паттернов проектирования и даже UML в XP. Пожалуй я воздержусь от приведения здесь заготовленных мною цитат из статьи, а закончу пост настоятельной рекомендацией причитать эту статью. Она как никакая иная ценна для опытных разработчиков, архитекторов и менеджеров, переходящих на Agile методологии и имеющих какие-то сомнения по применимости своих знаний и умений в новых условиях. Статья не мене полезна и тем, кто имеет большой опыть например в XP, но не имеющих базисных знаний и умений в предварительном проектировании. И пожалуй наиболее полезна статья тем, чьи знания, умения и опыт равноценны в обеих сферах, т.к. изложенные концепции позволят наиболее эффективно и гармонично использовать и сочетать все эти бесценные умения в вашей работе.

Posted by Vitalii Tsybulnyk on Wednesday, July 22, 2009 7:06 AM
Permalink | Comments (1) | Post RSSRSS comment feed