跳轉到

指令碼開發 / 程式碼規劃編排

指令碼集、指令碼、函式應當按照一定邏輯編排組織,而不是將程式碼隨意堆砌在一起。 合理編排指令碼集和指令碼有利於程式碼的維護以及系統執行效率。

1. 按照用途、型別合理劃分指令碼集和指令碼

一般來說,推薦選用以下幾種程式碼組織方式:

  • 為業務處理指令碼按照行業、專案、組織等方式建立單獨的指令碼集,如:eShopIoTmonitorsalesmarketing
  • 程式碼量過多時,根據使用頻率劃分低頻使用的指令碼和高頻使用的指令碼,如 predictionadvanced_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(...) 來呼叫。

具體使用何種方式,請根據實際情況酌情選擇。