LINUX.ORG.RU

Совместная разработка

 , ,


0

1

Привет.
Уточню сразу - у меня нет опыта совместной разработки. Допустим, у меня есть некая многопоточная софтина, как правильно организовать совместную работы с малоизвестными энтузиастами? Подозреваю что нужно сделать некое ядро (в которое никого не пускать) и модульную систему с чётко описанным интерфейсом, и принимать pull request’ы в виде модулей. Ну не пускать же первого встречного править всё что угодно.

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

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

Silerus ★★ ()
Ответ на: комментарий от Silerus

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

pavlick ★★ ()

Самый простой вариант:

Ветка master - для стабильного релиза, держишь ты.

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

Каждая фича\задача - отдельная ветка которая потом сливается в develop через pull request.

Norgat ★★★★★ ()
Ответ на: комментарий от pavlick

И так предположим Вы начальник проекта и вы выдали мне задачу.

  1. Вариант вы даете частичный доступ. Вы создаете под меня отдельную ветку (branch) и даете возможность в нее вносить изменения - я ее клонирую к себе, но при это я еще постоянно делаю fetch (fetch и pull - это разные вещи) из основной ветки (это важно, вообще полезно затягивать изменения перед началом работы, я имею ввиду регулярно), чтоб не сильно разбежаться. Я начинаю работать и делаю commit в свою ветку. Как то я рапортую вам о прогрессе, и на базе моих отчетов, проверяете работу (собираете и проверяете) и принимаете решение когда моя работа должна войти в основную ветку (т.е сливаете ветки в единую).
  2. Вариант вы не даете мне доступ. Я клонирую к себе проект, регулярно произвожу fetch, и по результату, на почту или по другому каналу отправляю вам patch. Вы накатывает patch на свою версию и либо принимаете его (фиксируете изменения в основной ветки, сами выполняете команды commit и push) или откатываетесь назад.
Silerus ★★ ()
Ответ на: комментарий от pavlick

Отломать что-то в многопоточном коде - плёвое дело

открой для себя регрессионное тестирование

я пишу каркас/основу с ясным интерфейсам

сложные вещи один не напишешь

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

Lzzz ()
  1. Вариант - никто не знает что делается: Вы даете мне техническое задания, я создаю на удобном мне сервере хранилище, пишу библиотеку, пишу под нее документацию, проверяю на своих тестах, даю вам ссылку на хранилище - и мне пофиг как это будет работать в вашем проекте, это ваша головная боль встроить это.
Silerus ★★ ()
Ответ на: комментарий от pavlick

как для вас определить область дозволенного? Отломать что-то в многопоточном коде - плёвое дело.

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

ugoday ★★★★★ ()

И если хочешь выступать в роли лидера проекта, почитай книгу Дэн Пилон, Расс Майлз «Управление разработкой ПО».

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

Lzzz ()
Ответ на: комментарий от ugoday

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

pavlick ★★ ()
Ответ на: комментарий от WitcherGeralt

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

pavlick ★★ ()

Иерархию всегда можно построить через ревью. Сначала ты никому не веришь и пускаешь в master только то, что посмотрел. Потом, когда у индивида достаточно компетенций по проекту что бы лить в мастер без согласования и он достаточно адекватен, что бы в спорных случаях позвать тебя - даёшь ему права лить в master и выбирать следующих адекватных индивидов. У этого процесса есть множество вариантов но принцип изложенный выше - един, по теме смотри всякие git flow, github/gitlab flow e.t.c.

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

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

pon4ik ★★★★★ ()
Ответ на: комментарий от pavlick

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

а) она многопоточная

б) она, возможно, существует

этого очевидно мало

anonymous ()

Если речь об opensource-разработке, то ИМХО, правы те, кто указывает, что проблема не в том, как рулить контрибьютерами, а в том, чтобы их привлечь. Вряд ли сразу появятся десятки желающих прислать тебе пулл-реквест. А с единичными пулл-реквестами достаточно ревью и тестирования. Многопоточность кода тут мало на что влияет, при условии наличия минимально приемлемой для многопоточки архитектуры. Кроме того, есть ли причины бояться, что в коде появятся баги? Они есть в любой нетривиальной программе в любой момент времени.

roof ★★ ()
Последнее исправление: roof (всего исправлений: 1)

Спасибо всем кто отписался. Ну еще пару слов про тесты, я не сильно упорот - вообще не вижу смысла в каких-то там фреймворках, клепать исполняемый тест файл, добавлять в TESTS automake’а, make check, ошибки на stderr. Вроде удобно.

pavlick ★★ ()
Ответ на: комментарий от x905

У тебя очень сильные аргументы, а по-существу можешь обосновать? Например, я накостылю:

typedef bool (*fn_t)();
fn_t tests[] =
{
	[](){return true;},
	[](){return true;},
	[](){return true;}
};
int main(int argc, char *argv[])
{
    // Запускаем или все тесты, или заданный через командную строку.
}

Здесь товарищ тоже спрашивал https://softwareengineering.stackexchange.com/questions/137302/do-i-really-need-a-unit-test-framework, все перечисленные в ответ плюшки в моем костыле есть - авто подхват теста (он же в массиве), запуск конкретного, …

pavlick ★★ ()
Ответ на: комментарий от anonymous

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

pavlick ★★ ()

