Иногда, открываешь какой-нибудь проект с историей и понимаешь, что история и у этого проекта была длинная… Да еще и авторы менялись, и видно, что у них был небольшой опыт.

В чем это выражается? — В том, что все части системы настолько переплетены, что невозможно оторвать один кусок и использовать где-то еще. Как результат, такой проект, конечно невозможно накрыть никакими модульными тестами кроме как приемочными со стороны группы QA. А значит, что со временем стоимость доработки будет возрастать, так как мы теряем уверенность в том, что наши изменения не поломают какие-то другие части.

Другим симптомом низкого качества проекта, может служить факт, что один класс выполняет одновременно множество ролей, то есть такой универсал-многостаночник. Это часто получается из-за того, что разработчику просто лень писать новый класс/интерфейс, потом его вводить в систему перестраивая связи. Намного проще просто «добавить метод по месту», «ведь если я добавлю сюда еще один метод ничего плохого не произойдет, так?» — думает он. Но после одного метода, появляется второй и третий. Если разработчик продвинутый, он запишет задачу «технический долг — надо выполнить рефакторинг и поделить всё на части», но часто он может даже не понимать, что проблема существует. Это обычно распространено в молодых командах, где нет специалиста с хорошим и правильным стажем.

А бывает ли такое, где есть специалист со стажем, но проект все-равно находится в запутанном состоянии? Да, и такое бывает. Как правило, на проектах, которые велись одним разработчиком, и его никто не наставлял на путь истинный. А потом, он вырастает, у него уж есть репутация «я тут давно работаю», «поработай тут, с мое, а потом говори» И он уже становится неспособным воспринимать правильный дизайн и правильное разделение компонент. Ему кажется, что это слишком сложно и запутанно.

Иногда, можно видеть ситуацию, когда профессионал пишет «по-быстрому», расширяя объекты несвойственным функционалом. Однако, профи точно знает, что прямо сейчас он решает задачу быстро, или делает макет, а завтра ему нужно будет обязательно выполнить рефакторинг. Но такой подход всё-таки оправдан только на быстрых и коротких проектах с очень маленькой длительностью. Технический долг имеет свою процентную ставку, и с каждой неделей она возрастает.

Как понять какой дизайн хороший, а какой плохой? Я рекомендую простой критерий:

Для каждого класса/объекта системы пишем ответы на вопросы:
  • Чем класс должен заниматься? Какова его зона ответственности?
  • Чем класс НЕ ДОЛЖЕН заниматься? В какие смежные области класс точно не должен лезть.

Ответы на эти вопросы сформируют систему связанных фактов, которую нужно проверить ответив на самый главный вопрос:

Почему ты считаешь, что (эта фича/действие/возможность) должна обеспечиваться этим классом?

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

Кроме этих вопросов, можно применить еще несколько индикаторов, позволяющих «поймать» неверное решение на ранних фазах:

Класс выполняет больше одной роли. В ответе на вопрос «Что класс должен делать?» хочется начать перечислять возможности. И вы не можете сконцентрироваться на какой-то одной самой важной. Это означает, что надо подумать о разделении на несколько классов.

Не удается выразить одним кратким предложением, чем занимается класс. Это значит, что его зона ответственности размыта, и у вас нет понимания зачем этот класс нужен. Индикатор показывает, что в будущем это может стать «кучей мусора».

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

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

