Эксперт в области разработки и облачных технологий
1,6
рейтинг
31 марта 2013 в 23:52

Разработка → Правила жизни в ИТ проектах

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

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

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

Чем проще решение тем оно надежней


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

Не стоит изобретатель велосипеды


Если есть готовый фреймворк, или библиотека который Вы можете использовать — используйте его. Не стоит писать свой.

Логику и типы данных лучше выносить в отдельные сборки


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

Open Source надо использовать с умом


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

Не стоит сразу писать платформу


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

CMS не панацея


Мне часто доводилось видеть веб-проекты, которые начинались с того, что ставилась какая-то популярная CMS и продукт развивался путем «накручивания» на нее кода. В результате получался неповоротливый механизм который процентов на 10% использовал функционал CMS, а 90% кода были перегружены и нечитаемы, так приходилось учитывать структуру самой CMS и структуру ее БД.
Гораздо эффективнее писать решение конкретной задачи, чем пытаться приспособить для этого неповоротливую CMS.

Предметная область важнее всего


Во всех проектах соблюдайте приоритет: Предметная область -> Архитектура -> Административные задачи
Продукт создается для клиента, а не для разработчика, или системного администратора.
Мне приходится встречать ситуации, когда администратор начинает рассказывать разработчикам как им лучше писать API для продукта. Так же встречались разработчики, которые предлагали клиенту отказаться от функционала, так как его не поддерживает CMS с которой разработчик умеет работать. Такой подход недопустим, если вы действительно хотите создать качественный продукт.
Решение создается в первую очередь для клиента, а не для программиста, или администратора.

Оптимизация нужна только там, где нужна


Иногда встречаю разработчиков которые говорят «Я не буду использовать Entity framework, он генерирует не эффективный SQL», или «Использование linq — это синтаксический сахар! Циклы и перебор лучше.» Да, иногда не все вещи которые удобны — будут максимально эффективны в плане быстродействия. Но стоят ли проценты производительности снижения уровня удобства разработки и увеличения объема кода?
Часто бывает достаточно выделить две три «тяжелые» функции в хранимую процедуру и обвернуть ее вызов через Entity Framework, или провести оптимизацию конкретных узких мест в коде, чем полностью отказываться от тех преимуществ которые дают новые технологии.

Читаемый код, лучше переоптимизированного


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

Инструмент должен быть удобен


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

ТЗ должно быть


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

Лучше применять готовый продукт, чем писать свой


Есть много ситуаций, когда разработчик, или клиент решают что стоит написать свое решение. На самом деле, где-то в половине случаев так поступать не стоит.
Разработка — это всегда длительный и дорогой процесс. Поэтому, даже если кажется что написать свой аналог проще и дешевле — в 90% это только иллюзий.
Если на рынке есть аналогичное решение — лучше приобрести его. Оно уже есть и уже работает. Здесь и сейчас.
Писать свое решение стоит только в том случае, все участники проекта осознают риски, понимают что процесс будет длительным и дорогим.
Явные признаки того, что лучше купить и внедрить чем писать:
  • существует продукт который покрывает предполагаемый сценарий использования
  • существует продукт который покрывает предполагаемый сценарий использования после определенной конфигурации
  • существует несколько продуктов которые при взаимодействии и интеграции покрывают предполагаемый сценарий использования
  • существует продукт который можно расширить определенным функционалом (дописать модуль для CRM) и после этого он покроет сценарий использования

Когда есть смысл писать свой:
  • человек принимающий решение точно знает почему он начинает разработку
  • на рынке нет продукта который мог бы реализовать требуемую функциональность
  • у компании достаточно финансов что бы не только длительное время инвестировать в продукт, но и заниматься в последствии его поддержкой
  • Вы стартап, и для Вас работают совершенно другие критерии


Кроме ИТ есть еще много чего в жизни


Этот совет последний по списку, но не по важности. Я не просто так поставил в начале статьи фотографию из ONE ☆ LIFE Everest Expedition организованной Артемием Суриным. Для очень многих в нашей профессии ИТ стало не только работой, но и самой жизнью. Я и сам довольно много времени провожу за экраном ноутбука/планшета/телефона. Но кроме этого есть вещи которые так же доставляют многим из нас немало удовольствия. Для кого-то это дельтапланеризм, для кого-то чтение книг, спорт, путешествия, общение с новыми людьми, коллекционирование, рисование сочинение.

