mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-18 05:32:52 +00:00
cd14f9ebcb
* split up select.md * array-join.md basic refactoring * distinct.md basic refactoring * format.md basic refactoring * from.md basic refactoring * group-by.md basic refactoring * having.md basic refactoring * additional index.md refactoring * into-outfile.md basic refactoring * join.md basic refactoring * limit.md basic refactoring * limit-by.md basic refactoring * order-by.md basic refactoring * prewhere.md basic refactoring * adjust operators/index.md links * adjust sample.md links * adjust more links * adjust operatots links * fix some links * adjust aggregate function article titles * basic refactor of remaining select clauses * absolute paths in make_links.sh * run make_links.sh * remove old select.md locations * translate docs/es * translate docs/fr * translate docs/fa * remove old operators.md location * change operators.md links * adjust links in docs/es * adjust links in docs/es * minor texts adjustments * wip * update machine translations to use new links * fix changelog * es build fixes * get rid of some select.md links * temporary adjust ru links * temporary adjust more ru links * improve curly brace handling * adjust ru as well * fa build fix * ru link fixes * zh link fixes * temporary disable part of anchor checks
843 lines
36 KiB
Markdown
843 lines
36 KiB
Markdown
---
|
||
machine_translated: true
|
||
machine_translated_rev: 72537a2d527c63c07aa5d2361a8829f3895cf2bd
|
||
toc_priority: 68
|
||
toc_title: "\u0686\u06AF\u0648\u0646\u0647 \u0628\u0631\u0627\u06CC \u0646\u0648\u0634\
|
||
\u062A\u0646 \u062C++ \u06A9\u062F"
|
||
---
|
||
|
||
# چگونه برای نوشتن ج++ کد {#how-to-write-c-code}
|
||
|
||
## توصیه های عمومی {#general-recommendations}
|
||
|
||
**1.** در زیر توصیه, مورد نیاز نیست.
|
||
|
||
**2.** اگر شما در حال ویرایش کد, این را حس می کند به دنبال قالب بندی کد های موجود.
|
||
|
||
**3.** سبک کد برای سازگاری مورد نیاز است. سازگاری خواندن کد را ساده تر می کند و همچنین باعث می شود که کد را جستجو کنید.
|
||
|
||
**4.** بسیاری از قوانین دلایل منطقی ندارند; دیکته شده توسط شیوه های تاسیس شده است.
|
||
|
||
## قالببندی {#formatting}
|
||
|
||
**1.** بسیاری از قالب بندی به صورت خودکار انجام می شود `clang-format`.
|
||
|
||
**2.** فرورفتگی فضاهای 4 هستند. پیکربندی محیط توسعه خود را به طوری که یک تب اضافه می کند چهار فضا.
|
||
|
||
**3.** باز و بسته شدن براکت فرفری باید در یک خط جداگانه باشد.
|
||
|
||
``` cpp
|
||
inline void readBoolText(bool & x, ReadBuffer & buf)
|
||
{
|
||
char tmp = '0';
|
||
readChar(tmp, buf);
|
||
x = tmp != '0';
|
||
}
|
||
```
|
||
|
||
**4.** اگر کل بدن تابع یک است `statement`, این را می توان در یک خط قرار داده شده. فضاهای محل در اطراف پرانتز فرفری (علاوه بر فضای در پایان خط).
|
||
|
||
``` cpp
|
||
inline size_t mask() const { return buf_size() - 1; }
|
||
inline size_t place(HashValue x) const { return x & mask(); }
|
||
```
|
||
|
||
**5.** برای توابع. فضاهای اطراف براکت قرار ندهید.
|
||
|
||
``` cpp
|
||
void reinsert(const Value & x)
|
||
```
|
||
|
||
``` cpp
|
||
memcpy(&buf[place_value], &x, sizeof(x));
|
||
```
|
||
|
||
**6.** داخل `if`, `for`, `while` و عبارت دیگر, یک فضای در مقابل براکت باز قرار داده(به عنوان مخالف به عملکرد تماس).
|
||
|
||
``` cpp
|
||
for (size_t i = 0; i < rows; i += storage.index_granularity)
|
||
```
|
||
|
||
**7.** اضافه کردن فضاهای اطراف اپراتورهای دودویی (`+`, `-`, `*`, `/`, `%`, …) and the ternary operator `?:`.
|
||
|
||
``` cpp
|
||
UInt16 year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
|
||
UInt8 month = (s[5] - '0') * 10 + (s[6] - '0');
|
||
UInt8 day = (s[8] - '0') * 10 + (s[9] - '0');
|
||
```
|
||
|
||
**8.** اگر یک خوراک خط وارد شده است, قرار دادن اپراتور در یک خط جدید و افزایش تورفتگی قبل از.
|
||
|
||
``` cpp
|
||
if (elapsed_ns)
|
||
message << " ("
|
||
<< rows_read_on_server * 1000000000 / elapsed_ns << " rows/s., "
|
||
<< bytes_read_on_server * 1000.0 / elapsed_ns << " MB/s.) ";
|
||
```
|
||
|
||
**9.** شما می توانید فضاهای برای هم ترازی در یک خط استفاده, در صورت دلخواه.
|
||
|
||
``` cpp
|
||
dst.ClickLogID = click.LogID;
|
||
dst.ClickEventID = click.EventID;
|
||
dst.ClickGoodEvent = click.GoodEvent;
|
||
```
|
||
|
||
**10.** از فضاهای اطراف اپراتورها استفاده نکنید `.`, `->`.
|
||
|
||
در صورت لزوم اپراتور می تواند به خط بعدی پیچیده شود. در این مورد جبران در مقابل افزایش می یابد.
|
||
|
||
**11.** از فضا برای جدا کردن اپراتورهای غیر ضروری استفاده نکنید (`--`, `++`, `*`, `&`, …) from the argument.
|
||
|
||
**12.** بعد از ویرگول فاصله بگیر ولی نه قبل از اون همین قاعده برای یک نقطه و ویرگول در داخل یک `for` اصطلاح.
|
||
|
||
**13.** از فضاها برای جدا کردن استفاده نکنید `[]` اپراتور
|
||
|
||
**14.** در یک `template <...>` عبارت, استفاده از یک فضای بین `template` و `<`; بدون فاصله پس از `<` یا قبل از `>`.
|
||
|
||
``` cpp
|
||
template <typename TKey, typename TValue>
|
||
struct AggregatedStatElement
|
||
{}
|
||
```
|
||
|
||
**15.** در کلاس ها و سازه, نوشتن `public`, `private` و `protected` در همان سطح به عنوان `class/struct`, و تورفتگی بقیه کد.
|
||
|
||
``` cpp
|
||
template <typename T>
|
||
class MultiVersion
|
||
{
|
||
public:
|
||
/// Version of object for usage. shared_ptr manage lifetime of version.
|
||
using Version = std::shared_ptr<const T>;
|
||
...
|
||
}
|
||
```
|
||
|
||
**16.** اگر همان `namespace` برای کل فایل استفاده می شود, و هر چیز دیگری قابل توجهی وجود ندارد, افست در داخل لازم نیست `namespace`.
|
||
|
||
**17.** اگر بلوک برای `if`, `for`, `while`, یا عبارت دیگر متشکل از یک `statement`, براکت فرفری اختیاری هستند. محل `statement` در یک خط جداگانه, در عوض. این قانون نیز برای تو در تو معتبر `if`, `for`, `while`, …
|
||
|
||
اما اگر درونی `statement` شامل براکت های فرفری یا `else` بلوک خارجی باید در براکت های فرفری نوشته شود.
|
||
|
||
``` cpp
|
||
/// Finish write.
|
||
for (auto & stream : streams)
|
||
stream.second->finalize();
|
||
```
|
||
|
||
**18.** نباید در انتهای خطوط هیچ فضایی وجود داشته باشد.
|
||
|
||
**19.** فایل های منبع هستند وزارت مخابرات 8 کد گذاری.
|
||
|
||
**20.** شخصیت های غیر ASCII استفاده می شود string literals.
|
||
|
||
``` cpp
|
||
<< ", " << (timer.elapsed() / chunks_stats.hits) << " μsec/hit.";
|
||
```
|
||
|
||
**21.** هنوز عبارات متعدد در یک خط ارسال نمی.
|
||
|
||
**22.** بخش های گروهی کد در داخل توابع و با بیش از یک خط خالی جدا می شوند.
|
||
|
||
**23.** توابع جداگانه, کلاس, و به همین ترتیب با یک یا دو خط خالی.
|
||
|
||
**24.** `A const` (مربوط به ارزش) باید قبل از نام نوع نوشته شده است.
|
||
|
||
``` cpp
|
||
//correct
|
||
const char * pos
|
||
const std::string & s
|
||
//incorrect
|
||
char const * pos
|
||
```
|
||
|
||
**25.** هنگام اعلام اشاره گر یا مرجع `*` و `&` نمادها باید با فاصله در هر دو طرف از هم جدا.
|
||
|
||
``` cpp
|
||
//correct
|
||
const char * pos
|
||
//incorrect
|
||
const char* pos
|
||
const char *pos
|
||
```
|
||
|
||
**26.** هنگام استفاده از انواع قالب ها با نام مستعار `using` کلمه کلیدی (به جز در ساده ترین موارد).
|
||
|
||
به عبارت دیگر پارامترهای قالب فقط در `using` و در کد تکرار نمی شود.
|
||
|
||
`using` می توان به صورت محلی اعلام کرد, مانند داخل یک تابع.
|
||
|
||
``` cpp
|
||
//correct
|
||
using FileStreams = std::map<std::string, std::shared_ptr<Stream>>;
|
||
FileStreams streams;
|
||
//incorrect
|
||
std::map<std::string, std::shared_ptr<Stream>> streams;
|
||
```
|
||
|
||
**27.** هنوز متغیرهای مختلفی از انواع مختلف در یک بیانیه اعلام نمی.
|
||
|
||
``` cpp
|
||
//incorrect
|
||
int x, *y;
|
||
```
|
||
|
||
**28.** هنوز کست ج سبک استفاده نمی.
|
||
|
||
``` cpp
|
||
//incorrect
|
||
std::cerr << (int)c <<; std::endl;
|
||
//correct
|
||
std::cerr << static_cast<int>(c) << std::endl;
|
||
```
|
||
|
||
**29.** در کلاس ها و ساختار, اعضای گروه و توابع به طور جداگانه در داخل هر دامنه دید.
|
||
|
||
**30.** برای کلاس های کوچک و structs آن است که لازم نیست برای جدا کردن روش بیانیه از اجرای.
|
||
|
||
همان درست است برای روش های کوچک در هر کلاس و یا ساختار است.
|
||
|
||
برای templated کلاس و structs نیست جداگانه روش اعلامیه از اجرای (زیرا در غیر این صورت آنها باید تعریف شده در ترجمه همان واحد).
|
||
|
||
**31.** شما می توانید خطوط در بسته بندی 140 شخصیت, بجای 80.
|
||
|
||
**32.** همیشه پیشوند اپراتورهای افزایش/کاهش استفاده کنید اگر پسوند مورد نیاز نمی باشد.
|
||
|
||
``` cpp
|
||
for (Names::const_iterator it = column_names.begin(); it != column_names.end(); ++it)
|
||
```
|
||
|
||
## توضیحات {#comments}
|
||
|
||
**1.** حتما برای اضافه کردن نظر برای تمام بخش های غیر بدیهی از کد.
|
||
|
||
این بسیار مهم است. نوشتن نظر ممکن است به شما کمک کند متوجه شوید که کد لازم نیست یا اشتباه طراحی شده است.
|
||
|
||
``` cpp
|
||
/** Part of piece of memory, that can be used.
|
||
* For example, if internal_buffer is 1MB, and there was only 10 bytes loaded to buffer from file for reading,
|
||
* then working_buffer will have size of only 10 bytes
|
||
* (working_buffer.end() will point to position right after those 10 bytes available for read).
|
||
*/
|
||
```
|
||
|
||
**2.** نظرات می تواند به عنوان دقیق که لازم است.
|
||
|
||
**3.** محل نظرات قبل از کد توصیف می کنند. در موارد نادر, نظرات می تواند پس از کد است, در همان خط.
|
||
|
||
``` cpp
|
||
/** Parses and executes the query.
|
||
*/
|
||
void executeQuery(
|
||
ReadBuffer & istr, /// Where to read the query from (and data for INSERT, if applicable)
|
||
WriteBuffer & ostr, /// Where to write the result
|
||
Context & context, /// DB, tables, data types, engines, functions, aggregate functions...
|
||
BlockInputStreamPtr & query_plan, /// Here could be written the description on how query was executed
|
||
QueryProcessingStage::Enum stage = QueryProcessingStage::Complete /// Up to which stage process the SELECT query
|
||
)
|
||
```
|
||
|
||
**4.** نظرات فقط باید به زبان انگلیسی نوشته شود.
|
||
|
||
**5.** اگر شما در حال نوشتن یک کتابخانه, شامل نظرات دقیق توضیح در فایل هدر اصلی.
|
||
|
||
**6.** هنوز نظر که اطلاعات اضافی را فراهم نمی کند اضافه کنید. به خصوص, نظرات خالی مثل این را ترک کنید:
|
||
|
||
``` cpp
|
||
/*
|
||
* Procedure Name:
|
||
* Original procedure name:
|
||
* Author:
|
||
* Date of creation:
|
||
* Dates of modification:
|
||
* Modification authors:
|
||
* Original file name:
|
||
* Purpose:
|
||
* Intent:
|
||
* Designation:
|
||
* Classes used:
|
||
* Constants:
|
||
* Local variables:
|
||
* Parameters:
|
||
* Date of creation:
|
||
* Purpose:
|
||
*/
|
||
```
|
||
|
||
به عنوان مثال با اقتباس از منابع http://home.tamk.fi/~jaalto/دوره آموزشی/برنامه نویسی به سبک/doc/قابل نگهداشت-کد/.
|
||
|
||
**7.** هنوز نظرات زباله ارسال کنید (نویسنده, تاریخ ایجاد ..) در ابتدای هر فایل.
|
||
|
||
**8.** نظرات تک خط با سه اسلش شروع می شود: `///` و نظرات چند خط با شروع `/**`. این نظرات در نظر گرفته شده است “documentation”.
|
||
|
||
توجه: شما می توانید داکسیژن برای تولید اسناد از این نظرات استفاده کنید. اما داکسیگن به طور کلی استفاده نمی شود زیرا راحت تر است که کد را در محیط برنامه نویسی حرکت دهید.
|
||
|
||
**9.** نظرات چند خط باید خطوط خالی در ابتدا و پایان ندارد (به جز خط که بسته یک نظر چند خط).
|
||
|
||
**10.** برای اظهار نظر از کد, استفاده از نظرات اساسی, نه “documenting” نظر.
|
||
|
||
**11.** حذف بخش هایی از کد اظهار نظر قبل از ارتکاب.
|
||
|
||
**12.** هنوز ناسزا در نظرات و یا کد استفاده کنید.
|
||
|
||
**13.** از حروف بزرگ استفاده نکنید. هنوز نقطه گذاری بیش از حد استفاده کنید.
|
||
|
||
``` cpp
|
||
/// WHAT THE FAIL???
|
||
```
|
||
|
||
**14.** هنوز نظر را به محیطی استفاده نمی.
|
||
|
||
``` cpp
|
||
///******************************************************
|
||
```
|
||
|
||
**15.** هنوز بحث در نظرات شروع نشد.
|
||
|
||
``` cpp
|
||
/// Why did you do this stuff?
|
||
```
|
||
|
||
**16.** بدون نیاز به نوشتن نظر در پایان یک بلوک توصیف چه بود وجود دارد.
|
||
|
||
``` cpp
|
||
/// for
|
||
```
|
||
|
||
## نامها {#names}
|
||
|
||
**1.** استفاده از حروف کوچک با رکورد در نام متغیرها و اعضای کلاس.
|
||
|
||
``` cpp
|
||
size_t max_block_size;
|
||
```
|
||
|
||
**2.** نام توابع (روش) استفاده از camelCase آغاز با حروف کوچک نامه.
|
||
|
||
``` cpp
|
||
std::string getName() const override { return "Memory"; }
|
||
```
|
||
|
||
**3.** برای نام کلاس ها (structs) استفاده از CamelCase آغاز با حروف بزرگ نامه. پیشوند دیگر از من برای رابط استفاده نمی شود.
|
||
|
||
``` cpp
|
||
class StorageMemory : public IStorage
|
||
```
|
||
|
||
**4.** `using` به همان شیوه به عنوان کلاس به نام, و یا با `_t` در پایان.
|
||
|
||
**5.** نام استدلال نوع الگو: در موارد ساده, استفاده `T`; `T`, `U`; `T1`, `T2`.
|
||
|
||
برای موارد پیچیده تر, هم پیروی از قوانین برای نام کلاس, و یا اضافه کردن پیشوند `T`.
|
||
|
||
``` cpp
|
||
template <typename TKey, typename TValue>
|
||
struct AggregatedStatElement
|
||
```
|
||
|
||
**6.** نام استدلال ثابت الگو: هم پیروی از قوانین برای نام متغیر, و یا استفاده `N` در موارد ساده.
|
||
|
||
``` cpp
|
||
template <bool without_www>
|
||
struct ExtractDomain
|
||
```
|
||
|
||
**7.** برای کلاس های انتزاعی (رابط) شما می توانید اضافه کنید `I` پیشوند.
|
||
|
||
``` cpp
|
||
class IBlockInputStream
|
||
```
|
||
|
||
**8.** اگر شما استفاده از یک متغیر به صورت محلی, شما می توانید نام کوتاه استفاده.
|
||
|
||
در تمام موارد دیگر, استفاده از یک نام است که معنای توصیف.
|
||
|
||
``` cpp
|
||
bool info_successfully_loaded = false;
|
||
```
|
||
|
||
**9.** اسامی `define`بازدید کنندگان و ثابت جهانی استفاده از همه\_کاپ با زیرخط.
|
||
|
||
``` cpp
|
||
#define MAX_SRC_TABLE_NAMES_TO_STORE 1000
|
||
```
|
||
|
||
**10.** نام فایل باید همان سبک به عنوان مطالب خود استفاده کنید.
|
||
|
||
اگر یک فایل شامل یک کلاس, نام فایل به همان شیوه به عنوان کلاس (بالش).
|
||
|
||
اگر فایل شامل یک تابع واحد, نام فایل به همان شیوه به عنوان تابع (بالش).
|
||
|
||
**11.** اگر نام شامل مخفف, سپس:
|
||
|
||
- برای نام متغیر مخفف حروف کوچک استفاده کنید `mysql_connection` ) نه `mySQL_connection`).
|
||
- برای نام کلاس ها و توابع, نگه داشتن حروف بزرگ در مخفف`MySQLConnection` ) نه `MySqlConnection`).
|
||
|
||
**12.** استدلال سازنده استفاده می شود که فقط به مقداردهی اولیه اعضای کلاس باید به همان شیوه به عنوان اعضای کلاس به نام, اما با تاکید در پایان.
|
||
|
||
``` cpp
|
||
FileQueueProcessor(
|
||
const std::string & path_,
|
||
const std::string & prefix_,
|
||
std::shared_ptr<FileHandler> handler_)
|
||
: path(path_),
|
||
prefix(prefix_),
|
||
handler(handler_),
|
||
log(&Logger::get("FileQueueProcessor"))
|
||
{
|
||
}
|
||
```
|
||
|
||
پسوند تاکید می توان حذف اگر استدلال در بدن سازنده استفاده نمی شود.
|
||
|
||
**13.** هیچ تفاوتی در نام متغیرهای محلی و اعضای کلاس وجود دارد (هیچ پیشوندهای مورد نیاز).
|
||
|
||
``` cpp
|
||
timer (not m_timer)
|
||
```
|
||
|
||
**14.** برای ثابت در یک `enum` استفاده از CamelCase با حرف بزرگ. ت\_کاپها نیز قابل قبول است. اگر `enum` غیر محلی است, استفاده از یک `enum class`.
|
||
|
||
``` cpp
|
||
enum class CompressionMethod
|
||
{
|
||
QuickLZ = 0,
|
||
LZ4 = 1,
|
||
};
|
||
```
|
||
|
||
**15.** همه نامها باید به زبان انگلیسی باشد. ترجمه کلمات روسی مجاز نیست.
|
||
|
||
not Stroka
|
||
|
||
**16.** اختصارات قابل قبول هستند در صورتی که به خوبی شناخته شده است (زمانی که شما به راحتی می توانید معنای مخفف در ویکیپدیا و یا در یک موتور جستجو پیدا کنید).
|
||
|
||
`AST`, `SQL`.
|
||
|
||
Not `NVDH` (some random letters)
|
||
|
||
کلمات ناقص قابل قبول است اگر نسخه کوتاه استفاده مشترک است.
|
||
|
||
شما همچنین می توانید مخفف استفاده کنید اگر نام کامل در کنار در نظرات گنجانده شده است.
|
||
|
||
**17.** نام فایل با ج++ کد منبع باید `.cpp` گسترش. فایل های هدر باید داشته باشند `.h` گسترش.
|
||
|
||
## نحوه نوشتن کد {#how-to-write-code}
|
||
|
||
**1.** مدیریت حافظه.
|
||
|
||
تخصیص حافظه دستی (`delete`) تنها می تواند در کد کتابخانه استفاده می شود.
|
||
|
||
در کد کتابخانه `delete` اپراتور تنها می تواند در مخرب استفاده می شود.
|
||
|
||
در کد برنامه, حافظه باید توسط شی که صاحب رهایی.
|
||
|
||
مثالها:
|
||
|
||
- ساده ترین راه این است که یک شی را روی پشته قرار دهید یا عضو یک کلاس دیگر شوید.
|
||
- برای تعداد زیادی از اشیای کوچک از ظروف استفاده کنید.
|
||
- برای تخصیص خودکار تعداد کمی از اشیا که در پشته قرار دارند استفاده کنید `shared_ptr/unique_ptr`.
|
||
|
||
**2.** مدیریت منابع.
|
||
|
||
استفاده `RAII` و بالا را ببینید.
|
||
|
||
**3.** رفع خطا.
|
||
|
||
استفاده از استثنا. در بیشتر موارد, شما فقط نیاز به پرتاب یک استثنا, و لازم نیست برای گرفتن (به دلیل `RAII`).
|
||
|
||
در برنامه های پردازش داده ها نیست, اغلب قابل قبول برای گرفتن استثنا نیست.
|
||
|
||
در سرور هایی که رسیدگی به درخواست کاربر, این معمولا به اندازه کافی برای گرفتن استثنا در سطح بالای کنترل اتصال.
|
||
|
||
در توابع موضوع, شما باید گرفتن و نگه داشتن همه استثنا به تجدید نظر در موضوع اصلی پس از `join`.
|
||
|
||
``` cpp
|
||
/// If there weren't any calculations yet, calculate the first block synchronously
|
||
if (!started)
|
||
{
|
||
calculate();
|
||
started = true;
|
||
}
|
||
else /// If calculations are already in progress, wait for the result
|
||
pool.wait();
|
||
|
||
if (exception)
|
||
exception->rethrow();
|
||
```
|
||
|
||
هرگز استثنا بدون دست زدن به پنهان. هرگز فقط کورکورانه قرار دادن همه استثنا برای ورود به سیستم.
|
||
|
||
``` cpp
|
||
//Not correct
|
||
catch (...) {}
|
||
```
|
||
|
||
اگر شما نیاز به چشم پوشی از چند استثنا, انجام این کار تنها برای افراد خاص و تجدید نظر بقیه.
|
||
|
||
``` cpp
|
||
catch (const DB::Exception & e)
|
||
{
|
||
if (e.code() == ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION)
|
||
return nullptr;
|
||
else
|
||
throw;
|
||
}
|
||
```
|
||
|
||
هنگام استفاده از توابع با کدهای پاسخ یا `errno`, همیشه نتیجه را بررسی کنید و پرتاب یک استثنا در صورت خطا.
|
||
|
||
``` cpp
|
||
if (0 != close(fd))
|
||
throwFromErrno("Cannot close file " + file_name, ErrorCodes::CANNOT_CLOSE_FILE);
|
||
```
|
||
|
||
`Do not use assert`.
|
||
|
||
**4.** انواع استثنا.
|
||
|
||
بدون نیاز به استفاده از سلسله مراتب استثنا پیچیده در کد نرم افزار وجود دارد. متن استثنا باید قابل فهم برای یک مدیر سیستم.
|
||
|
||
**5.** پرتاب استثنا از destructors.
|
||
|
||
این توصیه نمی شود, اما مجاز است.
|
||
|
||
از گزینه های زیر استفاده کنید:
|
||
|
||
- ایجاد یک تابع (`done()` یا `finalize()`) که همه کار در پیش است که ممکن است منجر به یک استثنا انجام دهد. در صورتی که تابع نامیده می شد, باید بدون استثنا در مخرب بعد وجود داشته باشد.
|
||
- کارهایی که بیش از حد پیچیده هستند (مانند ارسال پیام بر روی شبکه) را می توان در روش جداگانه قرار داده است که کاربر کلاس باید قبل از تخریب تماس بگیرید.
|
||
- اگر یک استثنا در مخرب وجود دارد, بهتر است به سیستم وارد شوید از برای مخفی کردن (اگر چوب در دسترس است).
|
||
- در برنامه های ساده, قابل قبول است به تکیه بر `std::terminate` (برای موارد `noexcept` به طور پیش فرض در ج++11) برای رسیدگی به استثنا.
|
||
|
||
**6.** بلوک کد ناشناس.
|
||
|
||
شما می توانید یک بلوک کد جداگانه در داخل یک تابع واحد به منظور ایجاد متغیرهای خاص محلی ایجاد, به طوری که مخرب نامیده می شوند در هنگام خروج از بلوک.
|
||
|
||
``` cpp
|
||
Block block = data.in->read();
|
||
|
||
{
|
||
std::lock_guard<std::mutex> lock(mutex);
|
||
data.ready = true;
|
||
data.block = block;
|
||
}
|
||
|
||
ready_any.set();
|
||
```
|
||
|
||
**7.** چند رشته.
|
||
|
||
در برنامههای پردازش داده برونخط:
|
||
|
||
- سعی کنید بهترین عملکرد ممکن را در یک هسته پردازنده تک دریافت کنید. سپس می توانید کد خود را در صورت لزوم موازی کنید.
|
||
|
||
در برنامه های سرور:
|
||
|
||
- استفاده از استخر موضوع برای پردازش درخواست. در این مرحله, ما هیچ وظایفی که مورد نیاز تعویض زمینه فضای کاربری نداشته اند.
|
||
|
||
چنگال برای موازی سازی استفاده نمی شود.
|
||
|
||
**8.** همگام سازی موضوعات.
|
||
|
||
اغلب ممکن است موضوعات مختلف از سلول های حافظه مختلف (حتی بهتر: خطوط کش مختلف) استفاده کنند و از هماهنگ سازی موضوع (به جز `joinAll`).
|
||
|
||
اگر هماهنگ سازی مورد نیاز است, در بیشتر موارد, کافی است به استفاده از امکانپذیر تحت `lock_guard`.
|
||
|
||
در موارد دیگر استفاده از شکلهای هندسی اولیه هماهنگ سازی سیستم. هنوز انتظار مشغول استفاده کنید.
|
||
|
||
عملیات اتمی باید تنها در ساده ترین موارد استفاده می شود.
|
||
|
||
سعی نکنید ساختارهای داده ای بدون قفل را اجرا کنید مگر اینکه منطقه اصلی تخصص شما باشد.
|
||
|
||
**9.** اشاره گر در مقابل مراجع.
|
||
|
||
در بیشتر موارد, ترجیح می دهند مراجع.
|
||
|
||
**10.** توایع.
|
||
|
||
استفاده از منابع ثابت اشاره گر به ثابت, `const_iterator`, و روش توایع.
|
||
|
||
در نظر بگیرید `const` به طور پیش فرض و استفاده غیر-`const` فقط در صورت لزوم.
|
||
|
||
هنگام عبور متغیرها بر اساس ارزش, با استفاده از `const` معمولا معنی ندارد.
|
||
|
||
**11.** امضا نشده.
|
||
|
||
استفاده `unsigned` در صورت لزوم
|
||
|
||
**12.** انواع عددی.
|
||
|
||
استفاده از انواع `UInt8`, `UInt16`, `UInt32`, `UInt64`, `Int8`, `Int16`, `Int32` و `Int64`, و همچنین `size_t`, `ssize_t` و `ptrdiff_t`.
|
||
|
||
از این نوع برای اعداد استفاده نکنید: `signed/unsigned long`, `long long`, `short`, `signed/unsigned char`, `char`.
|
||
|
||
**13.** عبور استدلال.
|
||
|
||
رمز عبور مقادیر پیچیده توسط مرجع (محتوی `std::string`).
|
||
|
||
اگر یک تابع قطاری مالکیت یک شی ایجاد شده در پشته, را از نوع استدلال `shared_ptr` یا `unique_ptr`.
|
||
|
||
**14.** ارزش بازگشت.
|
||
|
||
در اکثر موارد فقط استفاده کنید `return`. ننویس `[return std::move(res)]{.strike}`.
|
||
|
||
اگر تابع یک شی در پشته اختصاص و بازده, استفاده `shared_ptr` یا `unique_ptr`.
|
||
|
||
در موارد نادر شما ممکن است نیاز به بازگشت به ارزش از طریق بحث و جدل. در این مورد استدلال باید مرجع باشد.
|
||
|
||
``` cpp
|
||
using AggregateFunctionPtr = std::shared_ptr<IAggregateFunction>;
|
||
|
||
/** Allows creating an aggregate function by its name.
|
||
*/
|
||
class AggregateFunctionFactory
|
||
{
|
||
public:
|
||
AggregateFunctionFactory();
|
||
AggregateFunctionPtr get(const String & name, const DataTypes & argument_types) const;
|
||
```
|
||
|
||
**15.** فضای نام.
|
||
|
||
بدون نیاز به استفاده از یک جداگانه وجود دارد `namespace` برای کد برنامه.
|
||
|
||
کتابخانه های کوچک هم به این نیاز ندارند.
|
||
|
||
برای کتابخانه های متوسط تا بزرگ, همه چیز را در یک `namespace`.
|
||
|
||
در کتابخانه `.h` پرونده, شما می توانید استفاده کنید `namespace detail` برای مخفی کردن اطلاعات پیاده سازی برای کد برنامه مورد نیاز نیست.
|
||
|
||
در یک `.cpp` پرونده, شما می توانید یک استفاده `static` یا فضای نام ناشناس برای مخفی کردن نمادها.
|
||
|
||
همچنین یک `namespace` می تواند برای یک استفاده شود `enum` برای جلوگیری از نام های مربوطه را از افتادن به یک خارجی `namespace` (اما بهتر است از یک `enum class`).
|
||
|
||
**16.** مقدار دهی اولیه معوق.
|
||
|
||
اگر استدلال برای مقدار دهی اولیه مورد نیاز, سپس شما به طور معمول باید یک سازنده به طور پیش فرض ارسال کنید.
|
||
|
||
اگر بعد شما نیاز به تاخیر دهی اولیه, شما می توانید یک سازنده به طور پیش فرض است که یک شی نامعتبر ایجاد اضافه. یا برای تعداد کمی از اشیا می توانید استفاده کنید `shared_ptr/unique_ptr`.
|
||
|
||
``` cpp
|
||
Loader(DB::Connection * connection_, const std::string & query, size_t max_block_size_);
|
||
|
||
/// For deferred initialization
|
||
Loader() {}
|
||
```
|
||
|
||
**17.** توابع مجازی.
|
||
|
||
اگر کلاس برای استفاده چند شکل در نظر گرفته شده, شما لازم نیست که به توابع مجازی. این نیز به مخرب اعمال می شود.
|
||
|
||
**18.** کدگذاریها.
|
||
|
||
استفاده از اوتیف - 8 در همه جا. استفاده `std::string`و`char *`. استفاده نشود `std::wstring`و`wchar_t`.
|
||
|
||
**19.** ثبت.
|
||
|
||
نمونه در همه جا در کد را ببینید.
|
||
|
||
قبل از ارتکاب, حذف همه بی معنی و اشکال زدایی ورود به سیستم, و هر نوع دیگری از خروجی اشکال زدایی.
|
||
|
||
ورود به چرخه باید حتی در سطح ردیابی اجتناب شود.
|
||
|
||
سیاهههای مربوط باید در هر سطح ورود به سیستم قابل خواندن باشد.
|
||
|
||
ورود به سیستم تنها باید در کد نرم افزار مورد استفاده قرار, در بیشتر قسمت ها.
|
||
|
||
ورود پیام باید به زبان انگلیسی نوشته شده است.
|
||
|
||
ورود ترجیحا باید برای مدیر سیستم قابل فهم باشد.
|
||
|
||
هنوز ناسزا در ورود به سیستم استفاده کنید.
|
||
|
||
استفاده از جی تی اف 8 را پشتیبانی می کند در ورود به سیستم. در موارد نادر شما می توانید شخصیت های غیر اسکی در ورود به سیستم استفاده کنید.
|
||
|
||
**20.** ورودی-خروجی.
|
||
|
||
استفاده نکنید `iostreams` در چرخه های داخلی که برای عملکرد برنامه حیاتی هستند (و هرگز استفاده نکنید `stringstream`).
|
||
|
||
استفاده از `DB/IO` کتابخانه به جای.
|
||
|
||
**21.** تاریخ و زمان.
|
||
|
||
دیدن `DateLUT` کتابخونه.
|
||
|
||
**22.** شامل شدن.
|
||
|
||
همیشه استفاده کنید `#pragma once` به جای شامل نگهبانان.
|
||
|
||
**23.** با استفاده از.
|
||
|
||
`using namespace` استفاده نمی شود. شما می توانید استفاده کنید `using` با چیزی خاص. اما محلی در داخل یک کلاس و یا تابع را.
|
||
|
||
**24.** استفاده نشود `trailing return type` برای توابع مگر اینکه لازم باشد.
|
||
|
||
``` cpp
|
||
[auto f() -> void;]{.strike}
|
||
```
|
||
|
||
**25.** اعلامیه و مقدار دهی اولیه از متغیرهای.
|
||
|
||
``` cpp
|
||
//right way
|
||
std::string s = "Hello";
|
||
std::string s{"Hello"};
|
||
|
||
//wrong way
|
||
auto s = std::string{"Hello"};
|
||
```
|
||
|
||
**26.** برای توابع مجازی, نوشتن `virtual` در کلاس پایه, اما ارسال `override` به جای `virtual` در کلاس های نسل نو.
|
||
|
||
## ویژگی های استفاده نشده از سی++ {#unused-features-of-c}
|
||
|
||
**1.** ارث مجازی استفاده نمی شود.
|
||
|
||
**2.** ویژگی استثنا از ج++03 استفاده نمی شود.
|
||
|
||
## سکو {#platform}
|
||
|
||
**1.** ما نوشتن کد برای یک پلت فرم خاص.
|
||
|
||
اما چیزهای دیگر برابر بودن, کراس پلت فرم و یا کد قابل حمل ترجیح داده می شود.
|
||
|
||
**2.** زبان: ج++17.
|
||
|
||
**3.** کامپایلر: `gcc`. در این زمان (دسامبر 2017), کد با استفاده از نسخه وارد شده 7.2. (همچنین می تواند با استفاده از وارد شود `clang 4`.)
|
||
|
||
کتابخانه استاندارد استفاده شده است (`libstdc++` یا `libc++`).
|
||
|
||
**4.**سیستم عامل: لینوکس اوبونتو, مسن تر از دقیق نیست.
|
||
|
||
**5.**کد برای معماری پردازنده ایکس86\_64 نوشته شده است.
|
||
|
||
مجموعه دستورالعمل پردازنده حداقل مجموعه پشتیبانی در میان سرورهای ما است. در حال حاضر, این سوس است 4.2.
|
||
|
||
**6.** استفاده `-Wall -Wextra -Werror` پرچم تلفیقی.
|
||
|
||
**7.** استفاده از لینک کردن استاتیک با تمام کتابخانه ها به جز کسانی که به سختی برای اتصال به استاتیک (خروجی را ببینید `ldd` فرمان).
|
||
|
||
**8.** کد توسعه یافته است و با تنظیمات انتشار دیباگ.
|
||
|
||
## ابزارها {#tools}
|
||
|
||
**1.** KDevelop خوب است IDE.
|
||
|
||
**2.** برای اشکالزدایی, استفاده `gdb`, `valgrind` (`memcheck`), `strace`, `-fsanitize=...` یا `tcmalloc_minimal_debug`.
|
||
|
||
**3.** برای پروفایل استفاده کنید `Linux Perf`, `valgrind` (`callgrind`), یا `strace -cf`.
|
||
|
||
**4.** منابع در دستگاه گوارش هستند.
|
||
|
||
**5.** استفاده مجمع `CMake`.
|
||
|
||
**6.** برنامه ها با استفاده از منتشر `deb` بسته.
|
||
|
||
**7.** مرتکب به استاد باید ساخت شکستن نیست.
|
||
|
||
هر چند تجدید نظر تنها انتخاب شده قابل اجرا در نظر گرفته.
|
||
|
||
**8.** مرتکب به عنوان اغلب به عنوان امکان پذیر است, حتی اگر کد تنها تا حدی اماده.
|
||
|
||
استفاده از شاخه برای این منظور.
|
||
|
||
اگر کد شما در `master` شاخه هنوز قابل ساختن نیست و از قبل از ساخت حذف می شود `push`. باید تمومش کنی یا ظرف چند روز حذفش کنی
|
||
|
||
**9.** برای تغییرات غیر بدیهی از شاخه ها استفاده کنید و بر روی سرور منتشر کنید.
|
||
|
||
**10.** کد استفاده نشده است از مخزن حذف شده است.
|
||
|
||
## کتابخانهها {#libraries}
|
||
|
||
**1.** ج++14 کتابخانه استاندارد استفاده شده است (پسوند تجربی مجاز), و همچنین `boost` و `Poco` چارچوب.
|
||
|
||
**2.** در صورت لزوم, شما می توانید هر کتابخانه شناخته شده موجود در بسته سیستم عامل استفاده.
|
||
|
||
اگر یک راه حل خوب در حال حاضر در دسترس وجود دارد, سپس استفاده کنید, حتی اگر به این معنی شما باید برای نصب کتابخانه دیگر.
|
||
|
||
(اما برای حذف کتابخانه های بد از کد تهیه می شود.)
|
||
|
||
**3.** شما می توانید یک کتابخانه است که در بسته نیست نصب, اگر بسته لازم نیست که چه شما نیاز دارید و یا یک نسخه منسوخ شده و یا نوع اشتباه از تلفیقی.
|
||
|
||
**4.** اگر کتابخانه کوچک است و سیستم ساخت پیچیده خود را ندارد, قرار دادن فایل های منبع در `contrib` پوشه
|
||
|
||
**5.** اولویت همیشه به کتابخانه هایی که در حال حاضر در حال استفاده هستند داده می شود.
|
||
|
||
## توصیه های عمومی {#general-recommendations-1}
|
||
|
||
**1.** ارسال کد به عنوان کوچک که ممکن است.
|
||
|
||
**2.** ساده ترین راه حل را امتحان کنید.
|
||
|
||
**3.** کد را بنویسید تا بدانید چگونه کار می کند و چگونه حلقه داخلی عمل می کند.
|
||
|
||
**4.** در ساده ترین موارد استفاده کنید `using` به جای کلاس و یا ساختار.
|
||
|
||
**5.** در صورت امکان, انجام سازنده کپی ارسال کنید, اپراتورهای انتساب, مخرب (به غیر از یک مجازی, اگر کلاس شامل حداقل یک تابع مجازی), حرکت سازنده و یا اپراتورهای انتساب حرکت. به عبارت دیگر, توابع کامپایلر تولید باید به درستی کار. شما می توانید استفاده کنید `default`.
|
||
|
||
**6.** ساده سازی کد تشویق می شود. کاهش اندازه کد خود را در صورت امکان.
|
||
|
||
## توصیه های اضافی {#additional-recommendations}
|
||
|
||
**1.** به صراحت مشخص `std::` برای انواع از `stddef.h`
|
||
|
||
توصیه نمی شود. به عبارت دیگر توصیه می کنیم نوشتن کنید `size_t` در عوض `std::size_t` چون کوتاهتر است .
|
||
|
||
این قابل قبول است برای اضافه کردن `std::`.
|
||
|
||
**2.** به صراحت مشخص `std::` برای توابع از کتابخانه استاندارد ج
|
||
|
||
توصیه نمی شود. به عبارت دیگر, نوشتن `memcpy` به جای `std::memcpy`.
|
||
|
||
دلیل این است که توابع غیر استاندارد مشابه وجود دارد, مانند `memmem`. ما با استفاده از این توابع در مناسبت. این توابع در وجود ندارد `namespace std`.
|
||
|
||
اگر شما ارسال `std::memcpy` به جای `memcpy` پس همه جا `memmem` بدون `std::` نگاه عجیب و غریب.
|
||
|
||
با این اوصاف, شما هنوز هم می توانید استفاده کنید `std::` اگر شما ترجیح می دهند.
|
||
|
||
**3.** با استفاده از توابع از ج زمانی که همان در استاندارد ج++ کتابخانه در دسترس هستند.
|
||
|
||
این قابل قبول است اگر کارایی بیشتری داشته باشد.
|
||
|
||
برای مثال استفاده کنید `memcpy` به جای `std::copy` برای کپی کردن تکه های زیادی از حافظه است.
|
||
|
||
**4.** استدلال تابع چند خطی.
|
||
|
||
هر یک از سبک های بسته بندی زیر مجاز است:
|
||
|
||
``` cpp
|
||
function(
|
||
T1 x1,
|
||
T2 x2)
|
||
```
|
||
|
||
``` cpp
|
||
function(
|
||
size_t left, size_t right,
|
||
const & RangesInDataParts ranges,
|
||
size_t limit)
|
||
```
|
||
|
||
``` cpp
|
||
function(size_t left, size_t right,
|
||
const & RangesInDataParts ranges,
|
||
size_t limit)
|
||
```
|
||
|
||
``` cpp
|
||
function(size_t left, size_t right,
|
||
const & RangesInDataParts ranges,
|
||
size_t limit)
|
||
```
|
||
|
||
``` cpp
|
||
function(
|
||
size_t left,
|
||
size_t right,
|
||
const & RangesInDataParts ranges,
|
||
size_t limit)
|
||
```
|
||
|
||
[مقاله اصلی](https://clickhouse.tech/docs/en/development/style/) <!--hide-->
|