Несколько вещей гарантированно будут увеличиваться со временем: расстояния между звёздами, энтропия вселенной и бизнес-требования к ПО. Многие статьи пишут «Не усложняйте!», но не пишут почему или как это сделать. Вот вам 10 ясных примеров.

1. Инженерам виднее

Мы, инженеры, считаем себя умнейшими людьми. Ну, поскольку мы создаём разные штуки. И эта ошибка часто приводит к оверинжинирингу. Если вы спланировали и построили 100 модулей — Бизнес всегда попросит у вас 101-ый, о котором вы никогда не задумывались. Если вы соберётесь с силами и решите 1000 проблем — они придут к вам и выложат на стол 10 000 новых. Вы считаете, что у вас всё под контролем, а на самом деле вы даже не представляете, в каком направлении вас завтра поведёт дорога.

image

За мои 15 лет работы программистом я ещё ни разу не видел, чтобы Бизнес выдал законченные и стабильные раз и навсегда требования к ПО. Они всегда меняются, расширяются. И это природа бизнеса, а не ошибки людей, управляющих им.

Мораль: Казино (бизнес) всегда побеждает.

2. Повторное использование бизнес-функционала

Когда Бизнес подкидывает нам всё больше и больше требований (как и ожидается), мы иногда говорим себе: «Ок, давайте попробуем сгруппировать и обобщить всё, что только можно!».

image

Вот почему большинство MVC-систем заканчиваются Большой Моделью или Жирным Контроллером. Но, как мы уже выяснили, бизнес-требования никогда не прекратят добавляться, а значит это путь в никуда. На самом деле нам нужно реагировать на это вот так:

image

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

Мораль: Предпочитайте изолированные действия, избегайте комбинирования.

Совет: Возьмите некоторую видимую пользователю часть вашей программы (форму\страницу\команду). Сколько переключений контекста понадобиться программисту, чтобы понять весь код, связанный с ней?

3. Обобщим вообще всё

(Несколько перекликается с предыдущим пунктом, но иногда случается и независимо от него)
  • Нужно подсоединиться к базе данных? Давайте напишем Обобщённый Адаптер.
  • Сделать запрос? Обобщённый Запрос.
  • Передать ему параметр? Обобщённый Параметр.
  • Собрать несколько параметров во что-то? Обобщённый Builder.
  • Отразить полученный результат во что-то? Обобщённый Data Mapper.
  • Обработать запрос пользователя? Обобщённый Запрос.
  • Что-то выполнить? Обобщённый Исполнитель.
  • и т.д.


Иногда инженеров заносит. Вместо решения бизнес-проблем они тратят время для выбора правильного родительского класса. А ответ прост.

image

Архитектура ПО всегда играет в догонялки с требованиями бизнеса. Так что даже если вы с помощью какой-то магии найдёте идеальную абстракцию сегодня, в комплекте с ней сразу будет идти срок её годности — см. пункт №1 выше — бизнес всегда побеждает. Так что лучшая характеристика качества сборки вашей архитектуры — как быстро она может быть разобрана. Есть отличная статья о том, как писать код, который будет легко удалить, а не легко изменить.
Мораль: Дублирование кода лучше, чем неверная абстракция.

Более того, дублирование кода иногда помогает найти ту самую правильную абстракцию. Потому, что когда вы видите несколько частей системы, использующий одинаковый код одинаковым образом — вы можете понять, что их объединяет. Качество Абстракции определяется качеством её слабейшего звена. Дублирование кода позволяет взглянуть на разные ситуации под разными углами и увидеть границы Абстракции чётче.

4. Написание обёрток для всех внешних библиотек

Существует практика написания обёрток (врапперов) для каждой используемой внешней библиотеки (в основном из-за следования стилю основного продукта, иногда из-за причин, описанных в предыдущих двух пунктах). Очень популярный подход в энтерпрайз-программировании. Программисты на динамических языках вроде Node/Ruby/Python просто добавляют библиотеку и начинают её использовать. Но Энтерпрайз Разработчик на это пойти не может — ему необходимо создать обёртку. А потом ещё обёртку над обёрткой. Возможно, это имело какой-то смысл в 2000-ых, когда большинство библиотек представляли собой мешанину, да и вообще открытого кода было не так много.

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

Мораль: обёртки должны быть исключениями, а не нормой.

5. Слепое применение метрик качества кода

Бездумное следования концепциям качества кода (вроде того, что все переменные должны быть объявлены как «private final», каждый класс должен иметь интерфейс) не сделает ваш код АВТОМАТИЧЕСКИ хорошим. Посмотрите, если ещё не видели, на энтерпрайз-версию FizzBuzz или Hello World. Прорва кода. На микро-уровне каждый класс следует принципам SOLID и использует отличные паттерны. Если вы натравите на этот код какой-нибудь инструмент анализа качества кода — он скажет, что это прекрасный продукт, прямо загляденье. Но если вы сделаете шаг назад — то сразу увидите каким кошмаром является эта программа, всего лишь печатающая «Fizz Buzz».

Мораль: всегда делайте шаг назад и смотрите на общую картину.

Аналогично, автоматические средства хорошо определяют тестовое покрытие кода, но совершенно ничего не говорят о том, тестируете ли вы то, что нужно, или нет. Они могут измерить производительность в некотором тесте, но ничего не скажут насколько хорошо ваша программа обрабатывает данные в другом случае. Все они смотрят на микро-уровень: что делает этот класс\метод\строка. И только Человек смотрит на общую картину.

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

5.1. Слои сандвича

Давайте возьмём некоторый тесно связанный функционал и разделим его на 10-20 слоёв, где каждый слой не имеет никакого смысла без остальных. Ну, потому что мы хотим реализовать концепцию «Тестируемого кода», или «Принцип единой ответственности», или назовите это ещё как-нибудь модно. В прошлом это делалось через наследование. Класс А наследуется от Б, который наследуется от С и т.д.

image

Сегодня люди делают всё то же самое, кроме того, что каждый класс теперь представляется парой интерфейс/класс и инжектируется на следующий слой, потому что у нас же SOLID.

image

Мораль: концепции требуют вдумчивого применения. Их нельзя применять просто везде и всегда, как инструменты.

6. Синдром Новинки

Изучили дженерики. Теперь у нас простой «HelloWorldPrinter» станет «HelloWorldPrinter<String,Writer>».
Не нужно использовать дженерики, когда реально необходимая форма будет всегда инстанциироваться одними и теми же типами данных. Параметров достаточно в большинстве случаев.

Изучили паттерн Стратегия. Теперь все операторы «if» будут стратегией.
Почему?

Научились писать DSL. Теперь у нас DSL будет везде и для всего.
Ну я даже не знаю…

Обнаружили моки. Теперь у нас будет замокано всё вдоль и поперёк.
Да ну как же…

Метапрограммирование — шикарная вещь, давайте используем здесь и здесь!
Объясни зачем…

Методы расширения\концепты\что-то ещё — хорошая штука, давайте будем использовать кругом!
А давайте не будем!

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

7. «X–сть»

  • Конфигурабельность
  • Безопасность
  • Масштабируемость
  • Поддерживаемость
  • Расширяемость
  • ...


Расплывчато. Неизменно. Трудно поспорить.
Пример 1: Давайте создадим CMS, чтобы клиент смог сам добавлять поля вот в эту форму.
Результат: Клиенты никогда не будут ею пользоваться. Когда понадобятся — они найдут разработчика и озадачат его. Возможно вместо полноценной CMS стоило набросать короткую инструкцию о том, как быстренько добавить поле.

Пример 2: Давайте спроектируем большой слой для работы с базами данных, для упрощения «Конфигурабельности». Мы должны получить возможность сменить базу данных правкой одного конфиг-файла.
Результат: За 10 лет работы я видел лишь один проект, где понадобилось менять одну базу данных на другую по объективным причинам. И, когда до этого дошло дело, то «правкой одного конфиг-файла» дело совсем не обошлось. Была масса сопутствующей работы. Несовместимость, пробелы в функционале. А ещё однажды клиент попросил на перевести ПОЛОВИНУ наших моделей данных в новую NoSQL базу данных. У нас был «магический файл» с подключением базы данных, но во-первых, только реляционной, а во-вторых для всех данных, а не для половины. Возможно все эти пляски с конфигурабельностью имеют смысл, когда речь идёт о чём-то вроде Оракловской базы данных, которая стоит как найм 20-ти программистов — там и правда удобно иметь возможность переключиться на что-то другое при необходимости. Но для современных баз данных, всё что нам необходимо — это простой набор вертикальных DAO-классов вместо широкого горизонтального слоя ORM. Не существует единой модели, удачно сочетающей в себе SQL и NoSQL, так что, возможно, нам действительно стоит их разделять, используя в каждом случае то одно, то другое, вместо того, чтобы пытаться совместить несовместимое и городить ужасные неверные абстракции.

