Top > C++ > AngelScript > 運用

運用 - Employment Edit

Last-modified: 2010-03-04 (木) 01:03:34

このページについて Edit

AngelScript(以下AS)を実際にチームで運用するときの使用例について書きます。

コーディング規約・運用ルールの例 Edit

チームでASを使う場合,コーディング規約をある程度決めておいた方がよいでしょう。
ここでは決めておくべき項目とその例を紹介します。

ちなみに,ここで使用している例は筆者が使っているルールです。
実際にコーディング規約を作る場合はここの例にこだわらず,
コミュニティやチームごとに親しみやすいルールで運用することをオススメします。

キャメルとは Edit

例の説明中に「キャメル」という言葉を使っています。
キャメルとはAbstractSceneやPlayerInformationのように
単語の頭が大文字,それ以外を小文字とした表記の方法のことを指します。

スクリプトファイル Edit

  • 原則,1スクリプトファイルにつき1つのクラスもしくは列挙型シンボルを記述するようにしてます。
  • クラス名とファイル名は同じにします。拡張子は.asを使用します。
  • Hogeというクラスのファイル名はHoge.asになります。

列挙型・列挙型の要素 Edit

  • 列挙型の名前はクラス同様キャメルを使います。
  • 列挙型の各要素は,列挙型の名前 + _ + キャメルで表現します。
  • 終端はTERMINATEを使います。
  • 最も小さい値はMIN,最も大きい値はMAXを使います。(この名前の付け方はD言語に合わせています)
すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 
-
|
|
|
|
|
|
!
enum ColorKind
{
    ColorKind_Red
    , ColorKind_Blue
    // term
    , ColorKind_TERMINATE
    , ColorKind_MIN = 0
    , ColorKind_MAX = ColorKind_TERMINATE-1
};

クラス Edit

  • 名前はキャメルを使います。
  • ASではC++のようにクラス内クラス宣言ができません。
  • これの代用として所属するクラス名 + _ + 内部クラス名でそれを表現するようにしています。
すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 
 
-
|
-
!
!
 
 
 
-
!
 
-
!
 
// C++での記述
class Obj
{
    class Inner
    {
    };
};
 
// ASで書くとこう
class Obj
{
};
class Obj_Inner
{
};

インターフェース Edit

  • 名前はI + キャメルを使います。
    すべてを展開すべてを収束
      1
      2
    
     
     
    
    interface IHuman {};
    class Taro : IHuman {};

メンバ変数・メンバ関数 Edit

  • AS自体にpublicやprivateといった公開修飾子は存在しませんが,命名規則を使うことでメンバがpublicなものかprivateなものか判別つくようにしています。
  • publicなメンバ変数・メンバ関数は小文字始まりのキャメルを使っています。
  • privateなメンバ変数はmv + キャメルを使っています。
  • privateなメンバ関数はmf + キャメルを使っています。
すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
 
-
|
|
|
|
|
!
class Hoge
{
    int mvPrivateValue; // privateなメンバ変数
    int publicValue; // publicなメンバ変数
    
    int publicFunction()const { return 0; } // publicなメンバ関数
    int mfPrivateFunction()const { return 0; } // privateなメンバ関数
};

グローバル変数・関数 Edit

  • ASコードはC++コードと違い,staticメンバ変数を持つことができません。
  • それの代わりとして筆者はグローバル変数・関数を使用しているようにしてます。
  • グローバル変数・関数をそれ以外の使い方としては使いません。
  • 全てのグローバル変数・関数はC++コードでのstaticメンバ変数・関数に該当するという考え方です。
  • publicなstaticメンバ変数・関数の名前は所属するクラス名 + _ + キャメルを使います。
  • privateなstaticメンバ変数の名前は所属するクラス名 + _ + sv + キャメルを使います。
  • privateなstaticメンバ関数の名前は所属するクラス名 + _ + sf + キャメルを使います。
  • 先頭に所属するクラス名をつける理由として,他のグローバル関数・変数の名前の衝突を回避する狙いがあります。
すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 
 
-
|
|
|
|
|
|
|
!
 
 
 
 
 
 
// C++のコード
class Hoge
{
public:
    static const int StaticFunction();
    static const int StaticValue;
 
private:
    static const int PrivateStaticFunction();
    static const int PrivateStaticValue;
};
 
