Pull to refresh

Comments 27

а джаваисты придумали maven, чтобы проблем со сборкой и использованием не было
С джавой все гораздо легче и проще. Согласен.
Ну в самой идее maven ничего дцава специфичного нет, можно было наверное что то такое сделать и для C/C++
Я имел в виду работу с компонентами и интерфейсами. В яве все достаточно четко регламентировано и рефлекшн реально жить помогает.
Ну да, и еще класслоадеры, которые позволяют реализовать систему плагинов
Это конечно здорово если все библиотеки будут атомарные и независимые. Только вот это далеко от реальности, по крайней мере при разработке бизнес приложений.

Вот пример поставлена задача реализовать работу приложения по определенному интерфейсу для работы с API какого либо сервиса (предположим что готовых библиотек для работы с нашим API нет) и в момент написания не известно будет ли данная библиотека использоваться в дальнейшем. Что делаю я, как разработчик — решаю задачу. Пишу библиотеку (класс, модуль что угодно) для работы конкретного приложения и тестирую приложение и наш свеженаписанный модуль в тех условиях в которых используется мое приложение. Результат: задача решена в максимально выгодные сроки.

Затем через полгода приходит автор и говорит: «Вот мне нужна вот эта штука....» (продолжение смотреть выше)

Т.е. уважаемый предлагает плевать на задачи которые ставятся перед разработчиками и разрабатывать модули с тестированием во всевозможных условиях пусть даже далеких от реалий проекта, на тот случай «А вдруг кому нибудь понадобится». Считаю что выделение в самостоятельные библиотеки необходимо делать лишь если возникла потребность в повторном использовании кода.
+1 и желательно с автором (-ами), кто поближе к оригинальным исходникам.

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

Я такого не писал.

«реализовать работу приложения по определенному интерфейсу для работы с API какого либо сервиса»

Описываем, какие функции из API сервиса нам нужны. Пишем интерфейс, предоставляющий работу с этими функциями. В идеале пишем тест для интерфейса. Реализуем компонент-wrapper между API сервиса и нашим приложением. Пока пишем, постоянно проверяем тестом работу компонента. Компонент отлажен. Подключаем его к проекту.
Если нет времени — можно тест не писать. Отлаживать запарно только.

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

* Ставим себе цель — получить качественный чёрный ящик из соседнего проекта по своему чёткому ТЗ (хочу то-то и то-то и всё)
* Узнаём, что в соседнем проекте есть нечто потенциально реюзабельное
* Пишем ТЗ на то, что мы хотим (можно и одной строчкой): хочу компонет, чтобы делал foo(string bar)
* Идём в соседний проект к тому, кто знает конкретику и узнаём детали
* Далее идем к ПМу своего проекта и запрашиваем у него, чтобы он договорился с ПМом соседнего проекта о выдаче подобного компонента (это надо, чтобы при невозможности прям щас, ПМ нашего проекта наши задачи подвигать смог, т.к. в данный момент мы «типа заблочены»)
* Получаем компонент и проверяем что он работает (если нет, извещаем ПМа, что не хочет работать и повторяем)
* PROFIT!!11

М.б. в таких задачах «парное» программирование пригодится реально :)

ps: Алгоритм не идеальный, но цель — получить работающий компонент в наш проект от тех, кто за меньшее время его сможет создать — авторов и только по запросу.
pps: Почему ПМы? А потому-что граница систем (межпроектье).
Хороший вариант, но слишком идеалистичный — т.е. так и надо, только слишком большая вероятность что часть плана не сработает. Вот подводные камни, до которых сходу можно додуматься:

> * Ставим себе цель — получить качественный чёрный ящик из соседнего проекта по своему чёткому ТЗ (хочу то-то и то-то и всё)

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

* Пишем ТЗ на то, что мы хотим (можно и одной строчкой): хочу компонет, чтобы делал foo(string bar)

Малореалистично, что на это выделят отдельные ресурсы, соответственно ТЗ получится куцее и не вполне адекватное.

* Идём в соседний проект к тому, кто знает конкретику и узнаём детали

Нервируя специалиста по конкретике. Только недавно, кстати, придумали одну вещицу, интересную соседним отделам — сразу слетелись как коршуны. Очень неудобно: в результате свои задачи отодвинулись, хотя профит получат эти другие отделы.

* Далее идем к ПМу своего проекта и запрашиваем у него, чтобы он договорился с ПМом соседнего проекта о выдаче подобного компонента (это надо, чтобы при невозможности прям щас, ПМ нашего проекта наши задачи подвигать смог, т.к. в данный момент мы «типа заблочены»)

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

| Нервируя специалиста по конкретике
Дык мы в любом случае к нему придём :)