Ну, во-первых, у тебя не буде контрибьюторов, во-вторых, ты и проект не осилишь, так как тебе рано пока в тимлиды. Ты даже не понимаешь с какой целью делаются большие проекты (с целью набить шишек и стать умнее/сделать что-то полезное). В первом случае ты бы не спрашивал, так как тебе это не надо, во втором, ты бы делал что-то полезное, а не трындычал на ЛОР-е с бездельниками.

peregrine ★★★★★ ()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от pavlick

Ну как минимум

  • твои ошибки в stderr CI пережевывать не будет

  • с сетапом и тирдауном (которые ещё и на разных уровнях будут нужны) ты соснешь

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

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

anonymous ()
Ответ на: комментарий от snizovtsev

Вот, допустим, я стал долларовым миллионером. Как мне правильно выбрать яхту?

Не выбирай яхту, там тебе нос на клей присобачат, дай мне 300К USD и я тебе спроектирую судно выживальщика с полной автономкой, даже Тинькофф со своим ледоколом за 100 миллионов USD умрёт от зависти. А пираты будут прятаться в бухты только услышав твои позывные по радио.

foror ★★★★ ()

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

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

foror ★★★★ ()

Допустим, у меня есть некая многопоточная софтина, как правильно организовать совместную работы с малоизвестными энтузиастами?

Для начала, выбрать правильную лицензию. А то (ну а вдруг полезная штука окажется), потом поздно будет под GPL/AGPL перелицензировать.

vvn_black ★★★★★ ()
Ответ на: комментарий от pavlick

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

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

typedef bool (*fn_t)();
fn_t tests[] =
{
	[](){return true;},
	[](){return true;},
	[](){return true;}
};
int main(int argc, char *argv[])
{
    // Запускаем или все тесты, или заданный через командную строку.
}

Супер, давай начнём с этого. Пишешь ты сотню таких тестов, всё тебя устраивает. Потом захочется видеть какой тест упал, ведь не удобно отсчитывать 79-й тест от начала в твоих tests[]. Тратишь время, пишешь в сотне тестов сообщения что это за тесты. Потом захочется видеть что упавший тест возвращает вместо ожидаемого. Тратишь время, добавляешь логгинг в сто тестов. Потом захочется цветов. Добавляешь в тыщу тестов (да, их к этому времени прибавилось). Потом оказывается что бывают исключения, оборачиваешь запуск в try..catch, это же пара строк. Но оказывается что исключения бывают ожидаемые и нет, поэтому оборачиваешь в try..catch ещё и часть тестов. Потом в тестируемом коде добавляется некий флаг тюнящий поведение, и нужно каждый тест проверять с флагом и без. Ты же не дурак копипастить тесты, поэтому функторы делаются полноценными лямбдами с захватом параметров и запускаются с разными оных параметров наборами. Потом оказывается что для части тестов нужны один параметры, для части другие. Пишется класс для параметров, и код для комбинаторного перебора. Также появляется несколько tests[] различающиеся параметрами. Начинает писаться абстрактный код для обработки того что обрабатывается везде одинаково, и соответсвенно куски частного для каждого типа тестов. Какие-то visitor’ы для заполнения вариантов параметров. Потом тебе требуется добавить ещё пару сотен тестов и ты понимаешь что затрахался писать в каждом логгирование, поэтому нужно сделать общий форматтер ожидаемого и возвращаемого значений. Пишешь его. Но ты всё ещё затрахался писать в каждом тесте что он тестирует, почему бы не сделать так чтобы сообщение просто показывало код проверки которую выполняет тест типа myFunc(1, 2) == 3? Перепиливаешь все эти лямбды на макросы со стрингификацией. Потом хочется тэгов чтобы запускать часть тестов, и вообще нужна возможность хранить метаданные для каждого теста - перепиливаешь лямбды обёрнутые в макросы на классы обёрнутые в макросы. Перепиливаешь систему параметров, потому что тесты больше не лямбды с захватом, а классы и можно сделать по-человечески без visitor’ов. Параллельно вся эта конструкция обрастает и другими насущными фичами - добавляется поддержка json/html/xml вывода для красивых отчётов, нечёткое сравнение float’ов, ограничение тестов по времени, поддержка в качестве ожидаемых значений контейнеров и других сложных типов, красивое сравнение этих контейнеров а-ля diff, поддержка пропуска тестов по условию, механизм для того чтобы не копипастить одинаковую инициализацию в кучу тестов, ещё немного комбинаторики, отлов в дополнение к исключениям сигналов, контроль rusage, отлов утечек памяти, потом возникает необходимость в mock’ах…

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

slovazap ★★★★★ ()

модульную систему с чётко описанным интерфейсом

Реальная разработка начинается там, когда приходит понимание что «четко описанного интерфейса» не существует.

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

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

А в остальном все по класике - на каждый пук - отдельная ветка, в которую регулярно автором подмерживается develop. Дорос до релиза - мержишь выбранные фиче-ветки в мастер. Ну и тесты, тесты на каждую функцию, expected success тесты для отлова основных ошибок, expected fail тесты для отлова того как работает твоя система ошибок. Ты ж ее тоже ж проектируешь? :)

nikitos ★★ ()

Подозреваю что нужно сделать некое ядро (в которое никого не пускать) и модульную систему с чётко описанным интерфейсом, и принимать pull request’ы в виде модулей.

Продуктивность будя хреновая. Менее плохо сделать «Organization», пригласить туда тех, кто будя пилить и пускай коммитят напрямую (с комментариями конечно).

anonymous ()
Ответ на: комментарий от next_time

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

anonymous ()