Пользователь
0,0
рейтинг
18 июля 2010 в 19:45

Разработка → Общие соображения по архитектуре ПО или Пособие для Главного Плотника (часть 2: что такое плохо и что с этим делать)

продолжение первой части, которая находится вот здесь

Что такое плохо?



Плохо может наступить, когда хотя бы одно-единственно правило не соблюдается. Например, все счастливы и довольны, все мегастандартно, просто и доступно. Но максимальное количество пользователей в системе на сервер – 10, а надо – 1000. Остальные сценарии додумайте сами, благо это просто. В принципе, плохо может наступить, даже если все пункты соблюдены, просто потому, что жизнь многогранна, и список не может быть исчерпывающим.

Например, одна из неприятностей, которая может случиться, – внезапная смена требований заказчиком. Т. е. вчера мы хотели делать распределенную 5-звенную систему, а сегодня централизованную 2- звенную. В общем случае бороться с этим невозможно и бессмысленно. Хуже того, целенаправленно бороться с этим вредно, один мой коллега сильно усложнил свой модуль, обосновывая это тем, что вдруг заказчик захочет сменить БД, а у нас все уже готово. Но могут помочь несколько советов.

1. Делайте все как можно проще. Простые решения проще переделывать.
2. Делайте все как можно проще, быстрее сделаете – быстрее начнете переделывать.
3. Делайте все как можно проще, простые решения не так жалко ломать.
4. Делайте все как можно менее связанным. Меньше связей – проще переделать отдельный кусок. Избегайте антипаттерна «банка с червяками».
5. По возможности при прочих равных используйте стандарты, если что-то пойдет не так, проще отмазаться. Т.е. если можно сделать UI на Swing или SWT – лучше выберите Swing: все примерно одинаково, зато, если что-то пойдет не так с SWT – вам это обязательно припомнят.
6. Все ходы записывайте. Надо помнить что email, как ни странно, обычно является доказательством в суде. И хотя не дай вам бог дойти до суда, но документировать все и просить важные моменты подтвердить по email можно и нужно.

Несколько советов и историй россыпью


Есть ряд вещей, которые не везде применимы, и, если даже применимы, не всегда стоит применять их все. Но, как правило, в нужном контексте они изрядно облегчат вашу непростую жизнь:

1. Вся система должны быть разделена на относительно компактные модули, каждый из которых кто-то досконально знает, и при этом модуль устроен в соответствии с общими командными стандартами. Если что-то пойдет не так, и разработчика переедет грузовик, то другой разработчик сможет в нем разобраться за разумное время. Идеально, если у вас совместное владение кодом и считается, что каждый разработчик должен уметь при наличии необходимости поменять код любого другого разработчика.

Эффект грузовика

Есть такое устойчивое словосочетание «Эффект грузовика». Это ситуация, когда устройство какого-то критичного модуля знал один человек, модуль большой, разобраться в нем не просто, человек тот кодировал, как ему удобно, а не как это принято в команде. И все было ОК, т. к. он брал на себя ответственность за модуль, и все всегда работало. Пока его не переехал грузовик…


2. Есть формальные и, что характерно, стабильные интерфейсы между модулями. Тут сильно помогает ведение документов со спецификациями и искоренение неформальных объяснений от одного девелопера другому, как оно работает. Есть дока, в ней написано, если непонятно, перепишем так, чтобы было понятно. Хотя это, конечно, идеальная ситуация.

3. Очень желательно избегать Copy&Paste. В реальности есть случаи, когда Copy Paste – лучшее решение, но, как правило, надо этого избегать. Например, нам надо вычислить URL картинки по ее ID, картинки показываются в 100 разных местах в приложении. Получается он очень просто: server.address/images.jpg. Но, если надо поменять это на images.server.address.jpg, то придется менять в 100 местах. И уж в одном точно сделаем ошибку. Пример, конечно, копеечный, но баги он может вызвать весьма весомые.