| как коршуны
Плюсы работы в организации — шаринг и реюс. Так что внутри мы все друг-другу братья и сЕстры. Здесь подход надо бы менять в сторону интеграционных выгод. И лучше решение подымать на уровень выше — на некий «Сход ПМов» или на их Главного ПМа. Представьте, что мы бы в проекте вдруг все начали свои фреймворки и функции для одного и того же бы писать? Главный архитектор бы задушил нас бородою и был бы прав. Так что здесь просто надо смело взять яйки в руки и повысить проблему на след. уровень. Интересы здесь более высоки нежели у конкретных проектов — это интересы организации. Вот пусть соотв. управленческий уровень и думает.

| мы и есть этот самый ПМ
Х.з. ПМ просто может эту мантру вложить с помощью Dependency Injection в головы девелоперов и сделать всё лучше.

| нормальный ПМ заставит интегрировать
Это который не умеет договариваться с соседним ПМом? По моему IMHO это не нормальный ПМ, а процентов 20 от него.
> Вот пусть соотв. управленческий уровень и думает.

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

> > мы и есть этот самый ПМ
> Х.з. ПМ просто может эту мантру вложить с помощью Dependency Injection в головы девелоперов и сделать всё лучше.

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

>> нормальный ПМ заставит интегрировать
>Это который не умеет договариваться с соседним ПМом? По моему IMHO это не нормальный ПМ, а процентов 20 от него.
За всю жизнь я встретил только одного, который адекватно умеет договариваться по техническим вопросам. Так что это не 20% от ПМа, а скорее 80% от ПМов. :)

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

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

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

Только вот проблема такого метода в том, что такая система должна насаждаться повсеместно в компании, а в противном случае, окажется, что либо человек не выделяет нужного внимания (использует командировку как отдых), либо в процессе работы кто-то очень большой постоянно выдёргивает у вас этого человека, либо ещё что-то.
У меня есть опыт работы в конторах, в которых был компонентный подход в командной разработке, есть опыт работы в конторах, где этого подхода нет.
В компаниях с компонентым подходим проект разбивали на компоненты для удобства планирования разработки и тестирования. Сторонние библиотеки и компиляторы были строго регламентированы. Работал билд-сервер.
Для компонентов, которые были строго частью проекта, интерфейсы писали с использованием PIMPL идиомы. Для компонентов, которые могли быть расширены в функциональности и могли бы иметь более широкое применение, интерфейсы делали COM-подобными.
При таком подходе очень удобно автоматизировать тестирование. И не раз случалось, компонентом интересовались из другого отдела. Проблем с переносом в таком случае практически никогда не было.
Возможно второй пример в моей статье не очень удачный, скорее всего я просто не весь контекст ситуации для второго примера изложил.
Как примеры:
Компонеты отделялись по функциональности и разработчикам.
Надо написать протокол — берем либу из другого отдела, реализующую доступ к TCP. Сверху пишем свою либу, реализующую протокол. Тест для нее отдельный. Это один человек.
Нужен XML парсер для настроек. Другой человек. Отдельный компонент и тест.
Доступ к базе. Отдельный компонент. COM-интерфейс. База ведь может расширяться. Тестирование отдельно.
Тестировщикам всегда есть чем заняться. Какие-то компоненты готовы раньше, какие-то позже.
Я в статье рассказал, что если решили использовать компонентную модель разработки, то вот как можно писать интерфейсы.
Ну как-то так.
Вы вообще всю статью читали? Смотрите примеры первый и третий! Либы уже реализованы, но их невозможно воткнуть без страданий и кучи зря потраченного времени. А вот второй пример — да, никто не обязан подстраиваться. Если некогда было сделать либу, глупо ему ставить в вину разработчику.
Принцип повторного использование кода — замечательная, правильная штука! Однако «замечательность и правильность» — это еще не повод возводить ее в предмет культового поклонения! Иначе, Вам придется каждую функцию (включая даже и «приватные методы» ваших модулей, lol) выводить в свой «компонент» со своим «интерфейсом» (что неизбежно приведет ваш проект к накрыванию медным тазом как только кол-во таких «функций-компонентов» станет чуть больше чем over 9k).

Другое дело — разумное, без фанатизма, следование принципу «повторного использования» заключается в следующем: Если реализуя некоторую «большую задачу» Вы реализовали хорошее решение некоторой «малой задачи». И про него ЗАВЕДОМО ИЗВЕСТНО, что это «малое решение» потребуется в решении других «больших задач», то да, это решение имеет смысл выделить в виде отдельного модуля/пакета/библиотеки/класса. Иначе, только «by request». Короче, без фанатизма, будьте прагматиками!