Пример 3: Мы построили систему OAuth-авторизации для энтерпрайз-клиентов. Для администраторов этой системы нас попросили добавить ещё один уровень — авторизацию администраторов через Google OAuth. «Потому, что должно быть безопасно». Если кто-то взломает нашу OAuth-авторизацию, нужно чтобы хотя бы учётки администраторов остались недоступны. Google OAuth — надёжная штука, так что возражать тут вроде бы особо нечего.
Результат: Тому, кто захочет взломать данную систему совсем не нужно пробиваться через OAuth-слой. Можно найти уязвимость в чём-нибудь попроще (такие всегда есть). В итоге все затраты на поддержку двух уровней OAuth (а они проходили насквозь через всю систему) дали примерно никаких результатов. Лучше было потратить это время на устранение обычных уязвимостей.

image

Мораль: Не принимайте все эти характеристики с окончанием на "-сть" как неизменную данность. Они имеют свою цену — так что чётко определяйте Сценарий\Историю\Использование.

8. Велосипедостроение

Это всегда круто в начале. Но через несколько лет это уже будет Груз Наследия.
Пара примеров:
  • Свои библиотеки (HTTP, мини-ORM, кеширование, конфигурация)
  • Свои фреймворки (CMS, обработка событий, многопоточность, фоновые задачи)
  • Свои инструменты (система сборки, система деплоя)


Что тут плохого:
  • Тривиальные, казалось бы, задачи на самом деле требуют приличных знаний и глубокого погружения в предметную область. Какой-нибудь «запускатель процессов» требует понимания менеджмента процессов в ОС, работы демонов, системы ввода\вывода и ещё кучи всего. CMS — это не просто что-то, подставляющие данные в шаблоны — там есть зависимости, проверки, визарды, обобщения и т.д. Самая простая на вид библиотека может иметь нетривиальную функциональность.
  • Всё это нужно ещё и поддерживать, обновлять.
  • Если вы выложите код в открытый доступ — всем будет плевать. Ну, может, кроме тех, кто работал над этим кодом раньше.
  • Люди, которые разбираются в этом коде — рано или поздно уйдут. А кроме них в этой реализации не разбирается никто в мире.
  • Внедрение в проект уже существующих библиотек и фреймворков, заточка их под ваши нужды требует время прямо сейчас. Но изобретение собственных велосипедов требует куда больше времени в долгосрочной перспективе.


Мораль: Переиспользуйте. Заимствуйте хорошее. Пересматривайте свои решения.
Если вы всё-же решили строить свой велосипед — по крайней мере делайте его по принципу «внутреннего опенсорса» в своей компании. Объясните людям, зачем это нужно. Покажите первый набросок. Предложите им использовать или улучшать это. И подумайте 10 раз, стоит ли продолжать строить этот велосипед, если даже ваши коллеги не выскажут своего одобрения.

9. Развивайте свой код

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

Вот как команды работают над задачами, а вот как они должны это делать, Каждый День:

image

Мораль: рефакторинг — это часть любой разработки. Никакой код не остаётся неизменным.

10. Неверные оценки сроков

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

