Serenity Operating System
at master 754 lines 16 kB view raw view rendered
1# Serenity C++ coding style 2 3For low-level styling (spaces, parentheses, brace placement, etc), all code should follow the format specified in `.clang-format` in the project root. 4 5**Important: Make sure you use `clang-format` version 15 or later!** 6 7This document describes the coding style used for C++ code in the Serenity Operating System project. All new code should conform to this style. 8 9We'll definitely be tweaking and amending this over time, so let's consider it a living document. :) 10 11 12### Names 13 14A combination of CamelCase and snake\_case. Use CamelCase (Capitalize the first letter, including all letters in an acronym) in a class, struct, or namespace name. Use snake\_case (all lowercase, with underscores separating words) for variable and function names. 15 16###### Right: 17 18```cpp 19struct Entry; 20size_t buffer_size; 21class FileDescriptor; 22String absolute_path(); 23``` 24 25###### Wrong: 26 27```cpp 28struct data; 29size_t bufferSize; 30class Filedescriptor; 31String MIME_Type(); 32``` 33 34Use full words, except in the rare case where an abbreviation would be more canonical and easier to understand. 35 36###### Right: 37 38```cpp 39size_t character_size; 40size_t length; 41short tab_index; // More canonical. 42``` 43 44###### Wrong: 45 46```cpp 47size_t char_size; 48size_t len; 49short tabulation_index; // Goofy. 50``` 51 52Data members in C++ classes should be private. Static data members should be prefixed by "s\_". Other data members should be prefixed by "m\_". Global variables should be prefixed by "g\_". 53 54###### Right: 55 56```cpp 57class String { 58public: 59 ... 60 61private: 62 int m_length { 0 }; 63}; 64``` 65 66###### Wrong: 67 68```cpp 69class String { 70public: 71 ... 72 73 int length { 0 }; 74}; 75``` 76 77Precede setters with the word "set". Use bare words for getters. Setter and getter names should match the names of the variables being set/gotten. 78 79###### Right: 80 81```cpp 82void set_count(int); // Sets m_count. 83int count() const; // Returns m_count. 84``` 85 86###### Wrong: 87 88```cpp 89void set_count(int); // Sets m_the_count. 90int get_count() const; // Returns m_the_count. 91``` 92 93Precede getters that return values through out arguments with the word "get". 94 95###### Right: 96 97```cpp 98void get_filename_and_inode_id(String&, InodeIdentifier&) const; 99``` 100 101###### Wrong: 102 103```cpp 104void filename_and_inode_id(String&, InodeIdentifier&) const; 105``` 106 107Use descriptive verbs in function names. 108 109###### Right: 110 111```cpp 112bool convert_to_ascii(short*, size_t); 113``` 114 115###### Wrong: 116 117```cpp 118bool to_ascii(short*, size_t); 119``` 120 121When there are two getters for a variable, and one of them automatically makes sure the requested object is instantiated, prefix that getter function with `ensure_`. As it ensures that an object is created, it should consequently also return a reference, not a pointer. 122 123###### Right: 124 125```cpp 126Inode* inode(); 127Inode& ensure_inode(); 128``` 129 130###### Wrong: 131 132```cpp 133Inode& inode(); 134Inode* ensure_inode(); 135``` 136 137Leave meaningless variable names out of function declarations. A good rule of thumb is if the parameter type name contains the parameter name (without trailing numbers or pluralization), then the parameter name isn't needed. Usually, there should be a parameter name for bools, strings, and numerical types. 138 139###### Right: 140 141```cpp 142void set_count(int); 143 144void do_something(Context*); 145``` 146 147###### Wrong: 148 149```cpp 150void set_count(int count); 151 152void do_something(Context* context); 153``` 154 155Prefer enums to bools on function parameters if callers are likely to be passing constants, since named constants are easier to read at the call site. An exception to this rule is a setter function, where the name of the function already makes clear what the boolean is. 156 157###### Right: 158 159```cpp 160do_something(something, AllowFooBar::Yes); 161paint_text_with_shadows(context, ..., text_stroke_width > 0, is_horizontal()); 162set_resizable(false); 163``` 164 165###### Wrong: 166 167```cpp 168do_something(something, false); 169set_resizable(NotResizable); 170``` 171 172Enum members should use InterCaps with an initial capital letter. 173 174Prefer `const` to `#define`. Prefer inline functions to macros. 175 176`#defined` constants should use all uppercase names with words separated by underscores. 177 178Use `#pragma once` instead of `#define` and `#ifdef` for header guards. 179 180###### Right: 181 182```cpp 183// MyClass.h 184#pragma once 185``` 186 187###### Wrong: 188 189```cpp 190// MyClass.h 191#ifndef MyClass_h 192#define MyClass_h 193``` 194 195### Other Punctuation 196 197Constructors for C++ classes should initialize their members using C++ initializer syntax. Each member (and superclass) should be indented on a separate line, with the colon or comma preceding the member on that line. Prefer initialization at member definition whenever possible. 198 199###### Right: 200 201```cpp 202class MyClass { 203 ... 204 Document* m_document { nullptr }; 205 int m_my_member { 0 }; 206}; 207 208MyClass::MyClass(Document* document) 209 : MySuperClass() 210 , m_document(document) 211{ 212} 213 214MyOtherClass::MyOtherClass() 215 : MySuperClass() 216{ 217} 218``` 219 220###### Wrong: 221 222```cpp 223MyClass::MyClass(Document* document) : MySuperClass() 224{ 225 m_myMember = 0; 226 m_document = document; 227} 228 229MyClass::MyClass(Document* document) : MySuperClass() 230 : m_my_member(0) // This should be in the header. 231{ 232 m_document = document; 233} 234 235MyOtherClass::MyOtherClass() : MySuperClass() {} 236``` 237 238Prefer index or range-for over iterators in Vector iterations for terse, easier-to-read code. 239 240###### Right: 241 242```cpp 243for (auto& child : children) 244 child->do_child_thing(); 245``` 246 247 248#### OK: 249 250```cpp 251for (int i = 0; i < children.size(); ++i) 252 children[i]->do_child_thing(); 253``` 254 255###### Wrong: 256 257```cpp 258for (auto it = children.begin(); it != children.end(); ++it) 259 (*it)->do_child_thing(); 260``` 261 262### Pointers and References 263 264Both pointer types and reference types should be written with no space between the type name and the `*` or `&`. 265 266An out argument of a function should be passed by reference except rare cases where it is optional in which case it should be passed by pointer. 267 268###### Right: 269 270```cpp 271void MyClass::get_some_value(OutArgumentType& out_argument) const 272{ 273 out_argument = m_value; 274} 275 276void MyClass::do_something(OutArgumentType* out_argument) const 277{ 278 do_the_thing(); 279 if (out_argument) 280 *out_argument = m_value; 281} 282``` 283 284###### Wrong: 285 286```cpp 287void MyClass::get_some_value(OutArgumentType* outArgument) const 288{ 289 *out_argument = m_value; 290} 291``` 292 293### "using" Statements 294 295In header files in the AK sub-library, however, it is acceptable to use "using" declarations at the end of the file to import one or more names in the AK namespace into the global scope. 296 297###### Right: 298 299```cpp 300// AK/Vector.h 301 302namespace AK { 303 304} // namespace AK 305 306using AK::Vector; 307``` 308 309###### Wrong: 310 311```cpp 312// AK/Vector.h 313 314namespace AK { 315 316} // namespace AK 317 318using namespace AK; 319``` 320 321###### Wrong: 322 323```cpp 324// runtime/Object.h 325 326namespace AK { 327 328} // namespace AK 329 330using AK::SomethingOrOther; 331``` 332 333In C++ implementation files, do not use "using" declarations of any kind to import names in the standard template library. Directly qualify the names at the point they're used instead. 334 335###### Right: 336 337```cpp 338// File.cpp 339 340std::swap(a, b); 341c = std::numeric_limits<int>::max() 342``` 343 344###### Wrong: 345 346```cpp 347// File.cpp 348 349using std::swap; 350swap(a, b); 351``` 352 353###### Wrong: 354 355```cpp 356// File.cpp 357 358using namespace std; 359swap(a, b); 360``` 361 362### Types 363 364Omit "int" when using "unsigned" modifier. Do not use "signed" modifier. Use "int" by itself instead. 365 366###### Right: 367 368```cpp 369unsigned a; 370int b; 371``` 372 373###### Wrong: 374 375```cpp 376unsigned int a; // Doesn't omit "int". 377signed b; // Uses "signed" instead of "int". 378signed int c; // Doesn't omit "signed". 379``` 380 381### Classes 382 383For types with methods, prefer `class` over `struct`. 384 385* For classes, make public getters and setters, keep members private with `m_` prefix. 386* For structs, let everything be public and skip the `m_` prefix. 387 388###### Right: 389 390```cpp 391struct Thingy { 392 String name; 393 int frob_count { 0 }; 394}; 395 396class Doohickey { 397public: 398 String const& name() const { return m_name; } 399 int frob_count() const { return m_frob_count; } 400 401 void jam(); 402 403private: 404 String m_name; 405 int m_frob_count { 0 }; 406} 407``` 408 409###### Wrong: 410 411```cpp 412struct Thingy { 413public: 414 String m_name; 415 int frob_count() const { return m_frob_count; } 416 417private: 418 int m_frob_count { 0 }; 419} 420 421class Doohickey { 422public: 423 String const& name() const { return this->name; } 424 425 void jam(); 426 427 String name; 428 int frob_count { 0 }; 429}; 430``` 431 432Use a constructor to do an implicit conversion when the argument is reasonably thought of as a type conversion and the type conversion is fast. Otherwise, use the explicit keyword or a function returning the type. This only applies to single argument constructors. 433 434###### Right: 435 436```cpp 437class LargeInt { 438public: 439 LargeInt(int); 440... 441 442class Vector { 443public: 444 explicit Vector(int size); // Not a type conversion. 445 Vector create(Array); // Costly conversion. 446... 447 448``` 449 450###### Wrong: 451 452```cpp 453class Task { 454public: 455 Task(ExecutionContext&); // Not a type conversion. 456 explicit Task(); // No arguments. 457 explicit Task(ExecutionContext&, Other); // More than one argument. 458... 459``` 460 461### Singleton pattern 462 463Use a static member function named "the()" to access the instance of the singleton. 464 465###### Right: 466 467```cpp 468class UniqueObject { 469public: 470 static UniqueObject& the(); 471... 472``` 473 474###### Wrong: 475 476```cpp 477class UniqueObject { 478public: 479 static UniqueObject& shared(); 480... 481``` 482 483###### Wrong: 484 485```cpp 486class UniqueObject { 487... 488}; 489 490UniqueObject& my_unique_object(); // Free function. 491``` 492 493### Comments 494 495Make comments look like sentences by starting with a capital letter and ending with a period (punctuation). One exception may be end of line comments like this `if (x == y) // false for NaN`. 496 497Use FIXME: (without attribution) to denote items that need to be addressed in the future. 498 499###### Right: 500 501```cpp 502draw_jpg(); // FIXME: Make this code handle jpg in addition to the png support. 503``` 504 505###### Wrong: 506 507```cpp 508draw_jpg(); // FIXME(joe): Make this code handle jpg in addition to the png support. 509``` 510 511```cpp 512draw_jpg(); // TODO: Make this code handle jpg in addition to the png support. 513``` 514 515Explain *why* the code does something. The code itself should already say what is happening. 516 517###### Right: 518 519```cpp 520i++; // Go to the next page. 521``` 522 523```cpp 524// Let users toggle the advice functionality by clicking on catdog. 525catdog_widget.on_click = [&] { 526 if (advice_timer->is_active()) 527 advice_timer->stop(); 528 else 529 advice_timer->start(); 530}; 531``` 532 533###### Even better: 534 535```cpp 536page_index++; 537``` 538 539###### Wrong: 540 541```cpp 542i++; // Increment i. 543``` 544 545```cpp 546// If the user clicks, toggle the timer state. 547catdog_widget.on_click = [&] { 548 if (advice_timer->is_active()) 549 advice_timer->stop(); 550 else 551 advice_timer->start(); 552}; 553``` 554 555### Overriding Virtual Methods 556 557The declaration of a virtual method inside a class must be declared with the `virtual` keyword. All subclasses of that class must also specify either the `override` keyword when overriding the virtual method, or the `final` keyword when overriding the virtual method and requiring that no further subclasses can override it. 558 559###### Right: 560 561```cpp 562class Person { 563public: 564 virtual String description() { ... }; 565} 566 567class Student : public Person { 568public: 569 virtual String description() override { ... }; // This is correct because it contains both the "virtual" and "override" keywords to indicate that the method is overridden. 570} 571 572``` 573 574```cpp 575class Person { 576public: 577 virtual String description() { ... }; 578} 579 580class Student : public Person { 581public: 582 virtual String description() final { ... }; // This is correct because it contains both the "virtual" and "final" keywords to indicate that the method is overridden and that no subclasses of "Student" can override "description". 583} 584 585``` 586 587###### Wrong: 588 589```cpp 590class Person { 591public: 592 virtual String description() { ... }; 593} 594 595class Student : public Person { 596public: 597 String description() override { ... }; // This is incorrect because it uses only the "override" keyword to indicate that the method is virtual. Instead, it should use both the "virtual" and "override" keywords. 598} 599``` 600 601```cpp 602class Person { 603public: 604 virtual String description() { ... }; 605} 606 607class Student : public Person { 608public: 609 String description() final { ... }; // This is incorrect because it uses only the "final" keyword to indicate that the method is virtual and final. Instead, it should use both the "virtual" and "final" keywords. 610} 611``` 612 613```cpp 614class Person { 615public: 616 virtual String description() { ... }; 617} 618 619class Student : public Person { 620public: 621 virtual String description() { ... }; // This is incorrect because it uses only the "virtual" keyword to indicate that the method is overridden. 622} 623``` 624 625### Const placement 626 627Use "east const" style where `const` is written on the right side of the type being qualified. See [this article](https://mariusbancila.ro/blog/2018/11/23/join-the-east-const-revolution/) for more information about east const. 628 629###### Right: 630 631```cpp 632Salt const& m_salt; 633``` 634 635###### Wrong: 636 637```cpp 638const Salt& m_salt; 639``` 640 641### Casts 642 643Before you consider a cast, please see if your problem can be solved another way that avoids the visual clutter. 644 645- Integer constants can be specified to have (some) specific sizes with postfixes like `u, l, ul` etc. The same goes for single-precision floating-point constants with `f`. 646- Working with smaller-size integers in arithmetic expressions is hard because of [implicit promotion](https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules). Generally, it is fine to use `int` and other "large" types in local variables, and possibly cast at the end. 647- If you `const_cast`, _really_ consider whether your APIs need to be adjusted in terms of their constness. Does the member function you're writing actually make sense to be `const`? 648- If you do checked casts between base and derived types, also consider your APIs. For example: Does the function being called actually need to receive the more general type or is it fine with the more specialized type? 649 650If you _do_ need to cast: **Don't use C-style casts**. The C-style cast has [complex behavior](https://en.cppreference.com/w/c/language/cast) that is undesired in many instances. Be aware of what sort of type conversion the code is trying to achieve, and use the appropriate (!) C++ cast operator, like `static_cast`, `reinterpret_cast`, `bit_cast`, `dynamic_cast` etc. 651 652There is a single exception to this rule: marking a function parameter as used with `(void)parameter;`. 653 654###### Right: 655```cpp 656MyParentClass& object = get_object(); 657// Verify the type... 658MyChildClass& casted = static_cast<MyChildClass&>(object); 659``` 660 661```cpp 662// AK::Atomic::exchange() 663 664alignas(T) u8 buffer[sizeof(T)]; 665T* ret = reinterpret_cast<T*>(buffer); 666``` 667 668```cpp 669// SeekableStream::tell() 670 671// Seek with 0 and SEEK_CUR does not modify anything despite the const_cast, 672// so it's safe to do this. 673return const_cast<SeekableStream*>(this)->seek(0, SeekMode::FromCurrentPosition); 674``` 675 676###### Wrong: 677```cpp 678// These should be static_cast. 679size_t mask_length = (size_t)((u8)-1) + 1; 680``` 681 682```cpp 683// This should be reinterpret_cast. 684return (u8 const*)string.characters_without_null_termination(); 685``` 686 687### Omission of curly braces from statement blocks 688 689Curly braces may only be omitted from `if`/`else`/`for`/`while`/etc. statement blocks if the body is a single line. 690 691Additionally, if any body of a connected if/else statement requires curly braces according to this rule, all of them do. 692 693###### Right: 694```cpp 695if (condition) 696 foo(); 697``` 698 699```cpp 700if (condition) { 701 foo(); 702 bar(); 703} 704``` 705 706```cpp 707if (condition) { 708 foo(); 709} else if (condition) { 710 bar(); 711 baz(); 712} else { 713 qux(); 714} 715``` 716 717```cpp 718for (size_t i = i; condition; ++i) { 719 if (other_condition) 720 foo(); 721} 722``` 723 724##### OK: 725 726```cpp 727if (condition) { 728 foo(); 729} 730``` 731 732###### Wrong: 733 734```cpp 735if (condition) 736 // There is a comment here. 737 foo(); 738``` 739 740```cpp 741if (condition) 742 foo(); 743else { 744 bar(); 745 baz(); 746} else 747 qux(); 748``` 749 750```cpp 751for (size_t i = i; condition; ++i) 752 if (other_condition) 753 foo(); 754```