А никто и не говорил о культе. Все согласны, что бывают задачи, которые очевидно могут быть использованы неоднократно. Да и хотя бы в целях удобства отладки логически законченный функционал отлаживать и тестировать удобнее отдельно. Вот ради таких случаев и следует реализовывать его в отдельном компоненте.
А про приватные методы в интерфейсе, вот этого я не понял. Это к чему? Я как раз пытался рассказать, что этого делать нельзя.
К сожалению, «очевидно могут быть использованы неоднократно» != «заведомо необходимо заложить повторное использование». Иначе будет "~100500" компонентов созданных по принципу «наверное, кому-нибудь пригодиться».

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

О! А это почему-же нельзя? Только потому что в «умных книжках» так написано «все что private не светить»? Вы полностью исключаете ситуацию, что работая над «внутренней кухней» какого-нибудь класса/модуля Вы породите внутри приватной функции такое решение, которое можно и нужно будет успешно заюзать в сотнях дальнейших проектов? Только потому что «нельзя»? А как же тогда «повторность использования» и как же тогда пропагандируемый Вами «компонентный подход»?

Перфекционизм — плохое качество для программиста. Но догматизм — еще губительнее.
Рожденное в приватной функции решение я выношу в какой-нибудь Tools.lib, как и написал в статье.
На счет приватных функций в интерфейсе компонента, приведите пример, плз.
Да где я тут догмы пропагандирую? И перфекционизм где?
Я рассказал, как можно интерфейсы оформлять.
Пример первый и третий — как раз таки про существующие либы.
Это все лишнее, вам нужен билд сервер. Отдельно собираем компоненты, отдельно весь проект и исходники.
А билд сервер есть, я про оформление компонентов говорил. Билд сервер не поможет с плохо оформленными компонентами и интерфейсами.
Если у вас есть билд сервер, то компоненты как минимум билдятся, а значит внешние зависимости как минимум резолвятся. Если после этого что-то не работает, то вам нужно интеграционное и системное тестирование всего проекта, плюс положить исходники рядом с скомпилированным проектом.
Отличная статья, но.

А сторонний потому, что в компоненте может быть использована реализация Microsoft STL, а мы хотим STLPort.

char* конечно здорово, но если в конторе общий стандарт, то можно и std::string&

а во вторых, как разработчик мобильных приложений — порой статические библиотеки являются единственным возможным решением.
Выкачиваешь проект. Компилишь. Вылезает куча ошибок, не хватает каких-то инклудов. Начинаешь выяснять. Оказывается для сборки проекта надо выкачать из CVS еще кучу проектов, их тоже собрать. Некоторые собираются стандартно студией, некоторые с бубном, вроде autoconf, make и иже с ними

Камешек в огород OpenSource. Слишком часто разработчики забывают, что для реиспользования код должен как минимум собираться. Т.е. надо полностью документировать от и до все зависимости, ключи, параметры. И постоянное тестирование, чтоб действительно всё, вместе со всеми зависимостями, собиралось за один шаг.
И в модулях желательны хоть какие-нибудь вменяемые комментарии по структуре, архитектуре и использованию, помимо надоедливой GPL/BSD/MIT-шапки.
Реально же, даже если нам не нужен отдельный компонент, а охота просто собрать уже готовый проект, обязательно возникнут затыки.
Вечно то makefile надо запускать с какими-нибудь сверхсекретными ключами (в инструкции по сборке о них, само собой, полный молчок), то выискивать зависимости (скачав и собрав ещё 20 проектов), а то и проверять версии gcc/Perl/Python, т.к. оно собирается лишь при удачном их сочетании.
Править код мало-мальски крупного проекта ещё веселее, т.к. он состоит на 80% из #define/#ifdef, и ещё на 15% из символов подчёркивания. Там, по сути, собственный метаязык поверх C++ определяется, плюс всегда почему-то зверское дублирование, когда один и тот же кусок кода в 5 местах оказывается. И если надо быстро пофиксить мелкий баг, то быстрее оказывается прогнать под отладчиком и пропатчить бинарник, чем неделю вникать в архитектуру, чтоб просто прочесть чёртовы исходники.
Неверное направление кидания камня выбрано. :)

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

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

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

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

Я сам когда-то, когда был молодым идеалистом, хотел создать библиотечку работы с предметной областью, которую бы использовали во всех проектах организации. Даже создал и даже использовал в нескольких проектах, в которых участвовал сам. К счастью, мне это удалось насадить только в них и нигде больше (никто не проникся). Потому что спустя некоторое время в одном проекте библиотечка пошла развиваться по одному пути, а во всех остальных было нецелесообразно идти по нему же. А договариваться очень сложно и требует много ресурсов.

Т.е. не жалуйтесь на неудобство чужих исходников, если они вам достались без платы автору. Не нравится — исправьте и поделитесь патчем (github?), или напишите своё.
Sign up to leave a comment.

Articles