У меня немного больше, чем навыки C на начальном уровне, и я хотел бы знать, существуют ли какие-либо де-факто «стандарты» для структурирования довольно сложных приложений на C. Даже на основе графического интерфейса пользователя.
Я всегда использовал парадигму объектно-ориентированного программирования в Java и PHP, и теперь, когда я хочу изучить C, я боюсь, что могу неправильно структурировать свои приложения. Я не понимаю, каким руководящим принципам следовать, чтобы иметь модульность, разделение и сухость с процедурным языком.
Есть ли у вас какие-нибудь чтения? Я не смог найти ни одной прикладной платформы для C, даже если я не использую фреймворки, я всегда находил хорошие идеи, просматривая их код.
c
project-management
Стивен
источник
источник
Ответы:
Ключ - модульность. Это проще спроектировать, реализовать, скомпилировать и поддерживать.
Если у вас есть время на обучение, посмотрите, как структурировано приложение Ada, с его обязательными
package
(интерфейс модуля) иpackage body
(реализация модуля).Это для кодирования.
Для поддержки (помните, что вы кодируете один раз, но поддерживаете несколько раз) я предлагаю задокументировать ваш код; Doxygen - хороший выбор для меня. Я также предлагаю создать надежный набор регрессионных тестов, который позволит вам провести рефакторинг.
источник
Распространено заблуждение, что методы объектно-ориентированного программирования не могут быть применены в C. Большинство может - просто они немного более громоздки, чем в языках с синтаксисом, предназначенным для работы.
Одна из основ проектирования надежной системы - это инкапсуляция реализации за интерфейсом.
FILE*
и функции, которые с ним работают (fopen()
иfread()
т. д.), являются хорошим примером того, как инкапсуляция может применяться в C для создания интерфейсов. (Конечно, поскольку C не имеет спецификаторов доступа, вы не можете обеспечить, чтобы никто не заглядывал внутрь astruct FILE
, но только мазохист мог бы это сделать.)При необходимости полиморфное поведение может быть реализовано в C с использованием таблиц указателей на функции. Да, синтаксис уродливый, но эффект такой же, как у виртуальных функций:
struct IAnimal { int (*eat)(int food); int (*sleep)(int secs); }; /* "Subclass"/"implement" IAnimal, relying on C's guaranteed equivalence * of memory layouts */ struct Cat { struct IAnimal _base; int (*meow)(void); }; int cat_eat(int food) { ... } int cat_sleep(int secs) { ... } int cat_meow(void) { ... } /* "Constructor" */ struct Cat* CreateACat(void) { struct Cat* x = (Cat*) malloc(sizeof (struct Cat)); x->_base.eat = cat_eat; x->_base.sleep = cat_sleep; x->meow = cat_meow; } struct IAnimal* pa = CreateACat(); pa->eat(42); /* Calls cat_eat() */ ((struct Cat*) pa)->meow(); /* "Downcast" */
источник
Все хорошие ответы.
Я бы только добавил «минимизировать структуру данных». Это может быть даже проще в C, потому что если C ++ - это «C с классами», ООП пытается побудить вас взять каждое существительное / глагол в своей голове и превратить его в класс / метод. Это может быть очень расточительным.
Например, предположим, что у вас есть массив значений температуры в определенные моменты времени, и вы хотите отобразить их в виде линейной диаграммы в Windows. В Windows есть сообщение PAINT, и когда вы его получите, вы можете в цикле пройти по массиву, выполняя функции LineTo, масштабируя данные по мере продвижения, чтобы преобразовать их в координаты пикселей.
Что я видел слишком много раз, так это то, что поскольку диаграмма состоит из точек и линий, люди будут создавать структуру данных, состоящую из точечных объектов и линейных объектов, каждый из которых может выполнять DrawMyself, а затем сделать это постоянным, исходя из теории, что эта каким-то образом «более эффективен», или что им, возможно, придется иметь возможность наводить указатель мыши на части диаграммы и отображать данные в числовом виде, поэтому они встраивают методы в объекты, чтобы справиться с этим, и это, конечно, включает создание и удаление еще большего количества объектов.
Таким образом, вы получаете огромное количество кода, который настолько удобочитаем, что просто тратит 90% своего времени на управление объектами.
Все это делается во имя «хорошей практики программирования» и «эффективности».
По крайней мере, в C простой и эффективный способ будет более очевидным, а искушение построить пирамиды менее сильным.
источник
В кодирования GNU стандарты развивались в течение нескольких десятилетий. Было бы неплохо их прочитать, даже если вы не следуете им в точности. Обдумывание поднятых в них вопросов дает вам более прочную основу для структурирования собственного кода.
источник
Если вы знаете, как структурировать свой код на Java или C ++, вы можете следовать тем же принципам с кодом C. Единственное отличие состоит в том, что у вас нет компилятора и вам нужно делать все вручную вручную.
Поскольку пакетов и классов нет, вам нужно начать с тщательной разработки модулей. Наиболее распространенный подход - создать отдельную исходную папку для каждого модуля. Вам нужно полагаться на соглашения об именах, чтобы различать код между разными модулями. Например, префикс всех функций с именем модуля.
У вас не может быть классов с C, но вы можете легко реализовать «абстрактные типы данных». Вы создаете файлы .C и .H для каждого абстрактного типа данных. Если вы предпочитаете, у вас может быть два файла заголовков, один публичный и один частный. Идея состоит в том, что все структуры, константы и функции, которые необходимо экспортировать, попадают в общедоступный файл заголовка.
Ваши инструменты тоже очень важны. Полезным инструментом для C является lint , который может помочь вам найти неприятный запах в вашем коде. Еще один инструмент, который вы можете использовать, - это Doxygen, который может помочь вам в создании документации .
источник
Инкапсуляция всегда является ключом к успешной разработке, независимо от языка разработки.
Уловка, которую я использовал для инкапсуляции «частных» методов в C, заключается в том, чтобы не включать их прототипы в файл «.h».
источник
Я предлагаю вам ознакомиться с кодом любого популярного проекта C с открытым исходным кодом, например ... хм ... ядра Linux или Git; и посмотрите, как они это организуют.
источник
Правило числа для сложных приложений: оно должно быть легко читаемым.
Чтобы упростить сложное приложение, я использую « Разделяй и властвуй» .
источник
Я бы посоветовал в качестве первого шага прочитать учебник C / C ++. Например, C Primer Plus - хороший пример. Просмотр примеров даст вам представление о том, как сопоставить ваш объектно-ориентированный объект Java с более процедурным языком, таким как C.
источник