├── LICENSE ├── README.md └── main.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Kelvin S. do Prado 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Guia Rápido de Boas Práticas em C++ 2 | 3 | # Sumário 4 | 5 | 1. [Introdução](#introdução) 6 | 2. [Estilo de Código](#estilo-de-código) 7 | 2.1. [Nomes de Variáveis](#nomes-de-variáveis) 8 | 2.2. [Nomes de Constantes](#nomes-de-constantes) 9 | 2.3. [Nomes de Funções](#nomes-de-funções) 10 | 2.4. [Nomes de Classes](#nomes-de-classes) 11 | 2.5. [Comentários](#comentários) 12 | 2.6. [Indentação](#indentação) 13 | 2.7. [Não utilize números mágicos](#não-utilize-números-mágicos) 14 | 2.8. [Inclua guards](#inclua-guards) 15 | 2.9. [Sempre utilize chaves](#sempre-utilize-chaves) 16 | 2.10. [Mantenha as linhas com um comprimento razoável](#mantenha-as-linhas-com-um-comprimento-razoável) 17 | 2.11. [Utilize aspas duplas para incluir arquivos locais](#utilize-aspas-duplas-para-incluir-arquivos-locais) 18 | 2.12. [Utilize constantes sempre que possível](#utilize-constantes-sempre-que-possível) 19 | 2.13. [Passe ou retorne tipos simples por valor](#passe-ou-retorne-tipos-simples-por-valor) 20 | 2.14. [Utilize double em vez de float](#utilize-double-em-vez-de-float) 21 | 3. [Dicas](#dicas) 22 | 3.1. [Lembre-se de deletar os ponteiros](#lembre-se-de-deletar-os-ponteiros) 23 | 3.2. [Utilize ponteiros inteligentes](#utilize-ponteiros-inteligentes) 24 | 3.3. [Códigos não utilizados devem ser deletados](#códigos-não-utilizados-devem-ser-deletados) 25 | 3.4. [Evite métodos com muitos parâmetros](#evite-métodos-com-muitos-parâmetros) 26 | 3.5. [Utilize espaços em branco para melhor visualização](#utilize-espaços-em-branco-para-melhor-visualização) 27 | 3.6. [Limite o escopo das variáveis](#limite-o-escopo-das-variáveis) 28 | 3.7. [Prefira `++i` em vez de `i++`](#refira-`++i`-em-vez-de-`i++`) 29 | 3.8. [Pare e dê uma volta](#pare-e-dê-uma-volta) 30 | 4. [Referências](#referências) 31 | 32 | # Introdução 33 | 34 | Este documento apresenta um guia rápido de boas práticas em **C++** e é voltado para iniciantes na linguagem mas também pode ser útil para desenvolvedores intermediários. 35 | 36 | As informações apresentadas neste guia foram obtidas de alguns materiais (livros e blogs), citados nas referências, e de conhecimento prático pessoal. 37 | 38 | Achei importante criar este material em PT_BR pois a maioria dos materiais encontrados estão escritos na língua do Tio Sam, o que dificulta um pouco o entendimento, principalmente para os iniciantes. Além disso, tentei resumir de forma bem prática e direta alguns conceitos básicos de forma que este material possa ser utilizado como um guia de consulta rápida. 39 | 40 | Caso você não concorde com algo ou tenha alguma informação a acrescentar, sinta-se à vontade para criar issues ou enviar pull requests. 41 | 42 | # Estilo de Código 43 | 44 | Todo projeto possui seu estilo de código, alguns com algumas práticas mais avançadas e outros praticamente sem nenhum padrão. Porém, o estilo de um código tem grande impacto em sua respectiva legibilidade. Sendo assim, é importante investir algumas horas do seu tempo para estudar um pouco sobre isso, além de realizar revisões de código sempre que possível, garantindo um código mais fácil de manter e evoluir. 45 | 46 | ## Nomes de Variáveis 47 | 48 | Variáveis devem sempre começar com letra minúscula, por exemplo: 49 | 50 | :heavy_check_mark: Bom 51 | ```c++ 52 | string myWeirdVariable; 53 | // ou 54 | string my_weird_variable; 55 | ``` 56 | 57 | :x: Ruim 58 | ```c++ 59 | string MyWeird_Variable2; 60 | // ou 61 | string My_weirdVariable_3; 62 | ``` 63 | 64 | Utilize um padrão já conhecido para a declaração das variáveis, como por exemplo: 65 | 66 | - [CamelCase][1] 67 | - [snake_case][2] 68 | 69 | Eu pessoalmente prefiro utilizar o padrão **CamelCase** e vejo muita gente utilizando ele também. Mas isso não significa que você deva necessariamente utilizá-lo. O mais importante é manter a consistência na declaração das variáveis. 70 | 71 | ## Nomes de Constantes 72 | 73 | Constantes devem ser declaradas sempre em letras maiúsculas (caixa alta): 74 | 75 | :heavy_check_mark: Bom 76 | ```c++ 77 | const double PI = 3.14159; 78 | ``` 79 | 80 | :x: Ruim 81 | ```c++ 82 | const double pi = 3.14159; 83 | ``` 84 | 85 | ## Nomes de Funções 86 | 87 | Nomes de funções devem começar com a primeira letra minúscula, assim como as variáveis: 88 | 89 | :heavy_check_mark: Bom 90 | ```c++ 91 | void myFunction(); 92 | ``` 93 | 94 | :x: Ruim 95 | ```c++ 96 | void MyFunction(); 97 | ``` 98 | 99 | :x: Pior ainda 100 | ```c++ 101 | void My_Function(); 102 | ``` 103 | 104 | ## Nomes de Classes 105 | 106 | Nomes de classes devem começar com a primeira letra maiúscula e seguir o padrão CamelCase (preferencialmente): 107 | 108 | :heavy_check_mark: Bom 109 | ```c++ 110 | class LinkedList 111 | ``` 112 | 113 | :x: Ruim 114 | ```c++ 115 | class linkedList 116 | ``` 117 | 118 | ## Comentários 119 | 120 | Utilize `//` para blocos de comentários (comentários de múltiplas linhas) dentro de funções, por exemplo: 121 | 122 | ```c++ 123 | bool equal( int value1, int value2 ) 124 | { 125 | // Compara dois valores e retorna 126 | // verdadeiro se os valores são iguais 127 | if( value1 == value2 ) 128 | { 129 | return true; 130 | } 131 | return false; 132 | } 133 | ``` 134 | 135 | Caso seja necessário comentar um bloco de código para debugar ou por algum outro motivo, você não terá problemas, por exemplo: 136 | 137 | :heavy_check_mark: Bom 138 | ```c++ 139 | bool equal( int value1, int value2 ) 140 | { 141 | /* 142 | // Compara dois valores e retorna 143 | // verdadeiro se os valores são iguais 144 | if( value1 == value2 ) 145 | { 146 | return true; 147 | } 148 | */ 149 | return false; 150 | } 151 | ``` 152 | 153 | Caso contrário, não seria possível comentar o bloco de código inteiro, por exemplo: 154 | 155 | :x: Ruim 156 | ```c++ 157 | bool equal( int value1, int value2 ) 158 | { 159 | /* 160 | /* 161 | * Compara dois valores e retorna 162 | * verdadeiro se os valores são iguais 163 | */ 164 | if( value1 == value2 ) 165 | { 166 | return true; 167 | } 168 | */ 169 | return false; 170 | } 171 | ``` 172 | 173 | Além disso, na minha opinião, quando é utilizado `//` para comentários de múltiplas linhas o código parece ser mais legível do que quando se utiliza `/* */`. 174 | 175 | ## Indentação 176 | 177 | O mais comum é a indentação ou recuo de código utilizando 4 espaços, 2 espaços ou 1 tab. Isso pode mudar de projeto para projeto ou mesmo de acordo com a linguagem de programação. Eu pessoalmente costumo utilizar 4 espaços e acredito que este seja o padrão mais utilizado pelos desenvolvedores. É possível configurar a IDE ou o editor para utilizar por padrão o indentação desejada. 178 | 179 | ## Não utilize números mágicos 180 | 181 | Não utilize números 'mágicos', por exemplo: 182 | 183 | :x: Ruim 184 | ```c++ 185 | double calc( double value ) 186 | { 187 | return value * 3.14159; 188 | } 189 | ``` 190 | 191 | Nestes casos opte por definir uma constante, por exemplo: 192 | 193 | :heavy_check_mark: Bom 194 | ```c++ 195 | const double PI = 3.14159; 196 | 197 | double calc( double value ) 198 | { 199 | return value * PI; 200 | } 201 | ``` 202 | 203 | Mas utilize, SIM, números, quando isso fizer sentido, por exemplo: 204 | 205 | :heavy_check_mark: Bom 206 | ```c++ 207 | double calc( double value ) 208 | { 209 | return value * 2; 210 | } 211 | ``` 212 | 213 | :x: Ruim 214 | ```c++ 215 | #define TWO 2 216 | 217 | double calc( double value ) 218 | { 219 | return value * TWO; 220 | } 221 | ``` 222 | 223 | ## Inclua guards 224 | 225 | Arquivos de cabeçalho (header files) devem utilizar guards para evitar problemas com a inclusão do mesmo arquivo múltiplas vezes e previnir conflitos com cabeçalhos de outros projetos: 226 | 227 | :heavy_check_mark: Bom 228 | ```c++ 229 | #ifndef MYCLASS_H 230 | #define MYCLASS_H 231 | 232 | class MyClass 233 | { 234 | public: 235 | void myFunc(); 236 | }; 237 | 238 | #endif 239 | ``` 240 | 241 | :x: Ruim 242 | ```c++ 243 | class MyClass 244 | { 245 | public: 246 | void myFunc(); 247 | }; 248 | ``` 249 | 250 | ## Sempre utilize chaves 251 | 252 | Sempre utilize chaves mesmo quando existe apenas uma linha de código dentro de um bloco. A não utilização de chaves pode causar erros semânticos no código, por exemplo: 253 | 254 | :heavy_check_mark: Bom 255 | ```c++ 256 | int sum = 0; 257 | for (int i = 0; i < 15; ++i) 258 | { 259 | ++sum; 260 | std::cout << i << std::endl; 261 | } 262 | ``` 263 | 264 | :x: Ruim 265 | ```c++ 266 | for (int i = 0; i < 15; ++i) 267 | std::cout << i << std::endl; 268 | ``` 269 | 270 | :x: Erro semântico 271 | ```c++ 272 | int sum = 0; 273 | for (int i = 0; i < 15; ++i) 274 | ++sum; 275 | std::cout << i << std::endl; 276 | ``` 277 | 278 | ## Mantenha as linhas com um comprimento razoável 279 | 280 | Mantenha as linhas com um comprimento razoável. Caso a linha seja muito extensa, tenha muitos caracteres, vale a pena quebrá-la em múltiplas linhas, por exemplo: 281 | 282 | :x: Ruim 283 | ```c++ 284 | if( (x == 1 && y == 2 && myFunction() == true) || (x == 0 && y == 0 && myFunction() == false) ) 285 | { 286 | 287 | } 288 | ``` 289 | 290 | :heavy_check_mark: Bom 291 | ```c++ 292 | if( (x == 1 && y == 2 && myFunction() == true) || 293 | (x == 0 && y == 0 && myFunction() == false) ) 294 | { 295 | 296 | } 297 | ``` 298 | 299 | ## Utilize aspas duplas para incluir arquivos locais 300 | 301 | Utilize aspas duplas (`""`) para incluir arquivos locais. 302 | 303 | :x: Ruim 304 | ```c++ 305 | #include 306 | #include 307 | ``` 308 | 309 | :heavy_check_mark: Bom 310 | ```c++ 311 | #include 312 | #include "MyHeader.hpp" 313 | ``` 314 | 315 | ## Utilize constantes sempre que possível 316 | 317 | Utilize `const` sempre que possível. `const` avisa ao compilador que a variável é imutável. Isto auxilia o compilador a otimizar o código e ajuda o programador a saber se uma função tem "efeitos colaterais". Ainda, a utilização de `const &` previne o compilador de copiar dados desnecessariamente. 318 | 319 | :x: Ruim 320 | ```c++ 321 | class MyClass 322 | { 323 | public: 324 | void do_something(int i); 325 | void do_something(std::string str); 326 | }; 327 | ``` 328 | 329 | :heavy_check_mark: Bom 330 | ```c++ 331 | class MyClass 332 | { 333 | public: 334 | void do_something(const int i); 335 | void do_something(const std::string &str); 336 | }; 337 | ``` 338 | 339 | ## Passe ou retorne tipos simples por valor 340 | 341 | Não passe ou retorne tipos simples por referência, mas sim por valor: 342 | 343 | :x: Ruim 344 | ```c++ 345 | class MyClass 346 | { 347 | public: 348 | explicit MyClass(const int& t_int_value) 349 | : m_int_value(t_int_value) 350 | { 351 | } 352 | 353 | const int& get_int_value() const 354 | { 355 | return m_int_value; 356 | } 357 | 358 | private: 359 | int m_int_value; 360 | } 361 | ``` 362 | 363 | Se o valor não será alterado é possível utilizar `const`. 364 | 365 | :heavy_check_mark: Bom 366 | ```c++ 367 | class MyClass 368 | { 369 | public: 370 | explicit MyClass(const int t_int_value) 371 | : m_int_value(t_int_value) 372 | { 373 | } 374 | 375 | int get_int_value() const 376 | { 377 | return m_int_value; 378 | } 379 | 380 | private: 381 | int m_int_value; 382 | } 383 | ``` 384 | 385 | Utilize a passagem de parâmetro por referência para objetos, vetores, etc. 386 | 387 | ## Utilize double em vez de float 388 | 389 | A utilização de `float` irá reduzir a precisão. Porém, em operações com vetores `float` pode ser mais rápido que `double` se você puder sacrificar a precisão. 390 | 391 | Contudo, `double` é a opção padrão recomendada já que este é o tipo padrão para valores de ponto flutuante em C++. 392 | 393 | # Dicas 394 | 395 | Nesta seção você irá encontrar algumas dicas importantes que podem ser úteis durante o desenvolvimento. 396 | 397 | ## Lembre-se de deletar os ponteiros 398 | 399 | Lembre-se de sempre deletar os ponteiros para liberar a memória alocada. Além de deletar o ponteiro, eu costumo definir ele como `NULL` para evitar [comportamento indefinido][3] (isso faz mais sentido quando o ponteiro está no escopo da classe e não da função). 400 | 401 | :heavy_check_mark: Bom 402 | ```c++ 403 | double myFunction(double value1, double value2) 404 | { 405 | Calculator *calc = new Calculator(); 406 | 407 | double result = calc->sum(value1, value2); 408 | 409 | delete calc; 410 | calc = NULL; 411 | 412 | return result; 413 | } 414 | ``` 415 | 416 | :x: Ruim 417 | ```c++ 418 | double myFunction(double value1, double value2) 419 | { 420 | Calculator *calc = new Calculator(); 421 | return calc->sum(value1, value2); 422 | } 423 | ``` 424 | 425 | Contudo, opte por utilizar [ponteiros inteligentes][4] (próximo tópico) sempre que possível. 426 | 427 | ## Utilize ponteiros inteligentes 428 | 429 | Sempre que possível utilize ponteiros inteligentes (smart pointers) ao invés de utilizar os ponteiros tradicionais (raw pointers). O uso de ponteiros inteligentes pode evitar diversos problemas, dentre eles o [vazamento de memória][5] (memory leak). 430 | 431 | :heavy_check_mark: Bom 432 | ```c++ 433 | void ponteiroInteligente() 434 | { 435 | // Declare um ponteiro inteligente na pilha e passe o ponteiro tradicional (ponteiro bruto) 436 | unique_ptr pSong(new Song(L"Nothing on You", L"Bruno Mars")); 437 | 438 | // Utilize pSong... 439 | // Exemplo: pSong->duration(); 440 | // pSong é deletado automaticamente ao fim da função 441 | } 442 | ``` 443 | 444 | :x: Ruim 445 | ```c++ 446 | void ponteiroTradicional() 447 | { 448 | // Utilizando ponteiro tradicional (ponteiro bruto) 449 | Song* pSong = new Song(L"Nothing on You", L"Bruno Mars"); 450 | 451 | // Utilize pSong... 452 | // Exemplo: pSong->duration(); 453 | 454 | // Não esqueça de deletar o ponteiro 455 | delete pSong; 456 | } 457 | ``` 458 | 459 | Exemplo modificado de: https://msdn.microsoft.com/pt-br/library/hh279674.aspx 460 | 461 | ## Códigos não utilizados devem ser deletados 462 | 463 | Códigos não mais utilizados (comentados) devem ser deletados, por exemplo: 464 | 465 | :x: Ruim 466 | ```c++ 467 | bool equal( int value1, int value2 ) 468 | { 469 | /* 470 | if( value1 < value2 || value1 > value2 ) 471 | { 472 | return false; 473 | } 474 | else 475 | { 476 | return true; 477 | } 478 | */ 479 | // Compara dois valores e retorna 480 | // verdadeiro se os valores são iguais 481 | if( value1 == value2 ) 482 | { 483 | return true; 484 | } 485 | return false; 486 | } 487 | ``` 488 | 489 | :heavy_check_mark: Bom 490 | ```c++ 491 | bool equal( int value1, int value2 ) 492 | { 493 | // Compara dois valores e retorna 494 | // verdadeiro se os valores são iguais 495 | if( value1 == value2 ) 496 | { 497 | return true; 498 | } 499 | return false; 500 | } 501 | ``` 502 | 503 | Assim o código fica mais limpo e mais fácil de compreender. 504 | 505 | ## Evite métodos com muitos parâmetros 506 | 507 | Sempre que possível evite a utilização de muitos parâmetros em métodos. Métodos com muitos parâmetros são geralmente difíceis de compreender. Se necessário refatore o método. 508 | 509 | :x: Ruim 510 | ```c++ 511 | void showUserInformation(string firstName, string lastName, string gender, int age, double height, double weight); 512 | ``` 513 | 514 | :heavy_check_mark: Bom 515 | ```c++ 516 | // Onde 'User' é um objeto/estrutura de dados 517 | void showUserInformation(User &user); 518 | ``` 519 | 520 | ## Utilize espaços em branco para melhor visualização 521 | 522 | Utilize espaços em branco para melhor visualização, por exemplo: 523 | 524 | :heavy_check_mark: Bom 525 | ```c++ 526 | if( (majorVersion == 2 && minorVersion == 5) || majorVersion >= 3 ) 527 | ``` 528 | 529 | :x: Ruim 530 | ```c++ 531 | if((majorVersion==2 && minorVersion==5) || majorVersion>=3) 532 | ``` 533 | 534 | :x: Pior ainda 535 | ```c++ 536 | if((majorVersion==2&&minorVersion==5)||majorVersion>=3) 537 | ``` 538 | 539 | ## Limite o escopo das variáveis 540 | 541 | Sempre que possível limite o escopo das variáveis: 542 | 543 | :heavy_check_mark: Bom 544 | ```c++ 545 | for (int i = 0; i < 15; ++i) 546 | { 547 | MyObject obj(i); 548 | // Faça algo com obj 549 | } 550 | ``` 551 | 552 | :x: Ruim 553 | ```c++ 554 | MyObject obj; // inicialização de objeto sem sentido 555 | for (int i = 0; i < 15; ++i) 556 | { 557 | obj = MyObject(i); // operação de atribuição desnecessária 558 | // Faça algo com obj 559 | } 560 | // obj ainda está ocupando memória sem motivo 561 | ``` 562 | 563 | ## Prefira `++i` em vez de `i++` 564 | 565 | Ainda que `i++` seja semanticamente correto, o pré-incremento (`++i`) é mais rápido que pós-incremento (`i++`), uma vez que não requer uma cópia do objeto. 566 | 567 | :x: Ruim 568 | ```c++ 569 | for (int i = 0; i < 15; i++) 570 | { 571 | std::cout << i << '\n'; 572 | } 573 | ``` 574 | 575 | :heavy_check_mark: Bom 576 | ```c++ 577 | for (int i = 0; i < 15; ++i) 578 | { 579 | std::cout << i << '\n'; 580 | } 581 | ``` 582 | 583 | Mesmo que os compiladores mais modernos otimizem esses dois laços para o mesmo código assembly, a utilização de `++i` ainda é uma boa prática. 584 | 585 | ## Pare e dê uma volta 586 | 587 | Sempre que estiver empacado na solução de um problema, respire fundo e vá dar uma volta ou fazer alguma outra atividade por um certo período de tempo. Isso ajuda a esfriar um pouco a cabeça e pensar em uma solução mais claramente. 588 | 589 | # Referências 590 | 591 | **C++ Best Practices**: https://www.gitbook.com/book/lefticus/cpp-best-practices/details 592 | 593 | **Google C++ Style Guide**: https://google.github.io/styleguide/cppguide.html 594 | 595 | **10 most voted C++ best practices**: http://codergears.com/Blog/?p=1957 596 | 597 | [1]: https://pt.wikipedia.org/wiki/CamelCase 598 | [2]: https://en.wikipedia.org/wiki/Snake_case 599 | [3]: https://pt.wikipedia.org/wiki/Comportamento_indefinido 600 | [4]: https://pt.wikipedia.org/wiki/Ponteiro_inteligente 601 | [5]: https://pt.wikipedia.org/wiki/Vazamento_de_mem%C3%B3ria 602 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Guia Rapido de Boas Praticas em C++" << endl; 8 | return 0; 9 | } --------------------------------------------------------------------------------