Вопрос: Коллеги, а какие вы применяете способы проверки дизайна на устойчивость?

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


  1. PHmaster
    30.06.2015 03:02
    +6

    Вы описали один антипаттерн объектно-ориентированного программирования под названием «Божественный объект». И упомянули еще один: «Равиоли-код». Рекомендую ознакомиться с более обширным списком (далеко не полным). Под таким многообещающим названием прочитать статью с описанием двух общеизвестных антипаттернов… Я испытал разочарование =/


    1. sbase Автор
      30.06.2015 10:59

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

      Для познания возможностей языка программирования нужно минимум 3 года, для познания паттернов и особенностей их применения еще 2 года. Таким образом, я хороший специалист с навыками проектирования должен иметь стаж не менее 5 лет. И то, если его кто-то наставлял на путь истинный.

      Коллега, какие более быстрые способы обучения навыкам хорошего проектирования с нуля Вы знаете?


      1. PHmaster
        30.06.2015 11:59
        +1

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

        Всего лишь двух из огромного списка. Без упоминания даже, что существуют другие, и их много. Это как если, выпуская человека впервые одного в джунгли, снабдить его единственным советом: «Остерегайся мухи цеце — и ты останешься жив и здоров».

        Коллега, какие более быстрые способы обучения навыкам хорошего проектирования с нуля Вы знаете?

        Самый быстрый способ: ознакомиться со списком паттернов проектирования и их кратким описанием, ознакомиться со списком и кратким описанием антипаттернов. И тогда вся Ваша статья (и без того не очень длинная) сведется вообще к одному предложению: «Не создавайте божественные объекты и не используйте равиоли-код — и всё, ваш дизайн будет хорошим». Как-то… жидковато для статьи с фундаментальным названием «Хороший дизайн, плохой дизайн…», Вам не кажется?
        Скрытый текст
        Тем более для человека, который заявляет, что он:
        Более 15 лет в индустрии разработки программного обеспечения. Познал ДАО Программирования, теперь наставляю на Путь Истинный. В областях:

        * архитектура программного обеспечения,
        * постановка процесса разработки
        * инженерия программного обеспечения.
        * применение ТОС для SW проектов


        1. sbase Автор
          30.06.2015 12:53

          Отвечая на Ваш вопрос, касательно фундаментальности статьи:
          Возможно, мне не удалось правильно донести свою мысль и Ваши ожидания от статьи разошлись с реальностью. Однако у всяких паттернов есть ключевые условия их возникновения как и у антипаттернов. Именно их и хотелось рассмотреть и начать какую-то конструктивную дискуссию именно о простых базовых принципах, применимых в качестве отправной точки при аудите дизайна (вместо «у тебя здесь божественный объект — исправь»). Однако, к сожалению, не увидел от Вас, коллега, ни одного конструктивного комментария.

          Что касается способа «RTFM паттерны»:

          Коллега, Вы серьезно уверены что молодой специалист, почти без стажа работы, сможет удержать в голове все паттерны и антипаттерны?
          Моя практика показывает, что беглый просмотр паттернов/антипаттернов без продолжительных навыков их применения не дает хорошего эффекта.

          Поэтому, повторю вопрос: какой способ Вы считаете приемлемым для быстрого обучения навыкам хорошего дизайна молодых специалистов, кроме способа «RTFM паттерны»?

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


          1. PHmaster
            30.06.2015 15:07

            Возможно, мне не удалось правильно донести свою мысль и Ваши ожидания от статьи разошлись с реальностью.

            В точку. Назови Вы статью «Антипаттерн 'Божественный объект'» — вообще никаких вопросов у меня бы не было. А так получается, что он единственный (ну вкупе еще с упомянутым «Равиоли-кодом») является корнем всех вообще зол в проектировании, и избавившись от этого антипаттерна в своем проекте — получишь идеальный дизайн.

            … начать какую-то конструктивную дискуссию именно о простых базовых принципах, применимых в качестве отправной точки при аудите дизайна...

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

            Коллега, Вы серьезно уверены что молодой специалист, почти без стажа работы, сможет удержать в голове все паттерны и антипаттерны?

            Коллега, а Вы серьезно уверены, что такому молодому специалисту без стажа работы и элементарных знаний хватит двух антипаттернов на все случаи жизни? Вы серьезно уверены, что такого «нулёвого» молодого специалиста можно сразу же смело допускать к проектированию более-менее серьезных приложений? Или все же стоит отправить его хотя бы немного поучиться, если он настолько молодой и настолько неопытный?

            Ну и давайте все же будем честными: мы же на Хабре, а не на страничке «программирование для чайников». Здесь от статьи ожидаешь немного большего, чем перечисления парочки всем известных прописных истин. Это мое личное мнение, конечно же, я могу и ошибаться.

            Однако, к сожалению, не увидел от Вас, коллега, ни одного конструктивного комментария.

            Правда? Ну то есть я просто написал: «КГ/АМ», и не потрудился разъяснить, чем вызвана моя реакция, и из моих слов совсем не понятно, что бы могло, по моему мнению, сделать статью более содержательной? Тогда извините, что произвел такое впечатление.


  1. velvetcat
    30.06.2015 08:59

    В ответе на вопрос «Что класс должен делать?»

    Самый лучший вопрос — «о чем класс знает?»


    1. sbase Автор
      30.06.2015 11:04

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


      1. velvetcat
        13.07.2015 19:20

        Да, действительно, я с Вами согласен. «Что должен делать» — основной вопрос. «Что знает» — проверочный.

        Кстати, это в точности то, как работает TDD: назначили действие — проверили, не слишком ли много классу надо знать для этого.

        Спасибо за наводку!


  1. 0x13
    02.07.2015 10:12

    Если вы нашли логическое и непротиворечивое доказательство, которое не конфликтует с ранее записанными фактами, значит ваш проект имеет хороший дизайн.

    Если Вы нашли такое логическое и непротиворечивое доказательство, то у Вашего проекта тепличные условия у Вас есть время их искать. :)

    Мое убеждение таково, что если человек не научился думать и не имеет должного опыта, то никакие гайдлайны такого рода его не спасут. Простой пример — пишет неопытный программист GUI приложение со сложной логикой, например, тот же редактор Word. Нафигачил он всю логику в класс MainWindow, прочитал этот пост и понял, что у него проблема, класс перегружен функциональностью. И что дальше ему делать, как понять, как этот класс делить? Ну ок, прочитал он книгу и вынес всю бизнес-логику из класса, осталась только работа с GUI, но и она очень сложная, код запутанный, как его делить дальше? Понятно, что пост ни в каком роде не претендует на полноту, но, на мой взгляд, новичкам лучше давать Если вы нашли логическое и непротиворечивое доказательство, которое не конфликтует с ранее записанными фактами, значит ваш проект имеет хороший дизайн. и больше конкретики.


    1. sbase Автор
      02.07.2015 10:40

      Это хороший комментарий Тимофей, а есть ли у Вас какие нибудь свои рецепты ускорения развития разработчика? Как научить его думать правильно?

      как понять, как этот класс делить?

      Мой рецепт такой, что если есть понимание что делить надо, то наиболее оптимально это разделение по ролям. И даже если разработчик будет вначале плодить слишком много классов это можно быстро вылечить, за счёт тех же обоснований «почему ты считаешь что это должно быть отдельным классом?»

      Тимофей, а какой Ваш рецепт в этом случае?


      1. 0x13
        02.07.2015 11:16

        Как научить его думать правильно?

        Учить постоянно задавать себе вопросы «почему», формировать причино-следственные связи и избегать карго-культа всеми возможными способами. Ну и все это бессмысленно без опыта — много делать руками, ошибаться, исправлять ошибки (тут как раз и важна помощь грамотных старших товарищей), снова делать, снова ошибаться и т.п. Я другого пути не знаю. :) Рецепты в этом смысле тоже полезны, но скорее как справочный материал.