Імена конвенцій, що використовуються для змінних та функцій у C [closed]


13

Під час кодування великого проекту в CI виникла проблема. Якщо я продовжую писати більше коду, тоді настане час, коли мені буде складно організувати код. Я маю на увазі, що імена для функцій та змінних для різних частин програми можуть здатися змішаними.

Тому я думав, чи є корисні умови іменування, які я можу використовувати для змінних та функцій C?

Більшість мов пропонує угоду про іменування. Але для C єдине, що я читав до цих пір, - це назви, які повинні бути описовими для читабельності коду.

Редагувати:

Приклади деяких прикладів запропонованих конвенцій про іменування:

Я десь прочитав ще кілька умовних імен для Java, але не міг згадати, де.


Наведіть кілька прикладів мов із запропонованими умовами іменування. І там, де ми можемо знайти ці умовні імена.
Філіп

@Philip Додав приклади
Aseem Bansal

1
Не повинно виникнути проблем зі змінними, оскільки ви не використовуєте глобали. А для імен функцій: якщо ім'я модуля є order.c, ви могли б назвати функції order_add(), order_del()і тому подібне. Можливо, існують старі системи, які говорять про те, що ім'я повинно бути унікальним протягом перших 8 символів. Якщо пізніше випадково перейдете на c ++, ви любите писати order::add()і order::del()потім.
ott--

Відповіді:


17

Якщо я продовжую писати більше коду, тоді настане час, коли мені буде складно організувати код.

У цьому ваша проблема: виправте організацію, і стиль повинен протікати легше.

Не чекайте, щоб упорядкувати свій код: тримайте код впорядкованому під час руху. Хоча мова це не робить для вас, код все одно повинен бути організований в модулі з низькою сполученістю і високою згуртованістю.

Ці модулі, природно, забезпечують простір імен. Скоротіть назву модуля (якщо він довгий) та вкажіть назви функцій префікса їх модулем, щоб уникнути зіткнень.

На рівні індивідуальних ідентифікаторів вони приблизно в порядку зростання суб'єктивності:

  1. виберіть умову і дотримуйтесь її
    • наприклад, function_like_this(struct TypeLikeThis variable)є загальним
  2. обов'язково уникайте угорських позначень (вибачте JNL)

    • якщо ви не бажаєте використовувати його як було призначено спочатку, це означає позначення додатків Сімоні, а не жахливу версію системи

      Чому? Я можу написати про це есе, але замість цього запропоную вам прочитати цю статтю Джоела Спольського, а потім полюйте ще трохи, якщо вам цікаво. Внизу є посилання на оригінальний папір Сімоні.

  3. уникайте типів покажчиків, якщо вони не є справді непрозорими типами файлів cookie - вони лише плутають речі

    struct Type *ok;
    typedef struct Type *TypePtr;
    TypePtr yuck;

    Що я маю на увазі під непрозорим типом cookie ? Я маю на увазі щось, що використовується у модулі (або бібліотеці чи будь-якому іншому), що має бути передано коду клієнта, але цей клієнтський код не може використовуватись безпосередньо. Він просто передає його назад до бібліотеки.

    Наприклад, бібліотека баз даних може відкрити подібний інтерфейс

    /* Lots of buffering, IPC and metadata magic held in here.
       No, you don't get to look inside. */
    struct DBContextT;
    /* In fact, you only ever get a pointer, so let's give it a nice name */
    typedef struct DBContexT *DBContext;
    
    DBContext db_allocate_context(/*maybe some optional flags?*/);
    void db_release_context(DBContext);
    int db_connect(DBContext, const char *connect);
    int db_disconnect(DBContext);
    int db_execute(DBContext, const char *sql);

    Тепер контекст непрозорий для клієнтського коду, тому що ви не можете заглянути всередину. Ви просто передаєте його назад до бібліотеки. Щось подібне FILEтакож є непрозорим, і дескриптор цілого файлу також є файлом cookie , але не є непрозорим.


Примітка про дизайн

Я використовував вище фразу " низька зв'язок" і "висока згуртованість" , і мені це дуже погано. Ви можете шукати його і, ймовірно, знайти якісь хороші результати, але я спробую коротко розглянути його (знову ж, я можу написати твір, але намагаюся цього не робити).

Бібліотека БД, накреслена вище, демонструє низьке з'єднання, оскільки вона відкриває невеликий інтерфейс для зовнішнього світу. Приховуючи дані про його реалізацію (частково з непрозорим фокусом cookie), вона не дозволяє коду клієнта залежати від цих деталей.

Уявіть, що замість непрозорого файлу cookie ми оголосимо структуру контексту, щоб її вміст був видно, і він включає дескриптор файлу сокета для підключення TCP до бази даних. Якщо ми згодом змінимо реалізацію на підтримку використання сегмента спільної пам’яті, коли БД працює на одній машині, клієнт повинен бути перекомпільований, а не просто повторний зв’язок. Ще гірше, що клієнт міг почати використовувати дескриптор файлів, наприклад, закликаючи setsockoptзмінити розмір буфера за замовчуванням, і тепер він також потребує зміни коду. Усі ці деталі повинні бути заховані всередині нашого модуля, де це практично, і це забезпечує низьке з'єднання між модулями.

Приклад також показує високу згуртованість , оскільки всі методи в модулі стосуються одного завдання (доступ до БД). Це означає, що лише код, який потрібно знати про деталі реалізації (тобто вміст нашого файлу cookie), насправді має доступ до них, що спрощує налагодження.

Ви також можете бачити, що, маючи одну проблему, було легко вибрати префікс, щоб згрупувати ці функції разом.

Тепер сказати, що цей приклад хороший - це легко (тим більше, що він навіть не є повним), але не одразу вам допомагає. Трюк полягає в тому, щоб спостерігати за тим, як ви пишете та розширюєте свій код, на функції, які роблять подібні речі або працюють на тих же типах (які можуть бути кандидатами для власного модуля), а також на функції, які роблять багато окремих речей, які не є ' t по-справжньому пов'язані і можуть бути кандидатами на розкол.


Чи можете ви допомогти мені зрозуміти, чому уникають угорської мови? Просто цікаво дізнатися більше про це. :)
JNL

@JNL: коментар занадто короткий, щоб правильно пояснити. Я пропоную вам поставити це як нове запитання.
Барт ван Іґен Шенау

with low coupling and high cohesion. Що це означає? І поясніть, будь ласка, про непрозорі типи печива. Я поняття не маю, що це означає.
Асеем Бансал

Я намагався виступити як коротко, так і відверто провалився в стислість. Будемо сподіватися, що це повинно вам почати.
Марно

Я відповідаю через кілька днів. Вибачте за це. Я читаю ваш опис low coupling and high cohesion. Отже, це в основному означає інкапсулювати речі, коли я можу, і це слід робити так, щоб функції, які насправді потребували, мали доступ. Деякі речі перейшли через мою голову, але все ж я думаю, що я зрозумів вашу думку.
Асеем Бансал

5

На мою думку, 90% проблеми з іменем вирішується, якщо мати на увазі три речі: а) зробити свою назву змінної та функції максимально описовою, б) бути узгодженою у всьому коді (тобто, якщо функція названа addNumbers, a друга функція повинна бути названа multiplyNumbers, а не numberMul) і c) спробуйте зробити імена короткими, якщо це можливо, як нам потрібно їх набрати.

Однак, якщо ви хочете ознайомитись з іншими аспектами цієї теми, на сторінці Вікіпедії, присвяченій іменуванню конвенцій , є хороший перелік речей, про які слід пам’ятати. Він також має розділ на C і C ++:

