開發 SAP RFC 專案的架構技巧
情境:使用 DotNET Client + SAP RFC 進行庫存管理
要測試 SAP RFC (Remote Function Call) 似乎真的要有 SAP 系統以及其 SAPGui 工具(很龐大),
就算把 SAP 架起來了也不是隨時有環境可進行測試,這一定會影響功能 面的開發進度。
因為大部分的功能看來都與 SAP RFC 無關,所以被此卡住就不划算了。
先介紹一個常見的 SA/SD 技巧:虛擬倉 + 虛擬儲位:
- 仔細想想就會發現所有的庫存交易都是Movement(移動)
- Movement 一定要有的資料是:品項、來源、目的、
與數量。 - 若把系統範圍之外的地方想像成虛擬倉/虛擬儲位的話,
則所有的庫存交易都可用一致的的 Movement邏輯處理掉,不必再裡廠內或廠外的問題。
舒緩此類系統邊界問題的架構技巧如下(此技巧也常用於 module 邊界):
- 建立一個 SapRfc 父類別並定義出要使用的函式介面。
- 再定義兩個 SapRfc 的子類別例如:SapRfcMock 與 SapRfcReal:
- SapRfcMock 是模擬介面,裡頭要用一般 DB 或 只用 Collection 隨你的便,這部分很單純。
- SapRfcReal 是真正去做 RFC 呼叫的類別,將 RFC 的 code 都放在這裡。
- 這樣功能面與 RFC 的工作就可平行地進展。
- 若使用 DotNET,建議不要再用 DataTable 之類的東西(因為也不會有DB),
因為靈活的 DataSource 屬性才是 DotNET的強項。 - 最好是建立 Model 物件(EX: Warehouse, Locator, Inventory, Product,...)
- 將上述的 Model 物件放到 List 之類的東西就可與控制項 binding 了。
- 若一鄧要用 DataTable 將面臨更多的轉換動作。
事實上 Model + SapRfcMock 定義完成後, 一至三天內馬上就可開始功能面的開發。
而且這個定義可以用遞增的方式進行,不用一次全部做完, 所以只需要很短的時間就做可出第一版。
UI(client端) 必須使用 SapRfc 呼叫以read/ write需要的資料。
千萬不要一開始就去想真正的 RFC 呼叫,因為研究 RFC 會卡住功能的開發。
只需用一個 flag 決定傳回 SapRfcMock 或 SapRfcReal 即可,整個感覺如下:
C# 檔案見:
https://drive.google.com/file/d/0B9exai2F1cufMHRPLWlpVUVXWGs/edit?usp=sharing
C# 檔案見:
https://drive.google.com/file/d/0B9exai2F1cufMHRPLWlpVUVXWGs/edit?usp=sharing
01 public sealed class SapRfcFactory {
02 private static SapRfc singleton = null;
03
04 public static SapRfc GetInstance() {
05 // 在此處決定要使用 real 或 mock 物件
06 if (singleton = null)
07 singleton = new SapRfcMock();
08 //singleton = new SapRfcReal();
09
10 return singleton;
11 }
12
13 private SapRfcFactory() {}
14
15 // other codes...
16 }
17
18 // 定義 RFC 呼叫介面
19 public abstract class SapRfc {
20 // 可以在此成員存放共用參數
21 Dictionary<string, object> dicParams = new Dictionary<string, object>();
22
23 public abstract bool Logon();
24 public abstract void Logout();
25 }
26
27 public class SapRfcMock: SapRfc {
28 public override bool Logon() {
29 // 直接回傳 true
30 return true;
31 }
32
33 public override void Logout() {
34 // do nothing.
35 }
36 }
37
38 public class SapRfcReal: SapRfc {
39 public override bool Logon() {
40 // 進行實際的 RFC 登入...
41 }
42
43 public override void Logout() {
44 // 進行實際的 RFC 登出...
45 }
46 }
沒有留言:
張貼留言