Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
В голове уже летают различные абстрактные модели, что от чего и куда. Но ни за одну из них ухватиться не получается, потому что перед тобой чистый лист и вырвав из головы одну мысль, применить ее не к чему, а вытащить весь скелет не получается потому, что ты уже думаешь о решении задачи, а тебе еще только нужно написать костяк приложения.
В ходе написания проекта я пришел к выводу, что это уже не первый раз, когда у меня получается подобная архитектура
проще отталкиваться уже от чего то
#include <QApplication>
#include <qqml.h>
#include "declarativeview.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setApplicationName("vreen");
a.setOrganizationName("vreen");
a.setOrganizationDomain("https://github.com/gorthauer/vreen");
DeclarativeView view;
return a.exec();
}
REVISION=`svn info | grep Revision | sed s/Revision:\ //` if [[ "$REVISION" == "" ]]; then REVISION=`svn info | grep Редакция: | sed s/Редакция:\ //` fi
de_DE? Чтобы корректно распарсить вывод команды, нужно просто выставлять LANG=C:REVISION=`LANG=C svn info | grep Revision | sed s/Revision:\ //`
#include "program_options.h"#include "version.h"#include "MyCompany/MyProject/program_options.h"#include "MyCompany/MyProject/version.h"А должно подразумевать указание «пространства имён» (как в Бусте и везде):
#include «MyCompany/MyProject/program_options.h»
#include «MyCompany/MyProject/version.h»
2) Такая иерархия файлов плохо масштабируется. Попробуй рассмотреть пример не отдельно взятого проекта в вакууме, а взаимодействие пары пользовательских модулей (например, library и runner), заданных заголовками и исходниками, и пары сторонних библиотек, заданных заголовками и предкомпилированными бинарниками.
На счет С++ namespace, я их специально не использую тут, потому что не знаю какие.
Я ни в коем случае не буду использовать название компании в исходных кодах.
Вы наверно пишите на Java или C#, потому что вот именно там я такую штуку видел очень часто.
#include "version.h"#include "SomeLibrary/version.h"#include "AnotherLibrary/version.h"...Я даже имя проекта в сорсах не использую.
Я даже имя проекта в сорсах не использую.
А в чем проблема конкретно с «version.h», его же никто напрямую не включает.
При этом сам MySupeLib.h можно включать как #include<foo/bar/MySuperLib.h>, это ничему не противоречит.
поскольку «путь» разрешается относительно текущего файла а потом уже относительно include path.
// Module/foo.cpp#include "version.h" // 1) Нет разрешения относительно текущего файла, будет поиск в include path,// где равноправны «мой» и «его» экземпляры version.h.#include "../version.h"// 2) Теперь файл Module/foo.cpp тяжело перемещать по необходимости (например, вглубь),// потому что помимо его перемещения в Module/Subsubmodule/ нужно _исправить его код_,// добавив больше «точек»: #include "../../version.h"#include "MyLibrary/version.h"// 3) Текущий файл Module/foo.cpp можно спокойно перемещать, потому что// он использует не относительный путь, а отсчитываемый от корня.Ок, значит чисто технически никаких проблем нет, и вы это признаете.
А проблемы, которые появятся при разрастании этой конкретной библиотеки можно решать по мере их поступления
Внутренние заголовки, тот же version.h например, используются только при сборке либы и наружу не отдаются.
Причем эта система сборки совершенно не связана с той системой, которая собирает приложение, например нет «утечки» include-path.
Подавляющему же числу библиотек достаточно примитивной плоской структуры вида libName/libName.h, где дополнительные публичные заголовочные файлы живут в той же папке libName/.
#include "header.h", а #include "libName/header.h". Но это не только на пользовательской стороне; так же требуется, чтобы этого соглашения придерживался автор библиотеки.Как бы хорошо ссылаться на буст, но надо понимать, что это нетипичный пример.
Между прочим все более-менее серьезные библиотеки собираются и устанавливаются и только потом их используют.
Далее бинарники и публичные заголовки либо устанавливаются в регламентированные локации на файловой системе, либо вручную тащатся в папку проекта.
Так я об этом и говорю. Только в include path должна включаться не папка libName/, а её родитель. Чтобы использование было не #include «header.h», а #include «libName/header.h». Но это не только на пользовательской стороне; так же требуется, чтобы этого соглашения придерживался автор библиотеки.
ИМХО практика писать чистый, поддерживаемый и расширяемый код, весь из себя ООП по канонам банды четырех — сильно переоценивается… только имеет смысл исключительно для больших проектов...
И кстати идиотский лейаут это не так страшно.
$(Qbit_ExtInclude)chineselib-1.2.3/include/ (там лежит единственная папка chineselib), а везде в коде писать явно #include "chineselib/magicheader.h" вместо просто #include "magicheader.h"Не знаю ни одной широкоизвестной библиотеки
Я согласен со всем что вы написали про библиотеки. Но сравнивать это с тем что делал я это так же, как говорить данный проект идет ортогонально C# идеологии — абсолютно верно, но бессмысленно.
Начну с того что я не предоставляю библиотеку. Это даже близко на нее не похоже и цели такой тоже не было. На этом пожалуй и закончу :)
то проект будет в виде библиотека + тонкий runner с точкой входа,
Если речь не о промышленной разработке,
Который должен уметь почти все что выше описанный проект :)
Любая разработка начинается с чего то. Это один из вариантов с чего я начинаю.
Правда в этом случае папка include/ избыточна.
В библиотеках приватные (чисто технические, не торчащие наружу) заголовки по возможности лучше прятать в src/
А как этот шаблон продолжать наполнять «мясом», то есть библиотеками, содержащими фактический код, а не инфраструктурную обвязку?
main(){
OtherLib.ResolveMyProblem();
}
Но вот идея про то, что в include должны быть публичные хедеры заставляет задуматься.
Но я не люблю *.h и *.cpp файлы держать в перемешку.
Вам рассказывать как программировать?
void exit_sig_handler(int sig)
{
Mediator::exit();
}
void Mediator::exit()
{
LOG("set exit");
{
boost::lock_guard<boost::mutex> lock(exit_mtx_);
exit_ = true;
}
exit_cv_.notify_one();
}
1. Лицензия, GPL3. Для многих будет неприемлимо.
2. Сигналы — демоны должны обрабатывать SIGTERM (остановка) и SIGHUP (обновление конфигурации).
3. Использование ревизии из svn для версионирования — плохое решение. Как минимум тем, что привязывает к svn.Для, для GIT это подойдет. И я не знаю как сделать автоверсионирование для GIT. Без него не хочу.
4. «Сборку дистрибутива» — ваш package.sh — умеет делать CMake.
5. Задание имени pid-файла через опцию командной строки я считаю излишним. у всех всегда пути жестко вкомпилированы, то же самое относится и к логам. При необходимости пути должны настраиваться во время конфигурирования, перед сборкой.Я с вами не согласен. И я в статье явно написал, что одно из требований это возможность запуска нескольких инстансов на одном сервере.
6. Если это демон, то почему не проиходит демонизации (создание новой сессии, отказ от управляющего терминала и тд.)? Имеет смысл сделать поддержку upstart (Linux), launchd (MacOS) и scm (Windows).
Это не демон. По сути это просто консольное приложение которое в случае необходимости можно отправить в background. Главное что бы логирование было в файл а не в консоль. Возможность сделать его демоном, интересная, но пока не было нужды.
Как бы вы сформулировали цели своего проекта, решаемые задачи и для кого он?Быстро начать писать прототип. Очень часто прототипы перерастают в рабочие проекты. В первую очередь для меня. Во вторую, для тех кто найдет его структуру полезной для себя. Это не ключ от всех дверей. Это не Boost.
Лицензия — Apache, BSD или MIT.
Пофиксить обработчик сигналов, с сохранением текущей семантики, можно при помощи pipe. (В обработчике писать кусок данных в пайп, ждать завершения при помощи чтения. Можно заменить на signalfd в новых линуксах. Или тупо sigsuspend в выделенном потоке.)
Быстро начать писать прототип. Очень часто прототипы перерастают в рабочие проекты. В первую очередь для меня. Во вторую, для тех кто найдет его структуру полезной для себя.
Pipe это еще сложнее чем сеть. Работать с ними легко, работать правильно и отказоустойчивость сложно. К примеру если создать Pipe, повиснуть в блокирующем чтении, а потом снаружи удалить файл Pipe — ничего не случится.
Быстро начать писать прототип. Очень часто прототипы перерастают в рабочие проекты
Извините, это полнейшее порно. Вот так у вас выглядит обработчик сигналов:
src/mediator.cpp
Проект доступен в Google Code, но только для read-only. Это не потому что я жадный, я просто не знаю как открыть доступ для всех.
При желании вносить правки, пишите ваш g-email, добавлю вас к проекту.
Проект NULL