ClickHouse/docs/fr/development/style.md

842 lines
30 KiB
Markdown
Raw Normal View History

2020-03-30 12:48:55 +00:00
---
machine_translated: true
2020-04-04 09:15:31 +00:00
machine_translated_rev: f865c9653f9df092694258e0ccdd733c339112f5
toc_priority: 68
toc_title: "Comment \xE9crire du Code C++ "
2020-03-30 12:48:55 +00:00
---
# Comment écrire Du Code C++ {#how-to-write-c-code}
2020-03-30 12:48:55 +00:00
## Recommandations Générales {#general-recommendations}
**1.** Ce qui suit sont des recommandations, pas des exigences.
**2.** Si vous modifiez du code, il est logique de suivre le formatage du code existant.
**3.** Le style de Code est nécessaire pour la cohérence. La cohérence facilite la lecture du code et facilite également la recherche du code.
**4.** Beaucoup de règles nont pas de raisons logiques; elles sont dictées par des pratiques établies.
2020-03-30 12:48:55 +00:00
## Formater {#formatting}
**1.** La plupart du formatage se fera automatiquement par `clang-format`.
**2.** Les tirets sont 4 espaces. Configurez votre environnement de développement afin quun onglet ajoute quatre espaces.
2020-03-30 12:48:55 +00:00
**3.** Les crochets douverture et de fermeture doivent être sur une ligne séparée.
2020-03-30 12:48:55 +00:00
``` cpp
inline void readBoolText(bool & x, ReadBuffer & buf)
{
char tmp = '0';
readChar(tmp, buf);
x = tmp != '0';
}
```
**4.** Si le corps entier de la fonction est un `statement` il peut donc être placé sur une seule ligne. Place des espaces autour des accolades (en plus de lespace à la fin de la ligne).
2020-03-30 12:48:55 +00:00
``` cpp
inline size_t mask() const { return buf_size() - 1; }
inline size_t place(HashValue x) const { return x & mask(); }
```
**5.** Pour les fonctions. Ne mettez pas despaces entre parenthèses.
2020-03-30 12:48:55 +00:00
``` cpp
void reinsert(const Value & x)
```
``` cpp
memcpy(&buf[place_value], &x, sizeof(x));
```
**6.** Dans `if`, `for`, `while` et dautres expressions, un espace est inséré devant le support douverture (par opposition aux appels de fonction).
2020-03-30 12:48:55 +00:00
``` cpp
for (size_t i = 0; i < rows; i += storage.index_granularity)
```
**7.** Ajouter des espaces autour des opérateurs binaires (`+`, `-`, `*`, `/`, `%`, …) 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.** Si un saut de ligne est entré, placez lopérateur sur une nouvelle ligne et augmentez le retrait avant.
2020-03-30 12:48:55 +00:00
``` 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.** Vous pouvez utiliser des espaces pour lalignement dans une ligne, si vous le souhaitez.
2020-03-30 12:48:55 +00:00
``` cpp
dst.ClickLogID = click.LogID;
dst.ClickEventID = click.EventID;
dst.ClickGoodEvent = click.GoodEvent;
```
**10.** Nutilisez pas despaces autour des opérateurs `.`, `->`.
2020-03-30 12:48:55 +00:00
Si nécessaire, lopérateur peut être renvoyé à la ligne suivante. Dans ce cas, le décalage devant celui-ci est augmenté.
2020-03-30 12:48:55 +00:00
**11.** Nutilisez pas despace pour séparer les opérateurs unaires (`--`, `++`, `*`, `&`, …) from the argument.
2020-03-30 12:48:55 +00:00
**12.** Mettre un espace après une virgule, mais pas avant. La même règle vaut pour un point-virgule à lintérieur dun `for` expression.
2020-03-30 12:48:55 +00:00
**13.** Ne pas utiliser des espaces pour séparer les `[]` opérateur.
**14.** Dans un `template <...>` expression, utiliser un espace entre les `template` et `<`; pas despace après `<` ou avant `>`.
2020-03-30 12:48:55 +00:00
``` cpp
template <typename TKey, typename TValue>
struct AggregatedStatElement
{}
```
**15.** Dans les classes et les structures, écrivez `public`, `private`, et `protected` sur le même niveau que `class/struct` et tiret le reste du code.
``` 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.** Si le même `namespace` est utilisé pour lensemble du fichier, et il ny a rien dautre significatif, un décalage nest pas nécessaire à lintérieur `namespace`.
2020-03-30 12:48:55 +00:00
**17.** Si le bloc pour un `if`, `for`, `while` ou autres expressions se compose dun seul `statement`, les accolades sont facultatives. Place de la `statement` sur une ligne séparée, à la place. Cette règle est également valable pour les imbriqués `if`, `for`, `while`, …
2020-03-30 12:48:55 +00:00
Mais si lintérieur `statement` contient des accolades ou `else` le bloc externe doit être écrit dans les accolades.
2020-03-30 12:48:55 +00:00
``` cpp
/// Finish write.
for (auto & stream : streams)
stream.second->finalize();
```
**18.** Il ne devrait pas y avoir despaces aux extrémités des lignes.
2020-03-30 12:48:55 +00:00
**19.** Les fichiers Source sont encodés en UTF-8.
**20.** Les caractères non-ASCII peuvent être utilisés dans les littéraux de chaîne.
``` cpp
<< ", " << (timer.elapsed() / chunks_stats.hits) << " μsec/hit.";
```
**21.** Nécrivez pas plusieurs expressions sur une seule ligne.
2020-03-30 12:48:55 +00:00
**22.** Groupez les sections de code à lintérieur des fonctions et séparez-les avec pas plus dune ligne vide.
2020-03-30 12:48:55 +00:00
**23.** Séparez les fonctions, les classes, etc. avec une ou deux lignes vides.
**24.** `A const` (liés à une valeur) doit être écrit avant le nom du type.
``` cpp
//correct
const char * pos
const std::string & s
//incorrect
char const * pos
```
**25.** Lors de la déclaration dun pointeur ou dune référence, le `*` et `&` les symboles doivent être séparés par des espaces des deux côtés.
2020-03-30 12:48:55 +00:00
``` cpp
//correct
const char * pos
//incorrect
const char* pos
const char *pos
```
**26.** Lors de lutilisation de types de modèles, les alias avec le `using` mot-clé (sauf dans les cas les plus simples).
2020-03-30 12:48:55 +00:00
En dautres termes, les paramètres du modèle sont indiquées que dans `using` et ne sont pas répétés dans le code.
2020-03-30 12:48:55 +00:00
`using` peut être déclaré localement, comme dans une fonction.
``` 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.** Ne déclarez pas plusieurs variables de types différents dans une instruction.
``` cpp
//incorrect
int x, *y;
```
**28.** Nutilisez pas de moulages de style C.
2020-03-30 12:48:55 +00:00
``` cpp
//incorrect
std::cerr << (int)c <<; std::endl;
//correct
std::cerr << static_cast<int>(c) << std::endl;
```
**29.** Dans les classes et les structures, groupez les membres et les fonctions séparément dans chaque portée de visibilité.
**30.** Pour les petites classes et structures, il nest pas nécessaire de séparer la déclaration de méthode de limplémentation.
2020-03-30 12:48:55 +00:00
La même chose est vraie pour les petites méthodes dans toutes les classes ou structures.
Pour les classes et les structures modélisées, ne séparez pas les déclarations de méthode de limplémentation (car sinon elles doivent être définies dans la même unité de traduction).
2020-03-30 12:48:55 +00:00
**31.** Vous pouvez envelopper des lignes à 140 caractères, au lieu de 80.
**32.** Utilisez toujours les opérateurs dincrémentation/décrémentation de préfixe si postfix nest pas requis.
2020-03-30 12:48:55 +00:00
``` cpp
for (Names::const_iterator it = column_names.begin(); it != column_names.end(); ++it)
```
## Commentaire {#comments}
**1.** Assurez-vous dajouter des commentaires pour toutes les parties non triviales du code.
2020-03-30 12:48:55 +00:00
Cest très important. Écrit le commentaire peut vous aider à réaliser que le code nest pas nécessaire, ou quil est mal conçu.
2020-03-30 12:48:55 +00:00
``` 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.** Les commentaires peuvent être aussi détaillées que nécessaire.
**3.** Placez les commentaires avant le code quils décrivent. Dans de rares cas, des commentaires peuvent venir après le code, sur la même ligne.
2020-03-30 12:48:55 +00:00
``` 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.** Les commentaires doivent être rédigés en anglais seulement.
**5.** Si vous écrivez une bibliothèque, incluez des commentaires détaillés lexpliquant dans le fichier den-tête principal.
2020-03-30 12:48:55 +00:00
**6.** Najoutez pas de commentaires qui ne fournissent pas dinformations supplémentaires. En particulier, ne laissez pas de commentaires vides comme celui-ci:
2020-03-30 12:48:55 +00:00
``` 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:
*/
```
Lexemple est emprunté à partir de la ressource http://home.tamk.fi/~jaalto/cours/coding-style/doc/désuète-code/.
2020-03-30 12:48:55 +00:00
**7.** Ne pas écrire des commentaires de déchets (auteur, date de création .. au début de chaque fichier.
**8.** Les commentaires sur une seule ligne commencent par trois barres obliques: `///` et les commentaires multi-lignes commencer avec `/**`. Ces commentaires sont pris en considération “documentation”.
REMARQUE: Vous pouvez utiliser Doxygen pour générer de la documentation à partir de ces commentaires. Mais Doxygen nest généralement pas utilisé car il est plus pratique de naviguer dans le code dans LIDE.
2020-03-30 12:48:55 +00:00
**9.** Les commentaires multilignes ne doivent pas avoir de lignes vides au début et à la fin (sauf la ligne qui ferme un commentaire multilignes).
**10.** Pour commenter le code, utilisez des commentaires de base, pas “documenting” commentaire.
**11.** Supprimez les parties commentées du code avant de valider.
**12.** Nutilisez pas de blasphème dans les commentaires ou le code.
2020-03-30 12:48:55 +00:00
**13.** Nutilisez pas de majuscules. Nutilisez pas de ponctuation excessive.
2020-03-30 12:48:55 +00:00
``` cpp
/// WHAT THE FAIL???
```
**14.** Nutilisez pas de commentaires pour créer des délimiteurs.
2020-03-30 12:48:55 +00:00
``` cpp
///******************************************************
```
**15.** Ne commencez pas les discussions dans les commentaires.
``` cpp
/// Why did you do this stuff?
```
**16.** Il nest pas nécessaire décrire un commentaire à la fin dun bloc décrivant de quoi il sagissait.
2020-03-30 12:48:55 +00:00
``` cpp
/// for
```
## Nom {#names}
**1.** Utilisez des lettres minuscules avec des traits de soulignement dans les noms des variables et des membres de la classe.
``` cpp
size_t max_block_size;
```
**2.** Pour les noms de fonctions (méthodes), utilisez camelCase commençant par une lettre minuscule.
``` cpp
std::string getName() const override { return "Memory"; }
```
**3.** Pour les noms de classes (structures), utilisez CamelCase commençant par une lettre majuscule. Les préfixes autres que I ne sont pas utilisés pour les interfaces.
``` cpp
class StorageMemory : public IStorage
```
**4.** `using` sont nommées de la même manière que les classes, ou avec `_t` sur la fin.
**5.** Noms des arguments de type de modèle: dans les cas simples, utilisez `T`; `T`, `U`; `T1`, `T2`.
Pour les cas plus complexes, suivez les règles pour les noms de classe ou ajoutez le préfixe `T`.
``` cpp
template <typename TKey, typename TValue>
struct AggregatedStatElement
```
**6.** Noms des arguments constants du modèle: suivez les règles pour les noms de variables ou utilisez `N` dans les cas simples.
``` cpp
template <bool without_www>
struct ExtractDomain
```
**7.** Pour les classes abstraites (interfaces), vous pouvez ajouter `I` préfixe.
``` cpp
class IBlockInputStream
```
**8.** Si vous utilisez une variable localement, vous pouvez utiliser le nom court.
Dans tous les autres cas, utilisez un nom qui décrit la signification.
``` cpp
bool info_successfully_loaded = false;
```
**9.** Les noms de `define`les constantes s et globales utilisent ALL\_CAPS avec des traits de soulignement.
``` cpp
#define MAX_SRC_TABLE_NAMES_TO_STORE 1000
```
**10.** Les noms de fichiers doivent utiliser le même style que leur contenu.
Si un fichier contient une seule classe, nommez-le de la même manière que la classe (CamelCase).
Si le fichier contient une seule fonction, nommez le fichier de la même manière que la fonction (camelCase).
**11.** Si le nom contient une abréviation, puis:
- Pour les noms de variables, labréviation doit utiliser des lettres minuscules `mysql_connection` (pas `mySQL_connection`).
- Pour les noms de classes et de fonctions, conservez les majuscules dans labréviation`MySQLConnection` (pas `MySqlConnection`).
2020-03-30 12:48:55 +00:00
**12.** Les arguments du constructeur utilisés uniquement pour initialiser les membres de la classe doivent être nommés de la même manière que les membres de la classe, mais avec un trait de soulignement à la fin.
``` 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"))
{
}
```
Le suffixe de soulignement peut être omis si largument nest pas utilisé dans le corps du constructeur.
2020-03-30 12:48:55 +00:00
**13.** Il ny a pas de différence dans les noms des variables locales et des membres de classe (aucun préfixe requis).
2020-03-30 12:48:55 +00:00
``` cpp
timer (not m_timer)
```
**14.** Pour les constantes dans un `enum`, utilisez CamelCase avec une lettre majuscule. ALL\_CAPS est également acceptable. Si l `enum` est non local, utilisez un `enum class`.
2020-03-30 12:48:55 +00:00
``` cpp
enum class CompressionMethod
{
QuickLZ = 0,
LZ4 = 1,
};
```
**15.** Tous les noms doivent être en anglais. La translittération des mots russes nest pas autorisé.
2020-03-30 12:48:55 +00:00
not Stroka
**16.** Les abréviations sont acceptables si elles sont bien connues (quand vous pouvez facilement trouver la signification de labréviation dans Wikipédia ou dans un moteur de recherche).
2020-03-30 12:48:55 +00:00
`AST`, `SQL`.
Not `NVDH` (some random letters)
Les mots incomplets sont acceptables si la version abrégée est dusage courant.
2020-03-30 12:48:55 +00:00
Vous pouvez également utiliser une abréviation si le nom complet est ensuite incluse dans les commentaires.
**17.** Les noms de fichiers avec le code source C++ doivent avoir `.cpp` extension. Fichiers den-tête doit avoir la `.h` extension.
2020-03-30 12:48:55 +00:00
## Comment écrire Du Code {#how-to-write-code}
2020-03-30 12:48:55 +00:00
**1.** Gestion de la mémoire.
Désallocation manuelle de la mémoire (`delete`) ne peut être utilisé que dans le code de la bibliothèque.
Dans le code de la bibliothèque, de la `delete` lopérateur ne peut être utilisé dans des destructeurs.
2020-03-30 12:48:55 +00:00
Dans le code de lapplication, la mémoire doit être libérée par lobjet qui la possède.
2020-03-30 12:48:55 +00:00
Exemple:
- Le plus simple est de placer un objet sur la pile, ou den faire un membre dune autre classe.
2020-03-30 12:48:55 +00:00
- Pour un grand nombre de petits objets, utiliser des récipients.
- Pour la désallocation automatique dun petit nombre dobjets qui résident dans le tas, utilisez `shared_ptr/unique_ptr`.
2020-03-30 12:48:55 +00:00
**2.** La gestion des ressources.
Utiliser `RAII` et voir ci-dessus.
**3.** La gestion des erreurs.
Utilisez des exceptions. Dans la plupart des cas, vous avez seulement besoin de lancer une exception, et navez pas besoin de lattraper (à cause de `RAII`).
2020-03-30 12:48:55 +00:00
Dans les applications de traitement de données hors ligne, il est souvent acceptable de ne pas attraper dexceptions.
2020-03-30 12:48:55 +00:00
Dans les serveurs qui gèrent les demandes des utilisateurs, il suffit généralement dattraper des exceptions au niveau supérieur du gestionnaire de connexion.
2020-03-30 12:48:55 +00:00
Dans les fonctions de thread, vous devez attraper et conserver toutes les exceptions pour les repasser dans le thread principal après `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();
```
Ne cachez jamais les exceptions sans les manipuler. Ne mettez jamais aveuglément toutes les exceptions au journal.
``` cpp
//Not correct
catch (...) {}
```
Si vous devez ignorer certaines exceptions, ne le faites que pour des exceptions spécifiques et repensez le reste.
``` cpp
catch (const DB::Exception & e)
{
if (e.code() == ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION)
return nullptr;
else
throw;
}
```
Lorsque vous utilisez des fonctions avec des codes de réponse ou `errno` toujours vérifier le résultat et de lever une exception en cas derreur.
2020-03-30 12:48:55 +00:00
``` cpp
if (0 != close(fd))
throwFromErrno("Cannot close file " + file_name, ErrorCodes::CANNOT_CLOSE_FILE);
```
`Do not use assert`.
**4.** Les types dException.
2020-03-30 12:48:55 +00:00
Il nest pas nécessaire dutiliser une hiérarchie dexceptions complexe dans le code de lapplication. Le texte dexception doit être compréhensible pour un administrateur système.
2020-03-30 12:48:55 +00:00
**5.** Lancer des exceptions de destructeurs.
Ce nest pas recommandé, mais il est permis.
2020-03-30 12:48:55 +00:00
Utilisez les options suivantes:
- Créer une fonction (`done()` ou `finalize()`) qui vont faire tout le travail en amont qui pourrait conduire à une exception. Si cette fonction a été appelée, il ne devrait y avoir aucune exception dans le destructeur plus tard.
- Les tâches trop complexes (comme lenvoi de messages sur le réseau) peuvent être placées dans une méthode distincte que lutilisateur de la classe devra appeler avant la destruction.
- Si il y a une exception dans le destructeur, il est préférable de lenregistrer que de le cacher (si lenregistreur est disponible).
2020-03-30 12:48:55 +00:00
- Dans les applications simples, il est acceptable de compter sur `std::terminate` (pour les cas de `noexcept` par défaut en C++11) pour gérer les exceptions.
**6.** Blocs de code anonymes.
Vous pouvez créer un bloc de code séparé à lintérieur dune seule fonction afin de rendre certaines variables locales, de sorte que les destructeurs sont appelés à la sortie du bloc.
2020-03-30 12:48:55 +00:00
``` cpp
Block block = data.in->read();
{
std::lock_guard<std::mutex> lock(mutex);
data.ready = true;
data.block = block;
}
ready_any.set();
```
**7.** Multithreading.
Dans les programmes de traitement de données hors ligne:
- Essayez dobtenir les meilleures performances possibles sur un seul noyau CPU. Vous pouvez ensuite paralléliser votre code si nécessaire.
2020-03-30 12:48:55 +00:00
Dans les applications serveur:
- Utiliser le pool de threads pour traiter les demandes. À ce stade, nous navons pas eu de tâches nécessitant un changement de contexte dans lespace utilisateur.
2020-03-30 12:48:55 +00:00
La fourche nest pas utilisé pour la parallélisation.
2020-03-30 12:48:55 +00:00
**8.** Synchronisation des threads.
Souvent, il est possible de faire en sorte que différents threads utilisent différentes cellules de mémoire (encore mieux: différentes lignes de cache,) et de ne pas utiliser de synchronisation de thread (sauf `joinAll`).
Si la synchronisation est nécessaire, dans la plupart des cas, il suffit dutiliser mutex sous `lock_guard`.
2020-03-30 12:48:55 +00:00
Dans dautres cas, utilisez des primitives de synchronisation système. Ne pas utiliser occupé attendre.
2020-03-30 12:48:55 +00:00
Les opérations atomiques ne doivent être utilisées que dans les cas les plus simples.
Nessayez pas dimplémenter des structures de données sans verrou à moins quil ne sagisse de votre principal domaine dexpertise.
2020-03-30 12:48:55 +00:00
**9.** Pointeurs vs références.
Dans la plupart des cas, préférez les références.
**10.** const.
Utiliser des références constantes, des pointeurs vers des constantes, `const_iterator` et const méthodes.
Considérer `const` pour être par défaut et utiliser non-`const` seulement quand cest nécessaire.
2020-03-30 12:48:55 +00:00
Lors du passage de variables par valeur, en utilisant `const` habituellement ne fait pas de sens.
**11.** non signé.
Utiliser `unsigned` si nécessaire.
**12.** Les types numériques.
Utiliser les types `UInt8`, `UInt16`, `UInt32`, `UInt64`, `Int8`, `Int16`, `Int32`, et `Int64` ainsi que `size_t`, `ssize_t`, et `ptrdiff_t`.
Nutilisez pas ces types pour les nombres: `signed/unsigned long`, `long long`, `short`, `signed/unsigned char`, `char`.
2020-03-30 12:48:55 +00:00
**13.** Passer des arguments.
Passer des valeurs complexes par référence (y compris `std::string`).
Si une fonction capture la propriété dun objet créé dans le tas, définissez le type dargument `shared_ptr` ou `unique_ptr`.
2020-03-30 12:48:55 +00:00
**14.** Les valeurs de retour.
Dans la plupart des cas, il suffit dutiliser `return`. Ne pas écrire `[return std::move(res)]{.strike}`.
2020-03-30 12:48:55 +00:00
Si la fonction alloue un objet sur le tas et le renvoie, utilisez `shared_ptr` ou `unique_ptr`.
Dans de rares cas, vous devrez peut-être renvoyer la valeur via un argument. Dans ce cas, largument doit être une référence.
2020-03-30 12:48:55 +00:00
``` 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.** espace de noms.
Il nest pas nécessaire dutiliser une `namespace` pour le code de lapplication.
2020-03-30 12:48:55 +00:00
Les petites bibliothèques nont pas besoin de cela non plus.
2020-03-30 12:48:55 +00:00
Pour les bibliothèques moyennes et grandes, mettez tout dans un `namespace`.
Dans la bibliothèque `.h` fichier, vous pouvez utiliser `namespace detail` pour masquer les détails dimplémentation non nécessaires pour le code de lapplication.
2020-03-30 12:48:55 +00:00
Dans un `.cpp` fichier, vous pouvez utiliser un `static` ou un espace de noms anonyme pour masquer les symboles.
Aussi, un `namespace` peut être utilisé pour un `enum` pour éviter que les noms correspondants ne tombent dans un `namespace` (mais il est préférable dutiliser un `enum class`).
2020-03-30 12:48:55 +00:00
**16.** Initialisation différée.
Si des arguments sont requis pour linitialisation, vous ne devriez normalement pas écrire de constructeur par défaut.
2020-03-30 12:48:55 +00:00
Si plus tard, vous devez retarder linitialisation, vous pouvez ajouter un constructeur par défaut qui créera un objet invalide. Ou, pour un petit nombre dobjets, vous pouvez utiliser `shared_ptr/unique_ptr`.
2020-03-30 12:48:55 +00:00
``` cpp
Loader(DB::Connection * connection_, const std::string & query, size_t max_block_size_);
/// For deferred initialization
Loader() {}
```
**17.** Des fonctions virtuelles.
Si la classe nest pas destinée à une utilisation polymorphe, vous navez pas besoin de rendre les fonctions virtuelles. Ceci sapplique également pour le destructeur.
2020-03-30 12:48:55 +00:00
**18.** Encodage.
Utilisez UTF-8 partout. Utiliser `std::string`et`char *`. Ne pas utiliser de `std::wstring`et`wchar_t`.
**19.** Journalisation.
Voir les exemples partout dans le code.
Avant de valider, supprimez toute journalisation sans signification et de débogage, ainsi que tout autre type de sortie de débogage.
Lenregistrement des cycles doit être évité, même au niveau de la Trace.
2020-03-30 12:48:55 +00:00
Les journaux doivent être lisibles à tout niveau denregistrement.
2020-03-30 12:48:55 +00:00
La journalisation ne doit être utilisée que dans le code de lapplication, pour la plupart.
2020-03-30 12:48:55 +00:00
Les messages du journal doivent être écrits en anglais.
Le journal devrait de préférence être compréhensible pour ladministrateur système.
2020-03-30 12:48:55 +00:00
Nutilisez pas de blasphème dans le journal.
2020-03-30 12:48:55 +00:00
Utilisez Lencodage UTF-8 dans le journal. Dans de rares cas, vous pouvez utiliser des caractères non-ASCII dans le journal.
2020-03-30 12:48:55 +00:00
**20.** Dentrée-sortie.
2020-03-30 12:48:55 +00:00
Ne pas utiliser de `iostreams` dans les cycles internes qui sont critiques pour les performances de lapplication (et ne jamais utiliser `stringstream`).
2020-03-30 12:48:55 +00:00
Lutilisation de la `DB/IO` la bibliothèque la place.
2020-03-30 12:48:55 +00:00
**21.** La Date et lheure.
2020-03-30 12:48:55 +00:00
Voir la `DateLUT` bibliothèque.
**22.** comprendre.
Toujours utiliser `#pragma once` au lieu dinclure des gardes.
2020-03-30 12:48:55 +00:00
**23.** utiliser.
`using namespace` nest pas utilisé. Vous pouvez utiliser `using` avec quelque chose de spécifique. Mais faire local à lintérieur dune classe ou dune fonction.
2020-03-30 12:48:55 +00:00
**24.** Ne pas utiliser de `trailing return type` pour les fonctions, sauf si nécessaire.
``` cpp
[auto f() -&gt; void;]{.strike}
```
**25.** Déclaration et initialisation des variables.
``` cpp
//right way
std::string s = "Hello";
std::string s{"Hello"};
//wrong way
auto s = std::string{"Hello"};
```
**26.** Pour les fonctions virtuelles, écrire `virtual` dans la classe de base, mais décrire `override` plutôt `virtual` dans les classes descendantes.
2020-03-30 12:48:55 +00:00
## Fonctionnalités inutilisées De C++ {#unused-features-of-c}
2020-03-30 12:48:55 +00:00
**1.** Lhéritage virtuel nest pas utilisé.
2020-03-30 12:48:55 +00:00
**2.** Les spécificateurs dException de C++03 ne sont pas utilisés.
2020-03-30 12:48:55 +00:00
## Plate {#platform}
**1.** Nous écrivons du code pour une plate-forme spécifique.
Mais toutes choses étant égales par ailleurs, le code multi-plateforme ou portable est préféré.
**2.** Langue: C++17.
**3.** Compilateur: `gcc`. En ce moment (décembre 2017), le code est compilé en utilisant la version 7.2. (Il peut également être compilé en utilisant `clang 4`.)
La bibliothèque standard est utilisée (`libstdc++` ou `libc++`).
**4.**OS: Linux Ubuntu, pas plus vieux que précis.
**5.**Le Code est écrit pour larchitecture CPU x86\_64.
2020-03-30 12:48:55 +00:00
Le jeu Dinstructions CPU est lensemble minimum pris en charge parmi nos serveurs. Actuellement, il sagit de SSE 4.2.
2020-03-30 12:48:55 +00:00
**6.** Utiliser `-Wall -Wextra -Werror` drapeaux de compilation.
**7.** Utilisez la liaison statique avec toutes les bibliothèques sauf celles qui sont difficiles à connecter statiquement (voir la sortie de la `ldd` commande).
**8.** Le Code est développé et débogué avec les paramètres de version.
## Outils {#tools}
**1.** KDevelop est un bon IDE.
**2.** Pour le débogage, utilisez `gdb`, `valgrind` (`memcheck`), `strace`, `-fsanitize=...`, ou `tcmalloc_minimal_debug`.
**3.** Pour le profilage, utilisez `Linux Perf`, `valgrind` (`callgrind`), ou `strace -cf`.
**4.** Les Sources sont dans Git.
**5.** Assemblée utilise `CMake`.
**6.** Les programmes sont libérés en utilisant `deb` paquet.
**7.** Les Commits à master ne doivent pas casser la construction.
Bien que seules les révisions sélectionnées soient considérées comme réalisables.
**8.** Faire sengage aussi souvent que possible, même si le code nest que partiellement prêt.
2020-03-30 12:48:55 +00:00
Utilisez des branches à cet effet.
Si votre code dans le `master` la branche nest pas constructible pourtant, lexclure de la construction avant que le `push`. Vous devrez le terminer ou lenlever dans quelques jours.
2020-03-30 12:48:55 +00:00
**9.** Pour les modifications non triviales, utilisez les branches et publiez-les sur le serveur.
**10.** Le code inutilisé est supprimé du référentiel.
## Bibliothèque {#libraries}
**1.** La bibliothèque standard C++14 est utilisée (les extensions expérimentales sont autorisées), ainsi que `boost` et `Poco` Framework.
**2.** Si nécessaire, vous pouvez utiliser toutes les bibliothèques bien connues disponibles dans le package OS.
Sil existe déjà une bonne solution, utilisez-la, même si cela signifie que vous devez installer une autre bibliothèque.
2020-03-30 12:48:55 +00:00
(Mais soyez prêt à supprimer les mauvaises bibliothèques du code.)
**3.** Vous pouvez installer une bibliothèque qui nest pas dans les paquets, les paquets nont pas ce que vous souhaitez ou avez une version périmée ou le mauvais type de compilation.
2020-03-30 12:48:55 +00:00
**4.** Si la Bibliothèque est petite et na pas son propre système de construction complexe, placez les fichiers source dans le `contrib` dossier.
2020-03-30 12:48:55 +00:00
**5.** La préférence est toujours donnée aux bibliothèques déjà utilisées.
## Recommandations Générales {#general-recommendations-1}
**1.** Écrivez aussi peu de code que possible.
**2.** Essayez la solution la plus simple.
**3.** Nécrivez pas de code tant que vous ne savez pas comment cela va fonctionner et comment la boucle interne fonctionnera.
2020-03-30 12:48:55 +00:00
**4.** Dans les cas les plus simples, utilisez `using` au lieu de classes ou des structures.
**5.** Si possible, nécrivez pas de constructeurs de copie, dopérateurs daffectation, de destructeurs (autres que Virtuels, si la classe contient au moins une fonction virtuelle), de constructeurs de déplacement ou dopérateurs daffectation de déplacement. En dautres termes, les fonctions générées par le compilateur doivent fonctionner correctement. Vous pouvez utiliser `default`.
2020-03-30 12:48:55 +00:00
**6.** La simplification du Code est encouragée. Réduire la taille de votre code si possible.
## Recommandations Supplémentaires {#additional-recommendations}
**1.** Spécifier explicitement `std::` pour les types de `stddef.h`
nest pas recommandé. En dautres termes, nous vous recommandons décriture `size_t` plutôt `std::size_t` parce que cest plus court.
2020-03-30 12:48:55 +00:00
Il est acceptable dajouter `std::`.
2020-03-30 12:48:55 +00:00
**2.** Spécifier explicitement `std::` pour les fonctions de la bibliothèque C standard
nest pas recommandé. En dautres termes, écrire `memcpy` plutôt `std::memcpy`.
2020-03-30 12:48:55 +00:00
La raison en est quil existe des fonctions non standard similaires, telles que `memmem`. Nous utilisons ces fonctions à loccasion. Ces fonctions nexistent pas dans `namespace std`.
2020-03-30 12:48:55 +00:00
Si vous écrivez `std::memcpy` plutôt `memcpy` partout, puis `memmem` sans `std::` va sembler étrange.
Néanmoins, vous pouvez toujours utiliser `std::` si vous le souhaitez.
**3.** Utilisation des fonctions de C lorsque les mêmes sont disponibles dans la bibliothèque C++ standard.
Ceci est acceptable sil est plus efficace.
2020-03-30 12:48:55 +00:00
Par exemple, lutilisation `memcpy` plutôt `std::copy` pour copier de gros morceaux de mémoire.
2020-03-30 12:48:55 +00:00
**4.** Arguments de fonction multiligne.
Lun des styles demballage suivants est autorisé:
2020-03-30 12:48:55 +00:00
``` 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)
```
[Article Original](https://clickhouse.tech/docs/en/development/style/) <!--hide-->