4. С другой стороны, также желательно избегать переусложнения. Городить 10 классов, чтобы избежать копирования одной строки один раз не стоит. Пример из практики. Был у меня класс для создания DTO-объектов из сущностей. Класс все делал сам, ориентируясь на аннотации. Причем DTO-объекты должны были получаться нескольких разных видов. Рос все более и более сложный универсальный класс. Потом мне это надоело, и я сделал три маленьких класса с общим утилитным классом. В этих 3-х классах было 50 % повторяющегося кода, мелко размазанного по методам. Зато классы были на порядок проще.

5. 10 раз подумайте, прежде чем использовать паттерн. Паттерны хороши, это коронные приемы в карате программной архитектуры, но, как говорил Брюс Ли, часто самый простой способ ударить – просто взять и ударить, без предварительного размахивания руками. Сколько раз я видел на форумах вот буквально такие сообщения: «Пацаны! Мне тут надо электронный магазин замутить, какие бы паттерны для этого использовать, я так думаю observer взять и синглтон, чего бы еще напихать?»

Предупреждение

Истину Вам говорю - паттерны для неокрепшего ума зло. Недавний пример - недавно коллега решая тестовую задачу от заказчика "сделать имплементацию интефейса для поиска максимального числа в массиве" умудрился использовать паттерн абстракная фабрика. Комментарий от заказчика не поддается переводу но примерно звучит как "где вы берете такую траву?".


Надо помнить, что даже если все эти правила соблюдены, и ваше решение оптимально, нравится команде и заказчику, 4 года работает без единой перезагрузки, все равно на 5-й год может придти только вылупившийся из яйца пионер и спросить: «А почему у вас не на Ruby? Я в журнале “Хакер” читал – Руби сейчас самая модная тема». При этом заказчик спросит: «Да, действительно, а почему? Вот и в журнале ”Хакер” об этом пишут". Главное тут – не кричать: «Убью заразу», –а аргументировано объяснить, куда надо засунуть Ruby и почему его нельзя засунуть непосредственно в проект. При этом:

1. Надо сохранить рассудок.
2. Не совершить уголовного преступления.
3. Иногда как ни странно можно сказать Ruby отстой, хочешь Ruby иди к другим девелоперам (с такими высказываниями впрочем надо быть осторожнее).
4. Можно пользоваться нечестными приемами вида:

* Таковы были изначальные требования заказчика;
* Ruby в те времена, когда мы начинали проект, еще и в зародыше не было;
* Spring это индустриальный стандарт «освященный» SUN (теперь уже Oracle).

Ничего не имею против Руби, просто лично на меня почему-то наезжали не менее двух раз, потрясая именно Руби, так что я решил, что это хороший пример. Хотя впрочем — Руби действительно отстой :-)

Что дальше?



Итак, мы разобрались, какая архитектура хорошая, а какая плохая. По большей части это технические решения. Но в любом случае эти решения реализуются вполне живой командой, т. е. группой людей, каждый из которых личность, яркая индивидуальность и имеет свое видение окружающего мира. Люди все разные, и это скорее хорошо, чем плохо, я бы даже сказал, замечательно, что все разные, но это надо учитывать при работе над проектом. Хуже того, люди вокруг проекта тоже живые и разные и могут предлагать вам делать странные или очень странные вещи (для вас, но не для их бизнеса). Далее россыпью ряд моментов, осложняющих жизнь архитектору, по-всякому связанных с тем, что вокруг живые люди.

Байка

Давно-давно я делал приложение, которое получало данные из определенного программного интерфейса и складывало их в БД. При недоступности БД данные складывались на жесткий диск в очередь. Пришел начальник и сказал: «Хочу, чтобы приложение, которое кладет данные на диск и которое читает, были два разных процесса». Почему он так сказал, для меня загадка по сей день. Может быть, сказался его опыт работы с UNIX-системами 10-летней давности, когда нити еще не придумали, и все делалось с помощью fork. Два разных процесса я сделал, но зачем это было надо, удивляюсь до сих пор. Вероятно, в этом и правда был смысл? Надо бы найти его как-то и спросить, да, боюсь, он уже не помнит.


Авторитет



Один из не вполне очевидных аспектов работы архитектора – авторитет. Вы можете быть очень опытным специалистом, предложить замечательное решение, но, если команда и/или заказчик будут считать вас недостаточно компетентным, счастья вам это не принесет. Причем хорошо, если авторитет велик, но в этом случае надо держать себя в руках и не давить авторитетом на команду.

Слишком мало


Предположим, что авторитета у вас слишком мало. Что не такая уж и редкость. Демократичность и доступность в общении очень этому способствуют. Скорее всего, вам придется объяснять каждое архитектурное решение каждому члену команды долго и нудно, каждый раз отвечая на глупые вопросы вида «А почему бы не сделать на Руби, я читал в “Плэйбое”, это очень модно». При этом если вы три года работали, например, с JSF и знаете все сильные и слабые стороны технологии, вам все равно не удастся переубедить человека, который дальше туториала не дошел, но тем не менее думает, что имеет право на свое мнение. Так как вам не верят и заведомо считают, что все, что вы предлагаете, – ересь. Авторитет – фактор сугубо нематериальный, но зачастую он может играть очень большую роль, особенно в длинных и сложных проектах.

Вы давите на команду авторитетом


Ситуация, когда вам верят безоговорочно, всем хороша, и вы можете сказать: «Так, используем EJB для связывания компонент. Я решил, так будет». Но есть проблемы.

1. Отсутствие обратной связи. Если вы что-то совсем уже не адекватное придумали, что иногда, но случается, никто вам об этом не скажет. Все будут упорно пытаться этому решению следовать, пока чаша народного терпения не переполнится, и вас не свергнут с трона.
2. Ошибаться вам никак нельзя. Если решения в той или иной степени обсуждаются и одобряется не только вами, но и командой, цена ошибки не так велика, легко можно сказать, что МЫ тут накосячили, давайте ВМЕСТЕ подумаем, что делать. Но если это было ваше единоличное решение, ответственность ляжет целиком на вас.
3. Вы можете банально разучиться обсуждать свои идеи с окружающими, а это не.очень полезно.

Если на клетке с тигром написано верблюд, не верь глазам своим



К сожалению, в мире IT на клетках с мышами пишут «лев» и продают как льва. Обусловлено это тем, что почти каждый может отличить льва от верблюда, но отличить хороший JMS-сервис от плохого могут не так уж много людей, и не всегда эти люди принимают решение. В принципе тут очень много зависит от отраслевой культуры. Например, в АСУТП доля нерабочих решений очень велика. Мне доводилось видеть продукты стоимостью > $ 1000, которые банально не работали вообще или без сбоев дольше двух часов, необходимых для проведения презентации. Как такое продавалось и зачем это покупалось? Ответы просты:

1. Откат и взятки.
2. Большой разрыв между людьми, владеющими деньгами, людьми, принимающими решение о покупке, и людьми, способными оценить, что же собственно купили.
3. В конечном счете, эту штуку таки заводили, окружив множеством подпорок. Последним я занимался лично и могу сказать что затраты на возведение подпорок зачастую в десятки раз превышали стоимость продукта.

В некоторых отраслях, например, в финансах (оговорюсь, в американских финансах) обитают очень прагматичные люди, и неработающих продуктов/технологий я там не видел (хотя, надо заметить, смотрел не очень много/долго).

Часто технология рекламируется как универсальное средство для всего, но в реальности ее применимость не так уж и широка. Так, в молодости я пытался использовать для передачи критичных данных по не надежной сети технологию DCOM (было это во времена NT4). Возникли проблемы, я провел ряд тестов и с удивлением обнаружил, что DCOM крайне неадекватно реагирует на разрыв соединения, в результате я все переделал на чистый TCP. Но что характерно, нигде на клетке с DCOM не было написано, что таймаут соединения для клиента и сервера нигде не выставляется, равен 8 минутам и на клиенте вообще не наступает (технические детали могу переврать, давно было).

Как архитектор я совершил одну большую и одну маленькую ошибку. Большая ошибка заключалась в том, что я не сделал прототипы перед тем как использовать незнакомую технологию. Маленькая – я не посмотрел, что по этому поводу говорят коллеги. Справедливости ради, последнее бы мне мало помогло т. к. в Интернете в ту пору (2000 г.) о DCOM говорили либо что это «ересь от MS, не пробовал и не собираюсь» либо, писали бодрые статьи о том, как DCOM ведет нас в светлое будущее. Более или менее здравых критических статей не было.

При этом с DCOM мне повезло, я принял на веру чьи-то слова, обжегся, но сам все исправил и не потратил чьи-то деньги или время.

Бывают, конечно, менее выпуклые примеры, цена ошибки там не так велика, но решить, что перед тобой все же верблюд, а не лев, сложнее.

Оптимизируйте заранее



Есть устойчивое мнение, что преждевременная оптимизация вредна, и это так на 100 %. Только высказывание это имеет контекст, а применяют его направо и налево, особенно если не умеют писать оптимальный код и вообще напрягать голову не хочется, а наоборот, хочется выглядеть крутым перцем, читающим модные статьи.
Когда оптимизировать заранее не надо и даже вредно

Например, раз в месяц мы выгружаем месячный агрегированный отчет. Генерация его занимает целый час. Можно путем оптимизации конкретно отчета уменьшить это время в 1000 раз. Но, если сам процесс генерации никого не напрягает, делать этого не надо, пока не попросят. При этом если на оптимизацию потратится неделя, то никого это точно не порадует. Время – деньги.

Когда оптимизировать надо до того, как написан первый байт



Обратный пример взят из реальной жизни. Некая команда, свежепрочитав статью о вреде преждевременной оптимизации, делала DataWarehouse. Воодушевленные новыми технологиями, они начали делать все это на объектной базе данных, хранящей, к тому же, данные в XML. Там было очень удобно манипулировать данными при помощи XPath. Я говорил, что не взлетит, но я для них был ни разу не авторитет и вообще из другого департамента. Как нетрудно догадаться, уже на мегабайте данных (а вообще объем данных под 1Гб) все встало намертво. Обидно было, что произошло это после 2-х месяцев работы. Тут как раз тот случай, когда надо думать заранее и, если сразу сделано плохо, то никакая оптимизация потом не поможет.

Не забивайте гвозди микроскопом, используйте молоток



Каждая технология имеет свою область применимости. Причем часто ее можно использовать и еще для чего-то, не факт, что это будет удобно и/или производительно. Например, мне доводилось видеть, как люди писали скрипты для администрирования UNIX-машин на PHP, размещали эти скрипты на http-сервере и запускали, запрашивая определенный URL из командной строки терминалки при помощи wget. Вот так:

/home/admin$> wget localhost:8089/scripts/admin/backupOracle.php

Это работало, но есть несколько «но»:

1. Другому админу ни в жисть с этим не разобраться, если первого админа переедет грузовик.
2. При частом использовании ест на порядки больше ресурсов.
3. PHP – не самый удобный язык для написания сценариев администрирования.

Другой пример. Flex-разработчик использовал для вызова прикладного Ява-кода, сидящего в JBoss из Rich, UI клиента, написанного на Flex-технологию JMS. Т.е. каждый вызов удаленного метода уже на сервере вел к передаче JMS-сообщения. Это работало, но в том конкретном случае куда проще было просто вызвать метод сервлета. Для интереса я сравнил производительность: получается, что JMS работал примерно в 40 раз медленнее, чем просто вызов сервлета (я уже молчу о том, как это было неудобно конфигурировать). Что неудивительно, JMS придумывали для другого, хотя технология очень гибкая, и ее можно использовать и таким извращенным способом.

Прежде чем использовать технологию, почитайте разные источники и подумайте головой, для чего технология была придумана, и, может быть, для вашего случая есть специальная технология, заточенная ровно под вас.