// ASコードで書くとこう。
const int Hoge_StaticFunction();
const int Hoge_StaticValue;
const int Hoge_sfPrivateStaticFunction();
const int Hoge_svPrivateStaticValue;

関数の引数の修飾子 Edit

  • ASコードではin,inout,outなどが使えますがこれらは使わないようにしています。
  • C++コードと同じようにObject&およびconst Object&のみ使うようにしています。
すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
-
|
!
 
 
-
|
|
|
-
|
!
|
|
-
|
!
!
class Foo
{
    int value;
};
 
class Hoge
{
    int mvValue;
 
    void readFoo( const Foo& aFoo )
    {
        mvValue = aFoo.value;    
    }
 
    void writeFoo( Foo& aFoo )
    {
        aFoo.value = mvValue;   
    }
};

名前空間を示す接頭辞 Edit

ASコードではC++コードの名前空間(namespace)に該当する機能がありません。(*moduleは別の機能です)
筆者は名前空間の機能を補うために,クラス名の頭に名前空間の略称を示す接頭辞をつけるようにしています。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 
-
|
!
 
 
 
-
!
// C++コード
namespace enemy {
    class StateAttack {};
}
 
// ASコード
class EnStateAttack // enemyの略称EnをStateAttackの前につけている
{
};

また,C++バインドしたクラス名は頭にAppという接頭辞をつけています。
こういった接頭辞をつける理由は,名前の衝突をさけることが1番の目的にあります。

publicメンバ変数およびプロパティアクセサを積極的に使用 Edit

ASコードではC#やD言語でおなじみのプロパティアクセサを使用できます。

プロパティアクセサがあると

  1. 読み書き可能なメンバ変数をpublicメンバ変数として宣言する。
  2. フックが必要になったタイミングでプロパティアクセサを記述する。

という流れが可能になります。
そのため,C++コードでは手間がかかるアクセサ記述を最小限に留めることができます。

この流れの例を示します。

Moveクラスはspeedというメンバ変数を持っているとします。
このspeedは読み書き可能なメンバ変数なのでpublicなメンバ変数として宣言します。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 
 
-
|
!
 
 
 
-
|
|
|
|
!
// Moveクラス
class Move
{
    float speed; // publicなメンバ変数として宣言
};
 
// Moveの動作をテストするコード
void Move_UnitTest()
{
    Move move;
    move.speed = 3; // write
    const float moveSpeed = move.speed; // read
    assert( moveSpeed == 3 );
}

ある日,Moveクラスのspeedに0以上の値しか設定できないように仕様を変更することになりました。
この仕様をプロパティアクセサを使用して実装します。

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 
-
|
|
|
-
|
!
|
-
|
|
!
!
 
 
 
 
-
|
|
|
|
!
// Moveクラス
class Move
{
    float mvSpeed; // privateなメンバ変数として宣言
 
    float get_speed()const
    {
        return mvSpeed;
    }
    void set_speed(const float aSpeed)
    {
        assert( 0 <= aSpeed );
        mvSpeed = aSpeed;
    }
};
 
// Moveの動作をテストするコード
// 前のバージョンから1行も変更していないが同じ動作をする
void Move_UnitTest()
{
    Move move;
    move.speed = 3; // write
    const float moveSpeed = move.speed; // read
    assert( moveSpeed == 3 );
}

Moveクラスの仕様変更をしましたが,プロパティアクセサを使ったため既存のコード(Move_UnitTest)を変更せずにすみました。

IDisposableの導入 Edit

ASのクラスのインスタンスのデストラクタが走るタイミングは
ガベージコレクションの都合で変わるため不確定と考えた方がいいでしょう。
そのため,メモリリソースを破棄するなど,タイミングを狙って後始末をしたい処理をデストラクタに書くべきではありません。

「タイミングを狙って後始末」という仕組みを実現するため
C#でおなじみのIDisposableインターフェースを用意し,
後始末が必要なクラスはこれを実装するようにしました。

すべてを展開すべてを収束
  1
  2
  3
  4
 
-
|
!
interface IDisposable
{
    void dispose();
}

リロード   新規 下位ページ作成 編集 凍結 差分 添付 コピー 名前変更   ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: Thu, 04 Mar 2010 01:03:34 JST (5157d)