コンテンツにスキップ

スクリプト開発 / コードの計画と配置

スクリプトセット, スクリプト, 関数は一定の論理に従って編成・整理すべきであり, コードを随意に積み重ねるべきではありません. スクリプトセットとスクリプトを合理的に編成することは, コードの保守性やシステム実行効率の向上に役立ちます.

1. 用途・タイプに応じてスクリプトセットとスクリプトを合理的に分割する

一般的には, 以下のようなコード構成方法を推奨します:

  • 業務処理スクリプトを, 業界・プロジェクト・組織などに応じて個別のスクリプトセットとして作成します. 例: eShop, IoT, monitor, sales, marketing など
  • コード量が多い場合は, 使用頻度に応じて低頻度で使用するスクリプトと高頻度で使用するスクリプトに分けます. 例: prediction, advanced_prediction

2. 別のスクリプト内の関数を呼び出す

スクリプトは機能・用途などの異なるニーズに応じて, 異なるスクリプトまたはスクリプトセットに分けることができ, 異なるスクリプトにあるコードは相互に呼び出すことができます. 別のスクリプト内の関数を呼び出す必要がある場合は, 該当するスクリプトをimportするだけで済みます.

別のスクリプトをインポートする際は, 固定の書き方に従う必要があります:

Python
1
2
3
4
5
6
# import <スクリプトセット ID>__<スクリプト ID>
import demo__script

# またはエイリアスを使用して短縮します
# import <スクリプトセット ID>__<スクリプト ID> as 別名
import demo__script as script

スクリプトエディターでは, 左側のバーの疑問符アイコンにマウスを合わせると, 関連するステートメントを直接コピーできます

スクリプトセットをエクスポートする場合, このスクリプトセットが依存している他のスクリプトも一緒にエクスポートする必要があります. そうしないと, エクスポートされたスクリプトセットは関数が不足しているため, 実際には実行できません!

スクリプトまたはスクリプトセットはPythonモジュールではなく, 元々importでインポートすることはできません

しかし, DataFlux Func は内部で動的ロードメカニズムを実装しており, import文を使用して動的コードをロードすることを許可しています. したがって, 以下の書き方はすべて誤りです.

Python
1
2
3
4
5
6
# 誤った書き方 1: スクリプトセットをモジュールとしてインポートする
import demo

# 誤った書き方 2: スクリプトをモジュールとしてインポートする
import demo.script
from demo import script

さらに, スクリプトをインポートする際には, 循環参照が発生しないように注意する必要があります. 例:

Python
1
2
3
4
5
6
7
8
# スクリプトセット demo の下のスクリプト script2
import demo__script2

# スクリプトセット demo の下のスクリプト script3
import demo__script3

# スクリプトセット demo の下のスクリプト script1
import demo__script1

注意: 複数のスクリプトを同時に編集している場合, 現在別のスクリプトをインポートしていると, 参照されるスクリプトは実際には公開済みのバージョンで実行され, システムはどの時点でもドラフトバージョンをインポートしません!

3. 単一のスクリプトのコード量と依存チェーン

DataFlux Func はスクリプトを実行する際, 必要なスクリプトを動的にロードして実行します. いずれかのスクリプトが別のスクリプトをインポートした場合, インポートされたスクリプトも動的にロードされます.

したがって, あるスクリプト内の特定の関数が特に頻繁に呼び出される場合は, それを単独で独立したスクリプトに抽出することを検討でき, ロードの消費を減らせます. 単一のスクリプトサイズは1000行以内に抑えることを推奨します.

さらに, 過度に長い依存チェーンを避けて, 無意味なパフォーマンス損失を防ぐ必要があります. 例:

  • スクリプト 1 は スクリプト 2 に依存します
  • スクリプト 2 は スクリプト 3 に依存します
  • スクリプト 3 は スクリプト 4 に依存します
  • スクリプト 4 は スクリプト 5 に依存します
  • ...

Python の組み込みモジュールとサードパーティ製モジュールは, この制限の影響を受けません

4. スクリプトを分割しない場合

上記ではスクリプトの合理的な計画とスクリプト間の呼び出し方法について触れましたが, 特定の状況(実際に使用する共通関数が非常に少なく単純な場合など)では, スクリプトを分割せずに, すべてのコードを同じスクリプトに置くことを検討できます.

この方法は, コードに多少の冗長性が生じますが, 追加の利点ももたらします:

  • 単一のスクリプトだけで実行可能で, ロード消費を減らせます
  • 共通関数の変更による影響を受けません
  • スクリプトエクスポート時の依存関係を考慮する必要がありません

実際の状況に応じて, 最も合理的な方法でスクリプトを計画してください

5. 同じスクリプトセット内のスクリプト間で相互参照する際の省略表記

バージョン 1.1.0rc51 で追加

同じスクリプトセット内では, スクリプト間の参照でスクリプトセット IDの部分を記述しなくても構いません(つまり, __ から始まる部分だけを記述します).

スクリプトセットをクローンし, スクリプトセット IDが変更された後でも, 内部の関数間で正しく参照できるようになります.

例:

Python
1
2
3
4
# スクリプト: demo__utils

def echo(msg):
    return msg
Python
1
2
3
4
5
6
7
# スクリプト: demo__test

# import demo__utils as utils と同等
import __utils as utils

def my_func(msg):
    return utils.echo(msg)

6. 過剰なカプセル化を避ける

Python はマルチパラダイムのプログラミング言語であり, シンプルな手続き型プログラミングも使用でき, 同様にオブジェクト指向の方法でプログラミングすることもできます.

しかし, DataFlux Func では, デバッグを容易にするために, 手続き型に偏ったプログラミング方式でコードを記述し, 過剰なカプセル化を避けることを推奨します.

例えば, 同じ機能は, 2つの異なる方法で実装できます:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import requests

# 手続き型
def query_some_api(url, params):
    r = requests.get(url, params)
    return r.json()

# オブジェクト指向
class APIQuery(object):
    def __init__(self, url):
        self.url = url

    def do(self, params):
        r = requests.get(self.url, params)
        return r.json()

def test_api_query(url, params):
    api_query = APIQuery(url)
    api_query.do(params)

上記の例では, 両方とも同じ機能を実現できますが, query_some_api(...)は直接呼び出せる関数であるため, エディターでこの関数を選択し, 直接パラメータを入力して実行できます.

一方, APIQuery クラスの do(...) メソッドをデバッグ実行するには, まずオブジェクトをインスタンス化してから呼び出す必要があるため, 別途テスト関数 test_api_query(...) を記述して呼び出すしかありません.

具体的にどの方式を使用するかは, 実際の状況に応じて適宜選択してください.