У C і C ++ ключові слова та стандартні ідентифікатори бібліотеки є здебільшого малими літерами. У стандартній бібліотеці С найчастішими є скорочені імена (наприклад, isalnum для функції, що перевіряє, чи є символ буквено-цифровим), тоді як у стандартній бібліотеці C ++ часто використовується підкреслення як роздільник слів (наприклад, out_of_range). Ідентифікатори, що представляють макроси, звичайно записуються, використовуючи лише великі літери та підкреслення (це пов'язано з умовою в багатьох мовах програмування використання ідентифікаторів верхнього регістру для констант). Імена, що містять подвійне підкреслення або починаються з підкреслення і великої літери, зарезервовані для реалізації (компілятор, стандартна бібліотека) і не повинні використовуватися (наприклад, зарезервовано__ або _Зарезервовано). [5] [6] Це поверхово схоже на штрихування, але семантика відрізняється:


3
"спробуйте зробити імена короткими, якщо можливо" Використовуйте IDE з автоматичним завершенням, тоді імена ваших функцій можуть бути настільки ж довгими та описовими, як вони повинні бути такими, як вам потрібно ввести лише один раз.
Джоель

1
@Joel жахлива порада. Не кожен буде використовувати той самий IDE, як ви.
Джеймс

6
@James Їм не потрібно, вони можуть просто використовувати будь-який гідний IDE. Тоді не потрібно жертвувати ясністю для продуктивності.
Джоель

Термін IDE розтягується трохи тонкими днями. Технічно Notepad ++ - це IDE, тому що ви можете налаштувати його для компіляції та запуску проекту, але це в першу чергу текстовий редактор. І воно автоматично завершується.
Філіп

5

Єдиним важким обмеженням у C є те, що немає просторів імен. Таким чином, ви повинні знайти спосіб , щоб зробити rename()функцію вашої файлової бібліотеки відрізняється від rename()функції вашої медіа - бібліотеки. Звичайним рішенням є префікс, наприклад: filesystem_rename()і media_rename().

Інша загальна порада: залишайтеся послідовними в рамках проекту чи команди. Читання буде покращено.


+1: Це особливо стосується експортованих символів у бібліотеці. "Мені шкода, але ця бібліотека файлових систем не йде з цією медіатекою, тому що обидва мають експортовану функцію перейменування.
Residuum

2

ЯКЩО ВИ ШУКАЄТЕ ГЛОБОЛЬНО ПРИЙМАНИЙ ФОРМАТ

MISRA / JSF / AUTOSAR охоплює майже 100% усіх галузевих стандартів для іменування та організації коду C / C ++. Проблема полягає в тому, що вони не зможуть безкоштовно дістатися, тобто кожен з путівників коштує певних грошей. Я знаю, що стандартна книга кодування MISRA 2008 C / C ++, ймовірно, коштує близько 50 доларів.

Ви можете думати про це як Гарвардську довідку щодо бібліографії та читання додатків, коли пишете журнал. Я використовував MISRA, і це хороший спосіб назвати ваші функції та змінні та організувати їх для правильного використання.

ЯКЩО ВИ ГОТУЙТЕ ЯКЩО ТОМУ ТОМОВОМ

Я думаю, посилання, які ви надали для Python та Java, добре. Я бачив, як люди приймають стиль javadoc, коментуючи, називаючи та впорядковуючи код. Власне кажучи, в останньому проекті мені довелося записати код C ++ у Java-подібних функціях / назвах змінних. Дві причини цього:

1) Це було, мабуть, простіше.

2) Вимоги до виробничого коду не торкнулися основи критично важливих для безпеки програмних систем.

3) Спадковий код був (якось) у тому форматі.

4) Доксиген дозволив Javadoc багато коментувати. У той момент ми використовували доксиген для створення документації для виробничих хлопців.