Мораль: неверная оценка сроков наносит вред качеству вашего проекта ещё до того, как написана первая строка кода.
Поделиться с друзьями
-->

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


  1. ServPonomarev
    25.07.2016 12:10
    +12

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

    Статья о том, как растут из миддлов в сеньоры.


    1. AndreyRubankov
      25.07.2016 22:57
      -1

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


  1. toshihir
    25.07.2016 13:23

    Отличная статья, спасибо! Со многим сталкивался сам, многое видел у других.


  1. areht
    25.07.2016 13:31

    > 2. Reusable Business Functionality
    > 2. Повторное использование кода

    надмозг подсказывает, что «переиспользование бизнесовой функциональности». Но точно не «кода»


    1. fetis26
      25.07.2016 16:14

      Уж лучше "Повторное использование бизнес-функционала"


      1. tangro
        25.07.2016 16:35

        Да, лучше, изменю. А вообще беда с этой статьей в том, что она на 30% была изменена автором уже после того, как я её перевёл.


        1. fetis26
          25.07.2016 17:14

          Но вообще статья отличная


        1. areht
          25.07.2016 17:29
          -5

          Странное оправдание. Не надо переводить на 30% плохие статьи? Переводчик — не гуглтранслейт, должен отвечать за вышедшее из под него.

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


          1. tangro
            25.07.2016 20:44
            +5

            Я не сказал, что она на 30% плохая. Я сказал, что взял статью, перевёл (это заняло несколько часов), потом ещё раз посмотрел на оригинал — и он стал уже значительно изменён, на глаз где-то на треть. Но поскольку первоначальный вариант тоже был не плох — я решил публиковать его. Отслеживать во времени все текущие и будущие правки и вносить изменения в перевод — это уже какая-то сверхзадача, непонятно зачем это делать.


  1. AxisPod
    25.07.2016 13:54
    +7

    Это именно то, что я называю: «Архитектура ради архитектуры».


  1. m0nstermind
    25.07.2016 14:33
    +7

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

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


    1. nicholas_k
      25.07.2016 16:36

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


      1. m0nstermind
        25.07.2016 18:13
        +5

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

        Можно лишь предположить, что, как и со стартапами, подобных велосипедов не доходит до опенсорса приблизительно 99,9 процентов. Но зато выстрелившие 0,1% дают достаточный профит для того, чтобы продолжать их строить. Спринг, кассандра, хадуп, бутстрап и тд и тп — были созданы теми самыми велосипедистами, решавшими конкретные задачи в конкретной конторе.
        К тому же, нельзя считать, что если велосипед не дошел до опенсорса — то деньги зря потрачены. Люди решили конкретные проблемы в конкретных проектах, не спасая попутно весь мир. Что в общем тоже хороший результат.


        1. nicholas_k
          25.07.2016 18:59
          +2

          >Но зато выстрелившие 0,1% дают достаточный профит для того, чтобы продолжать их строить.

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

          Это очень очень очень высокий уровень риска.


          1. VolCh
            26.07.2016 06:11
            +2

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


            1. nicholas_k
              26.07.2016 08:06

              Глупо было бы обобщать и говорить, что все велосипеды хороши или все велосипеды плохи.

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

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

              В общем, на мой взгляд, надо быть Гуглом или Яндексом, чтоб браться за серьезные велосипеды.


              1. VolCh
                26.07.2016 09:45

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


                1. nicholas_k
                  26.07.2016 11:07

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


        1. fetis26
          25.07.2016 19:34
          +2

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


          1. m0nstermind
            26.07.2016 11:17

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


            1. csbubbles
              27.07.2016 09:43
              +1

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

              Однако, практика изобретения велосипедов – сплошь, и рядом и во многих случаях она не обоснована «экономическими параметрами». Наоборот, инженерам часто все равно на конечный результат (с точки зрения бизнеса), они просто хотят сами спроектировать какие-то технические вещи, потому что им просто интересно это делать, и их обоснования типа «у нас будет лучше» или «мы сделаем это быстрее/дешевле» не основываются на реалиях. Наоборот, у истоков таких начинаний часто оказываются люди, которые плохо разбираются в предметной теме, не знают как уже созданные «велосипеды» работают (и не хотят знать!), не могут оценить реальные требования, которые могут возникнуть в перспективе, и т. д.

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


    1. ncix
      25.07.2016 17:41
      +4

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


      1. gribnoysup
        26.07.2016 11:32

        Вот! Отличная аналогия. Очень часто использование готового решения в проекте именно так и выглядит


  1. franzose
    25.07.2016 15:47
    +1

    Хорошая статья, только недавно прочитал её на Медиуме)


    1. tangro
      25.07.2016 16:37
      +2

      А как Вы его вообще читаете так, чтобы находить что-то интересное? Есть какие-то Best Practices?


      1. franzose
        26.07.2016 00:59

        Честно говоря, я сам там только пару дней назад зарегистрировался и почти случайно нашел эту статью по тегу php.


  1. boom
    25.07.2016 16:44
    +2

    да, статья хорошая, но есть пару «но»
    как бы заказчик не менял ТЗ, и как бы не пришлось менять бизнесс-логику — думать нужно всегда и пытаться писать идеальный код, можно писать тяп-ляп и это может работать, но написанный хорошо код будет легче саппортиться и он легче будет принимать капризы заказчика.

    Жать на практике это доказать практически нереально. У меня часто возникают споры с другими синьерами -но нет времени проверить ту, либо другую архитектуру — заказчик никогда не заплатит за это, нужно просто что-то принять и работать дальше. Лишь спустя пол-года (зависит от частоты изменений и проекта) будет видно — правильное ли было принято решение. Так вот хороший программист отличается от посредственного тем, что он правильных решений принимает больше — его проект не скатывается в спагети через пол года, а остается более-менее читабельным, понятным.

    Трудно понять что ты ошибся (или не ошибся) в момент анализа проблемы и реализации решения — на это нужен опыт (+, возможно, везение :))


    1. Kane
      25.07.2016 17:06

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


      1. fetis26
        25.07.2016 17:33

        Ну не совсем, надо понять что принятое решение было неправильным. А это совсем нетривиальная задача, особенно если учесть, что даже спагетти-код может работать и приносить прибыль.


        1. boom
          25.07.2016 18:06
          +1

          Согласен, например у меня впринципе не возникает такких проблем, какие возникают у соседнего отдела, т.к. я принял другое решение на каком-то раннем этапе, хотя задачи похожие. И теперь та команда борется с ветрянными мельницами… а я могу лишь говорить «а я ведь говорил!» :) но формально тогда у меня небыло доказательств.


          1. fetis26
            25.07.2016 19:31

            Мне кажется, что такое решение не всегда может быть взвешено принято на уровне команды. Просто слишком много неизвестных, а попробовать все нельзя. Надо общаться, обсуждать, посещать конференции, митапы. Тогда будет рождаться понимание того, что называют "Best practices" и согласно им уже действовать.


            1. VolCh
              26.07.2016 06:13

              Нет серебряной пули. Best practices могут и усложнить жизнь конкретному проекту.


              1. fetis26
                26.07.2016 11:47

                А я и не говорю, что это Серебряная пуля. Но очень часто решаемые задачи бывают схожи. Например, все магазины имеют авторизацию, добавление в корзину, оформление заказа. Изобретать тут какой-то свой огород и набивает те же шишки не имеет смысла никакого.


                1. VolCh
                  26.07.2016 12:43

                  Даже по авторизации нет стандартного решения, которое бы всех устраивало. Изобретают своё обычно не потому, что не хотят использовать готовое, а потому что готовое плохо вписывается в существующую и(или) планируемую архитектуру и(или) инфраструктуру.


      1. ncix
        25.07.2016 17:43
        +3

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


      1. heleo
        25.07.2016 20:44

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

        Отсюда растут несколько выводов:
        1. Понять неправильность выбранного решения можно в различные моменты, но желательно сделать это вовремя и следовать только ему иначе попадаешь в ловушку метаний «или-или».
        2. На ранних стадиях это влечёт за собой не полную «погруженность» в проблему, а следовательно не все нюансы такого подхода будут известны для будущих решений.
        3. На поздних стадиях может не хватить времени на изменение уже сделанного и пойдёт так как есть (если оно работает), главное не вляпаться в сопровождение или расширение функционала ( =( sad but true но это лучший вариант учения на своих ошибках, хуже если ошибки не твои...).

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


  1. Kane
    25.07.2016 17:01

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


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


    При этом не нужно стремиться оценить задачу с точностью до минуты. Я предпочитаю оценивать задачи с гранулярностью в четыре часа.


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


    1. ncix
      25.07.2016 17:47

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


      1. Kane
        25.07.2016 17:49

        Нет, такая методика приводит к тому, что посмотрев на задачу я могу довольно точно оценить, сколько времени на неё нужно, даже не вникая в детали.


        1. ncix
          25.07.2016 17:53

          А Вы разработчик, или руководите группой?


          1. Kane
            25.07.2016 17:58

            Разработчик


    1. ncix
      25.07.2016 17:50

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


      1. Kane
        25.07.2016 18:02

        Думаю, стоит отметить, что я говорю о не долгосрочной перспективе — планирование на несколько недель.


        1. OsipovRoman
          25.07.2016 18:12
          +1

          Для большинства задач все равно не удастся прописать в ТЗ все мелочи и подводные камни, которые могут возникнуть.


          1. Kane
            25.07.2016 18:15

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


            1. OsipovRoman
              25.07.2016 18:32
              +3

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


              1. Kane
                25.07.2016 18:36

                Кроме того, сознательно занижение точности оценки (например, не бывает задач которые можно сделать быстрее чем за день), в итоге позволяет скомпенсировать переоценки/недооценки.


        1. ncix
          26.07.2016 00:05
          +2

          А можно пример задачи и вашу оценку срока?


  1. ncix
    25.07.2016 17:48
    +4

    Идеальный код — не тот, к которому нечего добавить, а тот из которого уже нечего выкинуть.


    1. tdrive
      25.07.2016 20:45
      -1

      Бредовый тезис.
      Например код который не обрабатывает исключительные ситуации идеален? Или что ты выкинешь из когда который сам по себе не эффективно решает задачу, требует больше ресурсов чем нужно? Что бы ты выкинул из сортировки пузырьком?


      1. tangro
        25.07.2016 20:46
        -1

        Например код который не обрабатывает исключительные ситуации идеален?

        Да. Посмотрите, например, лекции Гугла. Там так прямо и говорят — если падает, то пусть уже падает.

        Или что ты выкинешь из когда который сам по себе не эффективно решает задачу

        Неэффективность можно выбросить


        1. orcy
          25.07.2016 23:05
          +2

          Да. Посмотрите, например, лекции Гугла. Там так прямо и говорят — если падает, то пусть уже падает.

          Посмотрите код гугла (Android, Chrome) сколько там обработок ошибок и исключений.


        1. ankh1989
          26.07.2016 09:36

          Лекции Гугла это как мнение жителей Австрии этому поводу: у них не может быть общего мнения. На практике лекции Гугла представляют из себя мнение пары опытных программёров, но у них есть пара не менее опытных знакомых которые имеют противоположное мнение.


        1. tdrive
          26.07.2016 10:13
          +1

          >Неэффективность можно выбросить
          Это уже эзотерика какаято


        1. tdrive
          26.07.2016 10:27

          >Да. Посмотрите, например, лекции Гугла. Там так прямо и говорят — если падает, то пусть уже падает.
          Подозреваю что вы не понимаете о том что там говорят.
          Сами то будете пользоваться например веб сервером который падает от любого некорректного запроса?


          1. tangro
            26.07.2016 11:35
            +2

            Некорректный запрос — это не исключение. Это стандартный сценарий, который должен стандартно обрабатываться. Исключение — это когда new не смог память выделить — тут нечего особо уже делать и да, веб-сервер должен упасть. Дальше можно анализировать креш-дамп.


            1. tdrive
              26.07.2016 21:19

              >когда new не смог память выделить
              Точно такой же стандартный сценарий как и некорректный запрос. В случае если это некий сервер и ему не хватает памяти для очередного подключения можно просто вернуть ошибку подключения с соответствующей информацией, и не надо ни какие дампы анализировать, сразу всем будет понятно что произошло, а сервер спокойно продолжит работу.


              1. tangro
                27.07.2016 15:13
                +1

                Совершенно не такой же. Запрос приходит извне, от юзера — и понятное дело, что он может быть какой-угодно. Обработка какого-угодно запроса — штатная ситуация. С другой стороны ситуация, когда new не может выделить память — это ошибка разработчиков или админов. И им нужно на неё отреагировать — пофиксить код, апгрейднуть сервер или сделать нормальное горизонтальное масштабирование. Эту ошибку нельзя просто проглотить и замолчать. Именно что должен быть креш, дамп, анализ и действие по исправлению.


                1. tdrive
                  27.07.2016 20:47
                  +1

                  >Эту ошибку нельзя просто проглотить и замолчать
                  А еще есть такая штука называется электронная почта, туда можно слать письма с возникшими эксепшенами.

                  Тут 2 варианта
                  1) забиваешь на эксепшены и тебе в 5 утра звонят с криками у нас нихрена не работает, все упало, сделай что нибудь мы кучу бабок просираем.
                  2) пилишь обработку эксепшенов, по ночам сервер ловит хайлоад и разгребает столько сколько позволяют ресурсы, пока ты смотришь эротические сны, а утром ты приходишь на работу, делаешь себе кофе, читаешь отчеты об ошибках, смотришь графики и со всем этим идешь к босу просить денег на новое железо.


                  1. VolCh
                    28.07.2016 08:15

                    А еще есть такая штука как логи и сервисы их мониторинга. А ещё есть сервисы контроля процессов.


                    1. tdrive
                      28.07.2016 17:44

                      спасибо Кэп


      1. ncix
        26.07.2016 00:03
        +2

        >>Например код который не обрабатывает исключительные ситуации идеален?
        it depends.

        >>Что бы ты выкинул из сортировки пузырьком?
        Ничего. Он идеален.

        >>Или что ты выкинешь из когда который сам по себе не эффективно решает задачу, требует больше ресурсов чем нужно
        Всё бы выкинул и переписал заново. Если мы говорим об идеальной ситуации, разумеется.


      1. VolCh
        26.07.2016 08:00
        +1

        1) если обработку исключительных ситуаций можно («may», а не «can») выкинуть, то код не идеален

        2) код сам по себе не решает задачу, её решает алгоритм в нём реализованный, код может быть идеальным, а алгоритм — нет.


        1. tdrive
          26.07.2016 10:18

          >2) код сам по себе не решает задачу, её решает алгоритм в нём реализованный, код может быть идеальным, а алгоритм — нет.
          Так код это и есть алгоритм записанный на определенном языке, что там может быть лишнего? неиспользуемая переменная? Чистить такие вещи задачи линтера, им только ленивый не пользуется. Получается мы живем в мире идеального кода)


          1. VolCh
            26.07.2016 12:50

            Там могут быть ненужные по ТЗ обработки исключительных ситуаций, например :)

            А линтерам, которые сами чистят код, я бы точно не доверился.


            1. tdrive
              26.07.2016 20:49

              >Там могут быть ненужные по ТЗ обработки исключительных ситуаций, например :)
              Если в ТЗ чего то нету, а ты понимаешь что это нужно, надо написать манагерам и уточнить. Ни кто в серьезном проекте не забивает на отказоустойчивость софта.

              >А линтерам, которые сами чистят код, я бы точно не доверился.
              не тупи, они показывают ошибки и ты сам решаешь что с ними делать.


              1. VolCh
                27.07.2016 17:12

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

                Не знаю, не пользуюсь линтерами, вполне хватает средств анализа кода в IDE. Если это примерно то же самое, то это просто автоматизированное детектирование явной грязи в коде.


                1. tdrive
                  27.07.2016 20:52

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

                  >Если это примерно то же самое, то это просто автоматизированное детектирование явной грязи в коде.
                  Так и есть, а все остальное как ты сам сказал это алгоритм и к оценки идеальности кода не имеет отношения.


                  1. VolCh
                    28.07.2016 08:23

                    В лог и так запишется необработанное исключение. А процесс перезапустится, если указать что-то типа restart always

                    Не не всё остальное. Например именование переменных, декомпозиция на функции/методы, единственная ответственность — пока нет сильного ИИ, никакой линтер не скажет, что переменную лучше назвать amount, а не sum или count.


                    1. tdrive
                      28.07.2016 17:54

                      >В лог и так запишется необработанное исключение.
                      Кто его запишет если все упало? Да еще и с бектрейсом без которого эксепшен практически бесполезен.

                      >А процесс перезапустится, если указать что-то типа restart always
                      Я бы посмотрел на тебя если бы у тебя базы данных падали и запускались по restart always


                    1. tdrive
                      28.07.2016 17:55

                      Есть вообще хоть один плюс от того что процесс падает?


                    1. tdrive
                      28.07.2016 17:58

                      >Не не всё остальное. Например именование переменных, декомпозиция на функции/методы, единственная ответственность — пока нет сильного ИИ, никакой линтер не скажет, что переменную лучше назвать amount, а не sum или count.
                      Ну и что в этих кейсах ты выкидываешь?


                    1. tdrive
                      28.07.2016 18:47

                      Или вот смотри отличный пример придумал, играешь ты в КС или танки или еще во что нибудь, напряженная борьба, сидишь потеешь и тут сервер падает, всех нафиг выкидывает из игры, ок логинишься играешь дальше и через 15 мин сервер опять падает, и новость на сайте: «Вот так и так мы превысили критический онлайн так что сервера будут падать, но вы не переживайте у нас включен restart always так что через 2-3 мин после падения они снова будут подниматься, наш тех. дир. VolCh убедил нас что это самая правильная логика работы серверов, через недельку мы купим новое железо а пока терпите. „

                      Надеюсь такой пример убедит тебя что ты говоришь полную ерунду)


            1. LynXzp
              27.07.2016 00:04

              Не что имел в виду tdrive, но на сколько мне известно линтеры только анализируют и предупреждают, остальное делает программист. Кстати компилятор или линковщик таки могут выкинуть переменную или функцию если они не используются.


  1. velvetcat
    25.07.2016 17:58
    +8

    Краткое содержание статьи: «Делайте то, что нужно и не делайте того, что не нужно». Ой, и еще «правильно оценивайте сроки».


  1. MediaRise
    26.07.2016 16:02
    +2

    Я добавлю еще один синдром, он называется «Я это увидел на Хабре, надо внедрять».
    Очень часто слышу по своему опыту, главное всегда одно обоснование технологии: ну на Хабре же написали для чего это.


  1. geekmetwice
    26.07.2016 18:21

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

    К слову, вот эти «профессионалы паттернов» даже не понимают, насколько смешно они выглядят, когда носятся с формулами а-ля «2х3=6». А если «3х2»? А если «4*y=?». Сначала идёт задача и её понимание, и только потом, МОЖЕТ БЫТЬ, после того как придумано решение, его можно «стандартно» решить шаблоном, да и то, если этот шаблон нужен.


    1. tdrive
      26.07.2016 20:59

      >2. Не применяйте методики только потому, что кто-то очень много о них говорит.
      А когда их нужно применять?

      >Сначала идёт задача и её понимание, и только потом, МОЖЕТ БЫТЬ, после того как придумано решение, его можно «стандартно» решить шаблоном, да и то, если этот шаблон нужен.
      Так сказал как будто паттерны проектирования что то плохое, это архитектурные решения проверенные временем, ну относительно проверенные. Они не могут быть нужны или не нужны, они или подходят для задачи или не подходят.


      1. geekmetwice
        26.07.2016 22:52

        > А когда их нужно применять?

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

        > Так сказал как будто паттерны проектирования что то плохое

        Именно. Представь себе, ты пришёл на урок математики, а тебе объясняют: «2 + 3 = 5» — запишите, дети, ЭТО ОЧЕНЬ ВАЖНО!
        Смысл? Тебе дают квадратное уравнение, а у тебя в голове «2 + 3». Ну да, на очередной задаче сложения ты это применишь, но в программировании не осталось «простого сложения», над каждой задачей надо думать. И от того, что пара паттернов подошла в твоей задаче, это вовсе не повод кричать о них на каждом углу. Да и самих шаблонов (стоящих, чтобы помнить) — раз-два и обчёлся. Фактически, это ты как программист должен такие шаблоны выдавать на ура после минуты раздумий (т.е. идём по пути задача -> решение), а не бегать с десятком шаблонов «в какую бы задачу их воткнуть». Люди потеряли смысл паттернов — от того и городят то, что и написано в заголовке статьи — переусложнённое ПО.


        1. tdrive
          26.07.2016 23:56

          >Тебе дают квадратное уравнение, а у тебя в голове «2 + 3»
          Так паттерны это и есть квадратные уравнения, это шаблон, можешь взять его частично, можешь дополнить…
          >это ты как программист должен такие шаблоны выдавать на ура после минуты раздумий
          любую архитектуру надо проверять на опыте и делать выводы, паттерны это то что уже проверено и известны плюсы и минусы.
          >т.е. идём по пути задача -> решение
          все верно
          >а не бегать с десятком шаблонов «в какую бы задачу их воткнуть».
          так же как и не решать все задачи через квадратные уравнения, это проблема ограниченного кругозора а не паттернов, причем тут они вообще?
          >Люди потеряли смысл паттернов — от того и городят то, что и написано в заголовке статьи — переусложнённое ПО.
          не понимаю о чем ты и где ты нашел хоть что то сложное в паттернах, он как раз и помагают не усложнать, это простые удачные решения часто встречающихся задач.


        1. tdrive
          27.07.2016 00:14

          Давай рассмотрим реальную ситуацию, вот стоит у тебя задача построить некую систему реального времени, например систему мониторинга, ты можешь неделю думать как и что тебе сделать, попробовать что нибудь написать, потом еще неделю на осознание того что твое решение нифига не подходит по требованиям да же в теории… или можешь вспомнить про лямбда и каппа архитектуры и у тебя в голове готовая схема ключевых элементов системы, надо только конкретные детали додумать. Или ты можешь сейчас на ура выдать пару альтернатив лямбда и каппа архитектурам, после минуты раздумий, которые лучше подойдут под эту конкретную задачу? Очень интересно было бы послушать.


    1. tdrive
      26.07.2016 21:09

      На прошедшем pgday вот этот чел http://pgday.ru/ru/2016/speakers/28 рассказывал что у них все построено на микросервисах, один микросервис переписывается командой с 0 за неделю и при таком раскладе совершенно пофиг на чем он написан, хоть на хаскеле, зато разработчики ни чем не ограничены в выборе технологий и могут спокойно набираться опыта и расти в профессиональном плане.


  1. Adnako
    26.07.2016 23:33

    Несколько вещей гарантированно будут увеличиваться со временем: ***,
    энтропия вселенной

    Объясните, пожалуйста эту мысль.