Хочется пожелать всем — не только работайте, но и живите!

P.S. Отдельное спасибо MarcusAurelius — за предварительное ознакомление со статьей и дельные замечания.
Андрей Губский @Ernado
карма
30,5
рейтинг 1,6
Эксперт в области разработки и облачных технологий

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

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

  • +3
    Спасибо :)
  • +4
    Когда есть смысл писать свой:
    В первую очередь нужно писать своей, когда ты чувствуешь, что хочешь сделать лучше, чем есть. Это необходимое условие, а достаточное — если ты чувствуешь, что можешь сделать лучше чем есть (включая разные возможности и квалификация и свободное время и финансы). И есть еще одна важная причина написания своего решения, хоть даже есть на рынке и можно купить — владение им vs лицензирование. Представь, что организация имеет тысячи сотрудников, каждому из которых нужно поставить какой-то софт, можно покупать тысячи лицензий, но чаще оказывается, что разработать просто дешевле и потом самому его неограниченно использовать, да и контроль над продуктом есть, ибо производителя сложно убедить, что нужно срочно добавить функцию в его коробочный продукт.

    По поводу клиента, и того, что клиент всегда прав — рад, что ты подправил в этой части свое видение. Но я все же приведу тут свое мнение полностью. Я согласен, что хороший прогрммист-исполнитель должен делать то, что у него заказывают, но задача архитектора — показать клиенту в чем он ошибается, он еще и аналитик, и чаще, ему виднее чем заказчику, что именно нужно этому заказчику. Типичный заказчик это пучок заблуждений. Если заказчику вовремя не сделать клизьму головного мозга с ромашкой, а просто сделать то, что он хочет, то проект рухнет и полная отверженность ляжет на заказчика, а частичная (закрытие темы) уже на архитектора. Грамотных заказчиков крайне мало, и их иногда можно выявить по признаку — они спрашивают «возможно, я ошибаюсь, что ты думаешь по этому поводу?». А неграмотные захвачены идеей и эмоциями и у них никогда не возникает сомнения. Если переубеждать заказчика, а он видит потом, что ты был прав и сэкономил ему время, деньги и нервы, то такой заказчик будет уже постоянным твоим приверженцем и не захочет искать кого-то другого на следующие проекты.
    • +1
      Грамотных заказчиков крайне мало, и их иногда можно выявить по признаку — они спрашивают «возможно, я ошибаюсь, что ты думаешь по этому поводу?»

      Полностью согласен. Это вообще вопрос присущий людям которые думают. Те кто не думает — уверенны что их мнение единственно-верное, и и мнение других их не интересует в принципе.
    • 0
      но чаще оказывается, что разработать просто дешевле и потом самому его неограниченно использовать

      Обычно, компании покупают продукты, чтобы последние приносили деньги. Поэтому, платить программисту, но оттягивать получение продукта — сильно под вопросом. Если в сумме даже и дешевле будет, то потерянное время может быть значительно дороже.
      Потом, я как программист, прекрасно в курсе своего бесконечного оптимизма. Всегда есть смысл пользоваться готовым продуктом. Свое — это и свои проблемы поддержки. Не только владение.

      Когда нужно (можно) писать свое:
      Когда время на «прикручивание» заметно превышает время на реализацию своего. Особенно, в случае, если требуется очень ограниченный функционал. Не писать свои велосипеды — это хорошо и правильно. Но не стоит впадать в другую крайность и на каждый «чих» тащить огромные чужие библиотеки. Как пример, когда-то мне нужно было сделать преобразования Фурье. Мне настоятельно советовали «библиотеку», мол не стоит писать велосипед. После полдня разбирательств, я бросил эту затею и написал что мне надо было: не преувеличиваю, ровно 4 строки кода.
  • +2
    > Логику и типы данных лучше выносить в отдельные сборки

    Я один не понял о чем речь?
    • +5
      Возможно, автор имел ввиду т.н. анемичную модель данных, когда единые модели данных разделяются на модели-контейнеры данных (содержащие в основном поля и свойства) и отдельно — модели по работе с этими данными (содержащие в основном методы по обработке анемичных моделей). Это если я правильно понял.
      • +1
        Да, именно так.
        • –3
          Кстати, это антипаттерн
          • +2
            Не всегда. Могу привести пример:
            Common — содержит простые классы предметной области.
            Logic.Server — содержит логику серверной части
            Logic.Client — содержит логику клиента.
            И там и там используются одни и те же классы, но логика разнесена сообразно слоям приложения.
            • 0
              Мы рискуем скатиться в очередной холивар «domain-centric vs data-centric архитектуры».
              В data-centric архитектуре anemic модель оправдана. Вопрос в том, оправдана ли data-centric архитектура в сложном enterprise-приложении
            • 0
              Только все равно лучше разделять типы сервера и клиента. И использовать мапперы.
          • +1
            Вообще не антипаттерн. Особенно если работаете с SOA.
            • 0
              Вот что пишет Фаулер на эту тему: www.martinfowler.com/bliki/AnemicDomainModel.html
              Я с ним в этой части согласен
              • 0
                Хорошо, как ваш объект с методами пролезет в сериализацию? Как будет обеспечиваться интероперабельность с другими платформами?
                • –1
                  Объект прекрасно сериализируется, не зависимо от того есть у него методы или нет. Взаимодействие с другими платформами так же не зависит от того есть у объектов методы или нет, а обеспечивается через стандартные механизмы, например WCF
                  • +1
                    Ну да, Dictionary проблем не вызывает, как и циклические ссылки, сериализуется все автоматом, события тоже работают по http.
                    • +1
                      Где вы в словах «объект с методами» увидели события, словари и циклические ссылки?
                      • 0
                        смысл в том, что DTO/View-модели делают не от хорошей жизни, а от того, что:
                        1) попробуйте передать Entity из EF/NHibernate по WCF
                        2) вы правда, хотите отдать клиенту через сервис отображение вашей БД? обычно надо отдавать немного другое.
                        • –1
                          Классы, которые в описали, не относятся однозначно к Domain Model. Разумеется, в некоторых случаях могут быть проблемы.
                  • 0
                    На моём проекте пришлось отказаться от «классических» моделей типа Active Record в сторону анемичных по 2-м причинам:
                    1. Увеличение сложности и распухание моделей. Около 20 полей, на каждое по 2 свойства, + обобщающие аксессоры, + 5 конструкторов, и очень много методов по работе со всем этим добром. И это всё — единая сущность. Прошло время, и сложность увеличилась до такого уровня, что ни вынос Repository в отдельный слой, ни наследование, ни вложенные классы не помогли уменьшить 1000+-строкового монстра. разделение данных и методов помогает бороться со сложностью.
                    2. Проблемы с сериализацией (ASP.NET 3.5). Для хранения данных в сессии используется State Server => все объекты, подлежащие хранению, должны быть помечены атрибутом [Serializable()]. Соотв., если у вас класс, поля которого являются другими классами, то вся эта цепочка тоже должна быть помечена через данный атрибут. А так как модели неразрывно связаны с Repository, ViewModels и Service layer, то лепить атрибут [Serializable()] пришлось бы вообще на всё подряд.
                    • –2
                      1. Вы выбрали неверный способ борьбы со сложностью. Помещать все методы, относящиеся к классу, в этот класс — такой же антипаттерн как и анемичная модель. Должно быть разделение на репозитории, сервисы, доменную модель, фабрики и т.д. Рекомендую прочесть «DDD» Эванса. Также можно прослушать наше обсуждение книги: ru-studygroup.livejournal.com/1517.html
                      2. Хранение в кеше — отдельная тема. Вкратце — нужно либо исключать из сериализации ненужные поля атрибутом [NonSerialized], либо делать свою систему сериализации
  • +2
    «Использование linq — это синтаксический сахар! Циклы и перебор лучше.»

    Забудьте это. А еще лучше, возьмите свой сложный алгоритм на переборах, перепишите на linq и замерьте. Будете удивлены. В большинстве случаев linq будет работать так же, как и на переборах. Причем не важно for или foreach
    • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Замерял. Работал правда не с Linq2SQL, а обычным Linq2Objects. Разница очень серьёзная в сравнении с for.
      Я не помню, инлайнит ли полный десктопный JIT маленькие лямбды, но CE ничего подобного не делает. И миллионы раз вызывает метод, что крайне дорого (расположение аргументов на стеке, возврат, и так далее). И чем больше Linq инструкций (Select, Where, Aggregate и тд) у вас будет тем хуже.

      • 0
        Вы сейчас попробуйте. Когда появился Linq — тормоза были, помню. В 4.5 дотнете уже всё в порядке. Вполне может быть, что linq не супер всё может оптимизировать, как это можно было бы вылизать долгими трудами и страшным кодом с помощью переборов, но работает в основном хорошо.

        Я замерял и удивился. Реально сложный алгоритм, с групбаями, и всем прочим. Конечно, не могу сказать, что прямо репрезентативные замеры получились. Меня интересовал только мой алгоритм, исследования не проводил. Но вот линькью дал одинаковую производительность с «оптимизированным» алгоритмом. А код в несколько раз стал меньше и намного более читаемый. Причем, не важно, со структурами он работает, с классами и т.д.
        • 0
          Про читаемость соглашусь, про перфоманс нет :)
          Для сложного алгоритма у Linq в любом случае будет приличный оверхед(там явно компилятор не соптимизирует ничего). Ну скажем соотношение по времени с развернуты руками циклом будет 2:3.

          Если получилось одно и то же время, вероятно вы просто что-то не то меряли и «переоптимизировали» алгоритм руками (например забыли про какой нибудь досрочный выход из цикла по условию :)
          • 0
            Как минимум — получилось. Если действительно бывает, что линькью делает так же, как и ручной перебор, то уже можно следовать железному правилу — писать на линькью. А если окажется (вдруг), что тормозит, смотреть почему и оптимизировать. (достаточно сложный был у меня алгоритм с проверками и брейками)

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

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

            Я готов поверить, что в 3.0-3.5 дотнете линькью мог «принципиально» сильно тормозить. В результате чего и в посте написали — лучше перебор. Сейчас я такого не наблюдаю.
  • +6
    На каждый пункт можно привести не один аргумент как «за» так и «против». Хоть бы и отсюда

    Несколько пунктов.

    Чем проще решение тем оно надежней

    Упрощать сложно. Нужны критерии «простоты» — что именно должно быть «просто»? Потому что абсолютно все «просто» быть не может.

    Не стоит изобретатель велосипеды

    Конечно, кто спорит. Но есть нюанс — нужно знать, что есть этот фреймворк, нужно понять, что он в принципе подходит, нужно знать, как именно его правильно использовать. А если их несколько похожих — нужно сравнить и выбрать наиболее подходящий. А время идет и подспудно сидит мысль — "давно бы уже сам все написал, чем сидеть выбирать, я ж программист, и я точно знаю, что именно мне нужно!"

    Даже плохое ТЗ лучше чем отсутствие какого либо.

    Тоже поспорю. Плохое ТЗ создает ложное представление о наличии какой-то информации, в то время как на самом деле информация может быть неактуальной, несистематизированной и т.п. И разработка по этому ТЗ будет пустой тратой времени. А делать не то что нужно — это (имхо) обычно гораздо хуже, чем вообще ничего не делать.

    Каждый проект — сложный клубок компромиссов и паллиативов, основанных на предметной области, задаче и опыте каждой конкретной команды. И никакой «свод правил» не избавит от проблем. Вопрос только в их количестве :)

    • +1
      Разные бывают проекты. В 95% случаев Вы правы. В остальных ТЗ — это залог успешности проекта.
  • +1
    Так же встречались разработчики, которые предлагали клиенту отказаться от функционала, так как его не поддерживает CMS с которой разработчик умеет работать. Такой подход недопустим, если вы действительно хотите создать качественный продукт.

    Бывают и такие случаи: у компании уже есть система с инструментами, в конечном итоге дающими заказчику тот результат, который он хотел; однако заказчик из-за недостатка опыта работы с подобными системами, либо от переизбытка фантазии, начинает выдумывать настолько нестандартные и бессмысленные варианты решения тех же самых задач и при этом настолько упорно стоит на своём и не хочет понимать объяснений, что аргумент «наша система не позволяет этого сделать» начинает казаться не таким уж и ужасным :)
  • +2
    Хочется пожелать всем — не только работайте, но и живите!

    Как говорят французы «Art de vivre»
  • +1
    Ребята, будем жить! (с) :-)
    Спасибо за теплые слова.

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