третья часть
Denis Tsyplakov @Semenych
карма
182,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (14)

  • +4
    4 статьи подряд? Автор, смилуйтесь! Выкладывайте по штуке раз в два дня, чтобы все успели прочесть и переварить.
    • +3
      По штуке не получится, надо пока мои девушки в деревне привести то, что есть в божеский вид. И до следующего лета :-)
      А так похоже что раньше следующих выходных свободное время мне не грозит.
      • 0
        Делайте и солите! А то у нас щас головы полопаются, и кто читать будет?!
  • 0
    давно я так не смеялся :) отличная статья
  • 0
    Make everything as simple as possible, but not simpler
  • +6
    Делайте все как можно проще.
    Эх… Проще всего — давать такие советы. По моим наблюдениям, программисты редко способны действительно понять и принять эту идею, если у них меньше 15-20 лет опыта. Нет, кивают и соглашаются с этим даже джуниоры, но для них это красивая теория, а не жизненная необходимость. И даже после того, как опытные разработчики нутром осознают важность и необходимость простоты, на практике простые решения разработать и реализовать оказывается крайне сложно. Причин тому множество:

    • * для начала довольно непросто дать определение «простоты», чтобы было проще оценивать туда ли мы идём и выбирать между разными подходами к решению задачи
      * приходится отказываться от «общепринятых» идей и решений: использовать JSON вместо XML, отказываться от ORM в пользу простого SQL, хранить данные в файлах сериализованные в тот же JSON вместо SQL-базы, отказываться от мантры «code reuse» и универсальных решений в пользу специализированных, даже если это приводит к значительному количеству copy&paste кода, избегать наследования в ООП кроме совсем тривиальных случаев, не особо увлекаться паттернами,… (многие из этих вещей Вы упомянули в статье, но до сих пор говорить о них вслух считается чуть ли не кощунством)
      * тяжело перестраивать мозги и удерживать себя от привычных, более универсальных но и более сложных решений
      * для того, чтобы суметь найти простое решение сложной задачи требуется повышенная ясность мышления — как ни парадоксально, но придумать сложное решение гораздо легче, чем простое (не даром давным-давно подмечено, что «ученики так и норовят всё переусложнить»)
      * очень сложно найти достойные изучения примеры чужого «простого» кода (я очень рекомендую исходники OS Plan9/Inferno)

      Самое смешное, что многие сильные разработчики гордятся своей способностью создавать очень сложные решения и разбираться в таких сложных системах. Им кажется, что именно высокая сложность систем, с которыми они работают, отличает их от более слабых разработчиков. И предложение писать код проще они воспринимают практически как оскорбление, мол, если нужно простое решение, то зачем для этого привлекать их, таких супер-профи… Это действительно смешно, т.к. решить задачу просто намного, намного сложнее, чем решить её сложно.
    • 0
      Это да проблема. Тут у нас в компании есть группа людей которые ведут борьбу за простоту кода. Но получается со скрипом.
      • 0
        Вот вопрос. Есть система из двух частей. Каждая на своём языке. И там и там есть код, делающий одну задачу, но так как языки разные, то он дублируется.

        «Простым» решением будет оставить как есть или сделать, например, одну библиотеку с обвязками для двух языков или кодогенератор, которые сгенерирует по файлу для каждой части?
        • 0
          Ну я бы сказал тут сильно зависит от деталей. Если эта штука работает и вероятность изменений в ней мала то лучше оставить.
          Если есть вероятность что придется менять — лучше конечно либу в том или ином виде.
  • 0
    Недавний пример — недавно коллега решая тестовую задачу от заказчика «сделать имплементацию интефейса для поиска максимального числа в массиве» умудрился использовать паттерн абстракная фабрика.


    Ух! Я б на это посмотрел! :)
  • 0
    Эффект грузовика — великолепно! Порой хочется спросить «что будет, когда ты уйдешь из проекта?», но воздерживаюсь от вопроса, боюсь что будет воспринят как намек. Теперь понятно как это назвать.
    • 0
      Этому выражению меня научил матерый американский програмер Валден.
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Ну это если мне не изменяет память американское выражение. Идея в том что если вы посмотрите на банку с червяками то они между собой довольно сильно спутаны. Если вы попытаетесь банку открыть, то червяки (проблемы) начнут расползаться так что не остановишь.

      Вообще выражение довольно образное — может быть стоило в статье выражаться как-то более определенно.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.