Багато програмістів будуть противником цього, але я особисто зауважую, що немає нічого поганого у прийнятті функції / назви змінної стилю javadoc у C / C ++. ТАК КУРС, практику організації управління потоком, безпеку різьблення тощо потрібно вирішувати незалежно. Однак я тут не заявник. Я також не знаю, наскільки суворі вимоги до вашого формату виробничого коду. Не перенаправляючи його на поза тему, я пропоную вам переглянути свої вимоги, дізнатися, наскільки ви залежали від конкретної конвенції про іменування, і перейдіть до рішення, зазначеного в моїх та інших відповідях.

Сподіваюся, це допомогло !?


Насправді я просив це особисті коди С. Але я запам’ятаю вашу пропозицію.
Асеем Бансал

@AseemBansal Особистий чи професійний, вони добре навчатись, а також добре додати своє резюме :) .... До вас.
hagubear

0

Мало важливих речей, які слід враховувати під час називання;

  1. Подивіться на тип actionObject або ObjectAction (об’єкт не для C. Але загалом, коли ви переходите до інших мов, орієнтованих на об'єкти). Це повинно допомогти

  2. Відпочинок буде БЕЗПЕЧНИМ, напевно коротким та описовим.

  3. Крім того, мати єдину мету кожної змінної та визначеної функції, наприклад: Якщо вона зберігає значення тимчасово, назвіть його як nTempVal для int
  4. Змінні мають бути іменниками, а Методи - дієсловом.

6
Угорська позначення (префіксація змінної літерами, що позначають тип) не призводить до болю. На щастя, це здебільшого вийшло з моди.
Gort the Robot

@StevenBurnap Було просто цікаво, чому уникнути угорського формату? Я вважаю, що цього вони навчали нас у школі, і я бачив такий код і на деяких робочих місцях. Який би ти не рекомендував, якщо не угорський. Спасибі
JNL

1
Найкраща конвенція про іменування - це лише одна послідовно використана, чіткі, описові назви в ідеалі зберігаються відносно короткими без зайвої абревіатури та уникають зайвих префіксів. Угорська нотація має малу фактичну корисність, робить код важче читати та ускладнює зміну типів.
Gort the Robot

2
Ось опис первісного наміру та гидоти, якою стала угорська нотація: joelonsoftware.com/articles/Wrong.html
Residuum

@Residuum Це було гарне посилання. Допомагав багато. Оцініть це.
JNL

0

Більшість відповідей хороші, але я хочу сказати кілька речей про іменування конвенцій для бібліотек та включених файлів, аналогічно використанню просторів імен іншими мовами, такими як C ++ або Java:

Якщо ви створюєте бібліотеку, знайдіть загальний префікс для експортованих символів, тобто глобальних функцій, typedefs та змінних. Це запобіжить зіткнення з іншими бібліотеками та визначить функції, що надходять із ваших. Це трохи додатків угорських позначень.

Можливо, ще більше і згрупуйте експортовані символи: libcurl використовує curl_ * для глобальних символів, curl_easy_ *, curl_multi_ * та curl_share_ * для різних інтерфейсів. Отже, крім використання curl_ * для всіх функцій, вони додали ще один рівень «просторів імен» для різних інтерфейсів: виклик функції curl_easy_ * на ручку curl_multi_ * тепер виглядає неправильно, див. Назви функцій за адресою http: // curl. haxx.se/libcurl/c/

Зберігаючи правила експортованих символів, слід використовувати правила для статичних функцій у #includeфайлах ed: Спробуйте знайти загальний префікс для цих функцій. Можливо, у вас є функції утиліти статичних рядків у файлі під назвою "my_string"? Префікс усіх цих функцій за допомогою my_string_ *.


Під експортованими символами ви маєте на увазі глобальні змінні, функції, typedefs тощо, якщо я правильно. Чи можете ви пояснити біт щодо групування експортованих символів? Я думав, ти вже це пояснив у попередньому абзаці. Що ви додали у 3-му пункті?
Асеем Бансал
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.