....продожение. Начало.
Как нетрудно было догадаться из предыдущего поста, пожалуй единственным подходящим решением проблем, возникающих при разработке портабельных систем, является абстракция и обобщенное программирование - сильные стороны C++. Описание техник можно поискать в серии книг C++ In Depth, книгах Мейерса и прочих гуру, я же приведу некоторые мысли относительно моментов, на которые следует обратить внимание, если вы используете для разработки сторонние библиотеки/компоненты.
Наличие довольно большого колличества библиотек для решения самых разнообразных задач, компилируемых под несколько основных платформ, существенно облегчает работу программиста. Однако все же существует несколько вопросов, которые возникают при использовании сторонней библиотеки при разработке продукта, и практически все они относятся к качеству кода...
Первым моментом, на который стоит обратить внимание, пожалуй, будет стабильность кодовой базы. Согласитесь, не совсем приятно будет, когда при выпуске новой версии программного продукта вы решили заодно проапгрейдить библиотеки и обнаружили, что разработчики одной из них заодно с пофикшеными багами поменяли API и билд сваливается.
Вторым - то насколько этот компонент подвергается тестированию, что повышает вероятность отлова багов до выпуска релизов, а вместе с этим и вероятность обойтись без лишней головной боли.
Третьим - наличие поддержки и ее вменяемости. Да я понимаю, что у вас комманда "звезд", которые умеют читать код по диагонали и нюхом чуять баги. Но они приходят и уходят и, вполне вероятно, что поддержкой все же придется воспользоваться.
Четвертым - maintainable ли код? Насколько легко будет споровождать его (если он открыт) в случае, если разработчики "забьют" на компонент? Насколько легко сопровождать код, написанный с использованием этой библиотеки? (так как в большинстве случаев библиотека и язык, на котором она написана, диктуют стиль программирования). Насколько легко вы воспринимаете идиомы, используемые при написании такого кода?
Пятым фактором является портируемость - то, что вынесено в заголовок данного поста, поэтому по умолчанию подразумевается портируемость библиотеки. Однако тут нужно учесть ряд моментов, как-то: есть ли зависимости от третьих библиотек? насколько все сказанное выше относится к этим библиотекам? Понятно, что в ряде случаев такую оценку провести попросту невозможно, поэтому зачастую просто полагаются на разработчиков и если они говорят, что "portable", - значит "portable" и все тут.
Шестым фактором является наличие возможности локализации. Можно ли использовать библиотеку/компонент в другой временной/географической зоне? нужны ли изменения?
Вот такие вот пироги. Все сказанное, конечно, так - абстрактные мысли, не подкрепленные личным опытом, поэтому хотелось бы услышать мнения людей, которым действительно приходилось сталкиваться с подобными проблемами, может чего упустил? написал неправильно? Из тех кого я читаю, на ум приходит пожалуй только Alex Ott.
Велкам в камменты, как говориться ;-).
Как нетрудно было догадаться из предыдущего поста, пожалуй единственным подходящим решением проблем, возникающих при разработке портабельных систем, является абстракция и обобщенное программирование - сильные стороны C++. Описание техник можно поискать в серии книг C++ In Depth, книгах Мейерса и прочих гуру, я же приведу некоторые мысли относительно моментов, на которые следует обратить внимание, если вы используете для разработки сторонние библиотеки/компоненты.
Наличие довольно большого колличества библиотек для решения самых разнообразных задач, компилируемых под несколько основных платформ, существенно облегчает работу программиста. Однако все же существует несколько вопросов, которые возникают при использовании сторонней библиотеки при разработке продукта, и практически все они относятся к качеству кода...
Первым моментом, на который стоит обратить внимание, пожалуй, будет стабильность кодовой базы. Согласитесь, не совсем приятно будет, когда при выпуске новой версии программного продукта вы решили заодно проапгрейдить библиотеки и обнаружили, что разработчики одной из них заодно с пофикшеными багами поменяли API и билд сваливается.
Вторым - то насколько этот компонент подвергается тестированию, что повышает вероятность отлова багов до выпуска релизов, а вместе с этим и вероятность обойтись без лишней головной боли.
Третьим - наличие поддержки и ее вменяемости. Да я понимаю, что у вас комманда "звезд", которые умеют читать код по диагонали и нюхом чуять баги. Но они приходят и уходят и, вполне вероятно, что поддержкой все же придется воспользоваться.
Четвертым - maintainable ли код? Насколько легко будет споровождать его (если он открыт) в случае, если разработчики "забьют" на компонент? Насколько легко сопровождать код, написанный с использованием этой библиотеки? (так как в большинстве случаев библиотека и язык, на котором она написана, диктуют стиль программирования). Насколько легко вы воспринимаете идиомы, используемые при написании такого кода?
Пятым фактором является портируемость - то, что вынесено в заголовок данного поста, поэтому по умолчанию подразумевается портируемость библиотеки. Однако тут нужно учесть ряд моментов, как-то: есть ли зависимости от третьих библиотек? насколько все сказанное выше относится к этим библиотекам? Понятно, что в ряде случаев такую оценку провести попросту невозможно, поэтому зачастую просто полагаются на разработчиков и если они говорят, что "portable", - значит "portable" и все тут.
Шестым фактором является наличие возможности локализации. Можно ли использовать библиотеку/компонент в другой временной/географической зоне? нужны ли изменения?
Вот такие вот пироги. Все сказанное, конечно, так - абстрактные мысли, не подкрепленные личным опытом, поэтому хотелось бы услышать мнения людей, которым действительно приходилось сталкиваться с подобными проблемами, может чего упустил? написал неправильно? Из тех кого я читаю, на ум приходит пожалуй только Alex Ott.
Велкам в камменты, как говориться ;-).
еще один фактор, наверное относящийся к кодовой базе - хороший дизайн, с правильным уровнем абстракции. Этот фактор позволяет программисту оперировать терминами из той области для которой он ведет разработку.
ReplyDeleteЯ достаточно часто встречал классы, которые содержали десятки методов, которые должны были решить все возможные задачи, хотя его можно было разбить на несколько классов, и использовать их композицию.
P.S. пока писал, решил что это наверное относится к 4-му пунтку :-)
P.P.S. и еще одно - зависимости между классами. Подключение класса, решающего одну задачу не должно приводить к линковке всех классов проекта. Даже внутри приложения желательно выделять отдельные подсистемы в библиотеки с четким интерфейсом
т.е. использовать модульность? ну а по поводу хорошего дизайна - тут мнения расхожи, как мне кажеться. Есть рекомендации признанных экпертов в этой области относительно хорошего дизайна, best practices, паттерны, однако велосипедостроители находятся всегда (и это не всегда плохо). И если рекомендации доступны допустим в виде книг этих экспертов, то о best practices известно меньше, ИМХО.
ReplyDeleteПо первому пункту: при статической компоновке я особых проблем не вижу. Обычно API меняется незначительно и все сводится к минимальному изменению кода. При динамической компоновке, по крайней мере в мире .so-библиотек, все решается на уровне компоновщика и имени библиотеки. Есть определенные праила именования, которые предписывают указывать версию API в имени после суффикса .so
ReplyDeleteПо второму пункту: обычно, если компонент достаточно поплярен - он отлично тестируется самой аудиторией и авторы достаточно оперативно исправляют баги. Если же компонент специфический, редкоиспользуемый - приходится рисковать.
По третьему пункту - согласен со всем.
По четвертому: обычно достаточно редко требуется сопровождение или развитие компонента.
Пятое: авторы, обычно, указывают, для каких систем была проверена работоспособность компонента.
Шестое: сейчас редко стретиш что-то, что должно поддерживать локализацию, но не поддерживающее ее. Это может быть только очень древний продукт и в таком случае проще его или переписать заново. По крайне мере - ту часть, которая необходима.
Теперь общие замечания. К портируемости относится 2-й пункт, 5-й, и, частично, 3-й. Остальное важно для поддержки.
Архитектура и хороший дизайн тоже мало влияют на портируемость. Основная их цель - сопровождение и развитие.
P.P.S. и еще одно - зависимости между классами. Подключение класса, решающего одну задачу не должно приводить к линковке всех классов проекта. Даже внутри приложения желательно выделять отдельные подсистемы в библиотеки с четким интерфейсом
ReplyDeleteНе совсем согласен. Да, для модуля должен быть определен абстрактный интерфейс, но вводить ограничение на компоновку глупо в том случае, если сам проект предоставляет инструментарий в виде библиотек.
Тут главное - избежать избыточности. В этом отношении я полностью согласен с альтовцами, которые требуют компоновки всех программ и библиотек с ключем --as-needed.
по первому пункту - имеется в виду примерно следующая ситуация:
ReplyDelete//было
int recv (char* buf);
//стало
int recv (char* buf, size_t size);
по второму пункту имеется в виду наличие автоматических тестов для проверки корректного функционирования.
по четвертому и пятому - согласен.
по поводу того что относиться к портируемости, а что к поддержке, я почему-то подумал, что обеспечение возможности поддержки для разных платформ тоже относится к портируемости.
//было
ReplyDeleteint recv (char* buf);
//стало
int recv (char* buf, size_t size);
- не вижу тут проблемы.
Про поддержку - я, почему-то, подумал про пользовательский саппорт. Конечно, поддержка различных платформ - это корень портируемости.
почему? разве подобные изменения не приведут к тому, что сборка продукта не увенчается успехом?
ReplyDeleteИзменения API отслеживаются и исправляются разработчиком. Конечный пользователь даже не подозревает об этом. Изменения ABI при статической компоновке тоже отслеживаются и исправляются разработчиком. При динамической компоновке работоспособность приложения начинает зависить от окружения. При зменениях в протоколах обмена данными программа тоже перестает работать на глазах у конечного пользователя.
ReplyDeleteСамые хорошие ошибки - это те, которые находятся в процессе отладки (моя любимая - Segmentation fault, т.к. по core-файлу потом достаточно просто найти проблему). Самые плохие ошибки - это те, которые вылазят у пользователя. Обычно они трудновоспроизводимы, а пользователь недостаточно квалифицирован, чтобы составить грамотный багрепорт.
согласен, но на отслеживание и исправление тратится время. В то же время, если код стабилен, то вероятность таких изменений снижается, следовательно разработчик продукта от этого только выигрывает.
ReplyDelete