QGIS コーディング基準¶
これらの基準は、すべての QGIS 開発者が守るべきです。
クラス¶
メンバー¶
クラスメンバー名は小文字のmで始まり、大文字と小文字を使用して形成されています。
mMapCanvas
mCurrentExtent
すべてのクラスメンバはプライベートにしましょう。公開クラスメンバは極力避けるようにしてください。保護メンバーは Python バインディングから使用できないため、メンバーが Python のサブクラスからアクセスする必要がある場合は、保護メンバを使用しないでください。
静的メンバの命名は、変数の場合は小文字の "s" で始め、定数の場合はすべての文字を大文字としてください。
sRefCounter
DEFAULT_QUEUE_SIZE
アクセサ関数¶
クラスのメンバ値はアクセサ関数を通じて取得しましょう。関数は、 get 接頭辞なしの名前を付ける必要があります。上記2つの私的メンバのためのアクセサ関数は次のようになります。
mapCanvas()
currentExtent()
アクセサが正しく const
でマークされていることを確認してください。適切な場合には、これはキャッシュされた値型のメンバー変数が mutable
でマークされていることを要求することができます。
関数¶
関数名は小文字で始まり、大文字と小文字を使用して形成されています。関数名は、その関数の目的について何かを伝える必要があります。
updateMapExtent()
setUserOptions()
既存の QGIS の API と Qt の API との一貫性を保つために、略語は避けましょう。例えば setDestSize
でなく setDestinationSize
、 setMaxVal
でなく setMaximumValue
といった形で書くようにしてください。
頭字語についても同様に、一貫性を保つためにキャメルケースにする必要があります。例えば、 setXML
でなく setXml
と書くようにしてください 。
関数の引数¶
関数の引数は説明的な名前を使用してください。1文字の引数名を使用しないでください (例:``setColor( const QColor& c )``ではなく、``setColor( const QColor& color )``とする)。
引数を参照渡しするべき場合に注意してください。オブジェクトの引数は小さくてコピーが簡単なもの (QPoint オブジェクトなど) でない限り、 const 参照で渡しましょう。 Qt の API との一貫性を保つために、暗黙的に共有されるオブジェクトは const 参照によって渡されます。 (例えば、 setTitle( QString title )
ではなく setTitle( const QString& title )
)。
関数の返値¶
小さくコピーが簡単なオブジェクトは値として返してください。より大きなオブジェクトは const 参照で返しましょう。この例外の一つは暗黙的に共有されるオブジェクトで、常に値で返します。 QObject
またはそのサブクラスは、ポインタとして返してください。
int maximumValue() const
const LayerSet& layers() const
QString title() const
(QString
は暗黙的に共有される)QList< QgsMapLayer* > layers() const
(QList
は暗黙的に共有される)QgsVectorLayer *layer() const;
(QgsVectorLayer
はQObject
を継承)QgsAbstractGeometry *geometry() const;
(QgsAbstractGeometry
は抽象クラスであり、おそらくキャストする必要がある)
APIドキュメント¶
公開 API で利用可能なすべてのクラス、メソッド、列挙型などのコードについては、 API ドキュメントを書く必要があります。
QGIS uses Doxygen for documentation. Write descriptive and meaningful comments that give a reader information about what to expect, what happens in edge cases and give hints about other interfaces he could be looking for, best practices and code samples.
メソッド¶
メソッドの説明は三人称を使用した説明的な形で書いてください。メソッドにはいつ導入されたかを定義する \since
タグが必要です。導入以降に重要な変更が行われたものについては、追加の \since
タグを追加してください。
/**
* Cleans the laundry by using water and fast rotation.
* It will use the provided \a detergent during the washing programme.
*
* \returns True if everything was successful. If false is returned, use
* \link error() \endlink to get more information.
*
* \note Make sure to manually call dry() after this method.
*
* \since QGIS 3.0
* \see dry()
*/
メンバ変数¶
メンバ変数はふつう private
セクションに入れ、ゲッタやセッタを利用できるようにしてください。エラー報告などのためのデータコンテナはこの例外です。このような場合はメンバに m
の接頭辞を付けないでください。
/**
* \ingroup core
* Represents points on the way along the journey to a destination.
*
* \since QGIS 2.20
*/
class QgsWaypoint
{
/**
* Holds information about results of an operation on a QgsWaypoint.
*
* \since QGIS 3.0
*/
struct OperationResult
{
QgsWaypoint::ResultCode resultCode; //!< Indicates if the operation completed successfully.
QString message; //!< A human readable localized error message. Only set if the resultCode is not QgsWaypoint::Success.
QVariant result; //!< The result of the operation. The content depends on the method that returned it. \since QGIS 3.2
};
};
Qt デザイナ¶
C ++ファイル¶
名前¶
C ++の実装とヘッダーファイルは、それぞれ拡張子.cppと.hを持つ必要があります。ファイル名はすべて小文字で、クラスの場合、クラス名と一致する必要があります。
例: クラス QgsFeatureAttribute
ソースファイルは qgsfeatureattribute.cpp
と qgsfeatureattribute.h
に置く
注釈
上記の文から明確ではない場合は、ファイル名がクラス名と一致するために、それは各クラスが独自のファイルで宣言され実装されるべきであることを暗黙的に意味します。これにより、新参者にとってコードが特定のクラスにどこで関連しているか特定するのがはるかに容易になります。
標準ヘッダとライセンス¶
各ソースファイルには以下の例に従ってパターン化されたヘッダセクションがあるようにしてください:
/***************************************************************************
qgsfield.cpp - Describes a field in a layer or table
--------------------------------------
Date : 01-Jan-2004
Copyright: (C) 2004 by Gary E.Sherman
Email: sherman at mrcc.com
/***************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
注釈
git中にはQt Creatorのためのテンプレートがあります。それを使用するには、 doc/qt_creator_license_template
からそれをローカルの場所にコピーし、メールアドレスと名前を(必要ならば)修正し、それを使用するようにQtCreatorを設定します 。
変数名¶
ローカル変数名は小文字で始まり、大文字と小文字を使用して形成されています。my
あるいは the
といった文字列を前に付けないでください。
例:
mapCanvas
currentExtent
列挙型¶
列挙型は、最初が大文字のキャメルケースで命名する必要があります、例えば:
enum UnitType
{
Meters,
Feet,
Degrees,
UnknownUnit
};
他のタイプと競合するジェネリック型の名前を使用しないでください。例えば Unknown
よりむしろ UnkownUnit
を使用してください
コメント¶
クラスのメソッドのコメントには、命令形ではなく三人称の終止形を使用してください。
/**
* Creates a new QgsFeatureFilterModel, optionally specifying a \a parent.
*/
explicit QgsFeatureFilterModel( QObject *parent = nullptr );
~QgsFeatureFilterModel() override;
Qt のシグナルとスロット¶
すべてのシグナル/スロットコネクトは、「新しいスタイル」を使用して行われるべきであるQt5で利用できる接続します。この要件のFuther情報は、 QEP #77 で利用可能です。
Qt自動接続スロット(すなわち void on_mSpinBox_valueChanged
と名前付けされたもの)の使用を避けてください。自動接続スロットはダイアログがリファクタリングされている場合は、警告なしに破損し、脆弱となりやすいです。
編集¶
任意のテキストエディタ/IDEは、次の要件が満たされているとすれば、QGISコードを編集するために使用できます。
字下げ¶
ソースコードは読みやすくするために字下げされなければなりません。変更されたファイルを検索し、 astyle を使用してそれらを字下げし直す scripts/prepare-commit.sh
があります。これは、コミットする前に実行する必要があります。また、個々のファイルを字下げするために scripts/astyle.sh
を使用できます。
ソースの完全な字下げを行うために使用されるバージョンとは異なる astyle インデントの新しいバージョンとして、このスクリプトは、私たちは(ビルドに含める cmake の中``WITH_ASTYLE``を有効にする)私たちのリポジトリに含まれていることを、古いの astyle のバージョンを使用しています。
API の互換性¶
There is API documentation for C++.
私たちは API の安定性および後方互換性を維持しようとしています。API のクリーンアップは、 Qt のソースコード例と同様の方法で行われるべきです。
class Foo
{
public:
/**
* This method will be deprecated, you are encouraged to use
* doSomethingBetter() rather.
* \deprecated use doSomethingBetter()
*/
Q_DECL_DEPRECATED bool doSomething();
/**
* Does something a better way.
* \note added in 1.1
*/
bool doSomethingBetter();
signals:
/**
* This signal will be deprecated, you are encouraged to
* connect to somethingHappenedBetter() rather.
* \deprecated use somethingHappenedBetter()
*/
#ifndef Q_MOC_RUN
Q_DECL_DEPRECATED
#endif
bool somethingHappened();
/**
* Something happened
* \note added in 1.1
*/
bool somethingHappenedBetter();
}
SIP バインド¶
SIP ファイルの一部は、特定のスクリプトを使用して自動的に生成されます。
ヘッダの前処理¶
正しく SIP を構築するためのすべての情報は C++ のヘッダファイル内になければなりません。そのような定義のためにいくつかのマクロを利用することができます。
#ifdef SIP_RUN
を使用すると SIP ファイルのみのコードを生成し、#ifndef SIP_RUN
は C++ のコードのみのものです。#else
文はどちらの場合も扱うことができます。SIP_SKIP
を使用すると、行が無効になります。以下の表記法を扱うことができます。
SIP_FACTORY
:/Factory/
SIP_OUT
:/Out/
SIP_INOUT
:/In,Out/
SIP_TRANSFER
:/Transfer/
SIP_PYNAME(name)
:/PyName=name/
SIP_KEEPREFERENCE
:/KeepReference/
SIP_TRANSFERTHIS
:/TransferThis/
SIP_TRANSFERBACK
:/TransferBack/
private
セクションは、ブロック内で#ifdef SIP_RUN
文を使用した場合を除いて表示されません。SIP_PYDEFAULTVALUE(value)
can be used to define an alternative default value of the python method. If the default value contains a comma,
, the value should be surrounded by single quotes'
SIP_PYTYPE(type)
can be used to define an alternative type for an argument of the python method. If the type contains a comma,
, the type should be surrounded by single quotes'
A demo file can be found in tests/scripts/sipifyheader.h
.
Generating the SIP file¶
The SIP file can be generated using a dedicated script. For instance:
scripts/sipify.pl src/core/qgsvectorlayer.h > python/core/qgsvectorlayer.sip
As soon as a SIP file is added to one of the source file
(python/core/core.sip
, python/gui/gui.sip
or
python/analysis/analysis.sip
), it will be considered as generated
automatically. A test on Travis will ensure that this file is up to date with
its corresponding header.
Older files for which the automatic creation is not enabled yet are listed in
python/auto_sip.blacklist
.
Improving sipify script¶
If some improvements are required for sipify script, please add the missing bits
to the demo file tests/scripts/sipifyheader.h
and create the expected
header tests/scripts/sipifyheader.expected.si
. This will also be
automatically tested on Travis as a unit test of the script itself.
コーディングスタイル¶
ここに、うまくいけばエラー、開発時間およびメンテナンスを減らすいくつかのプログラミングのヒントが記載されています。
可能なかぎりコードを一般化しましょう¶
コードをカット&ペーストしている、あるいは複数回同じことを書いている場合は、単一の関数にコードを統合することを検討してください。
これにより:
変更は複数の場所ではなく一箇所で行うことを可能にします
コードの膨張を防ぐのを助けます
複数のコピーが時間につれて違いを進化させること、したがって他人が理解して維持管理するのを難しくすること、がより起こりにくくします
述語中で定数は最初にしましょう¶
述語中では最初に定数を置くことを好みます。
value == 0
の代わりに 0 == value
これにより、プログラマが ==
を使用するつもりで誤って =
を使用することを防げます、それは非常に微妙な論理的バグになる。比較のための ==
の代わりに誤って =
を使用している場合、 定数には本質的に値を割り当てできませんから、コンパイラでエラーが発生します。
空白は友達になりえます¶
演算子、ステートメント、および関数の間にスペースを追加すると、人間がコードを簡単に解析できるようになります。
より読みやすいのは、こちら:
if (!a&&b)
またはこちら:
if ( ! a && b )
注釈
scripts/prepare-commit.sh
will take care of this.
コマンドは別々の行に入れましょう¶
コードを読み取るとき、行の先頭にない場合は、コマンドを見逃しやすくなります。すぐにコードを読むとき、それらは最初の数文字で探しているもののように見えない場合、行を読み飛ばすのが一般的です。 if
のような条件の後にコマンドを期待することも一般的です。
考えてみましょう:
if (foo) bar();
baz(); bar();
制御のどのような流れの一部を見逃すのは非常に簡単です。代わりに使用します
if (foo)
bar();
baz();
bar();
アクセス修飾子を字下げしましょう¶
アクセス修飾子は、公開API、保護されたAPIとプライベートAPIのセクションにクラスを構造化します。アクセス修飾子自体はこのような構造にコードをグループ化します。アクセス修飾子と宣言を字下げしてください。
class QgsStructure
{
public:
/**
* Constructor
*/
explicit QgsStructure();
}
お奨めの読み物¶
Effective Modern C++, Scott Meyers
More Effective C++, Scott Meyers
Effective STL, Scott Meyers
Design Patterns, GoF
Qt Quarterlyからの Qtスタイル(API)の設計 についてこの記事もお読みください。
貢献のためのクレジット¶
新機能の貢献者は、以下の手段によりその貢献について人々に知らせることをお勧めします:
コードが組み込まれた最初のバージョンの更新履歴にメモを追加すること、以下のタイプで:
This feature was funded by: Olmiomland https://olmiomland.ol This feature was developed by: Chuck Norris https://chucknorris.kr
writing an article about the new feature on a blog, and add it to the QGIS planet https://plugins.qgis.org/planet/
以下に自分の名前を追加すること: