iT邦幫忙

1

(4) 研發看 MES:第一個功能為什麼我選擇從機台開始?

mes
  • 分享至 

  • xImage
  •  

研發看 MES:第一個功能為什麼我選擇從機台開始?

前三天,我們花了一些時間了解:
MES 是什麼?
MES 到底在管理什麼?

以及:
正式開始生產以前,需要準備哪些基礎資料?

從今天開始,我想換一個角度。
不再只是「看 MES」,而是開始真的站在研發的角度思考:

如果今天要從零開始開發一套 MES,第一個功能到底要寫什麼?

產品?
製程?
途程?
工單?
還是直接開始寫 WIP?

如果是我,我會選擇:
機台(Machine)。

為什麼不是先寫工單?

從使用者的角度來看,工單可能才是生產真正開始的地方。

建立工單:

  • 選擇產品
  • 選擇客戶
  • 選擇途程
  • 填寫生產數量

接著開始建立 Lot、生產、進站、出站。
所以看起來,從工單開始開發好像很合理。
但如果真的打開 IDE 準備寫程式,很快就會遇到一個問題:

我的下拉選單資料從哪裡來?

產品還沒做。
客戶還沒做。
途程也還沒做。
途程裡面的製程甚至也還不存在。

當然,我們可以先 Mock。
也可以先寫死:

{
    "product": "PRODUCT-001",
    "customer": "CUSTOMER-001",
    "route": "ROUTE-001"
}

這樣工單頁面確實可以先做。
但是隨著系統慢慢完成,這些暫時寫死的資料還是得一個一個換掉。

所以如果今天的目標是:

從零開始,一步一步建立一套 MES。

我會選擇另外一個方向:
從依賴最少的功能開始往上開發。

第一個功能:機台

我們先把整套 MES 簡化來看。
未來可能會形成這樣的關係:

Machine
   ↓
Process
   ↓
Route
   ↓
Work Order
   ↓
Lot
   ↓
WIP

越下面的功能,通常需要知道越多前面的資訊。
相對來說,Machine 本身非常單純。

我們不需要先知道:

它屬於哪張工單?

也不需要先知道:

哪一個 Lot 正在使用?

更不需要為了建立一台機台,先建立一整條途程。
所以它很適合成為第一個練習。

先設計 Machine Table

假設今天先從最簡單的需求開始。

一台機台至少需要:

MACHINE_UUID
MACHINE_CODE
MACHINE_NAME
ENABLE
CREATE_TIME
UPDATE_TIME

例如:

MACHINE_UUID : 550e8400...
MACHINE_CODE : MC-001
MACHINE_NAME : 組裝機 01
ENABLE       : True

這時我們已經有第一張 MES Table 了。
接下來就是後端工程師非常熟悉的:
CRUD。


CRUD:看起來好像沒什麼?

機台的 CRUD 分別代表:
Create: 新增機台。
Read: 查詢機台。
Update: 修改機台。
Delete: 刪除機台。

如果做成 API,可能會長得像:

POST /machines
GET /machines
GET /machines/{machine_uuid}
PUT /machines/{machine_uuid}
DELETE /machines/{machine_uuid}

到這裡看起來跟一般後台管理系統沒有太大的差別。

甚至會讓人覺得:

「MES 不就也是 CRUD?」

至少在第一個功能,確實很像。

但是我們很快就會遇到第一個實務問題。

MACHINE_CODE 可以重複嗎?

假設使用者先建立:

MACHINE_CODE = MC-001
MACHINE_NAME = 組裝機 01

過幾天另外一個使用者又建立:

MACHINE_CODE = MC-001
MACHINE_NAME = 測試機 01

對系統來說,現在有兩台:
MC-001

那之後 Lot History 顯示:

LOT-001 使用 MC-001 生產。

到底是哪一台?
所以真正 Create 以前,我們可能就需要先做一些 Validation。

概念上可能像:

def create_machine(data):

    if not data["machine_code"]:
        raise Exception("Machine code is required.")

    if machine_exists(data["machine_code"]):
        raise Exception("Machine code already exists.")

    machine = Machine(**data)

    db.add(machine)
    db.commit()

這時候 CRUD 已經開始多了一些東西。
不是:

收到資料
↓
INSERT
↓
結束

而是:

收到資料
↓
資料驗證
↓
Business Rule
↓
INSERT
↓
完成

而且現在還只是 Machine。

那 Delete 呢?

接下來是我覺得 Master Data 很值得討論的一個問題:

機台真的應該 Delete 嗎?

假設:

MC-001

已經使用半年。
很多 Lot 都曾經使用這台機台生產。
因此 Lot History 裡可能存在:

LOT-001 → MC-001
LOT-002 → MC-001
LOT-003 → MC-001
...

某一天 MC-001 報廢了。
最直覺的操作可能是:

DELETE FROM MACHINE
WHERE MACHINE_CODE = 'MC-001';

但是如果真的刪掉,我們就要開始考慮:
以前的生產紀錄怎麼辦?

Lot History 還能不能知道當時使用的是哪台機台?
其他資料表有沒有 Foreign Key 指向它?
刪除之後會不會造成歷史資料無法追溯?
所以在這類基礎資料中,比起真正把資料刪掉,我們可能更需要的是:
disable。
例如:

MACHINE_CODE = MC-001
ENABLE       = False

代表:

MC-001 曾經存在,也保留過去的紀錄,但從現在開始不允許再使用。
因此畫面上的「刪除」與「停用」,在系統設計上其實是完全不同的概念。

停用之後,Read 也開始不單純了

當系統加入 ENABLE 之後,就會出現下一個問題。
假設今天製程設定要選擇可使用的機台。
查詢條件可能是:

WHERE ENABLE = 1

因為新的設定不應該再選到已停用的機台。
但是今天查的是:
三個月以前的 Lot History。

這時即使 MC-001 已經停用,我們仍然希望看到:

LOT-001
Machine:MC-001

所以同樣是「查詢 Machine」,不同使用情境需要的資料可能完全不同。
這也是我覺得開發 MES 很有趣的地方。
一開始看起來只是:
Create / Read / Update / Delete

真正開始加入生產需求之後,就會慢慢變成:
CRUD + Business Rule。


為什麼我選 Machine 當第一個功能?

因為它夠簡單。
現在我們只需要考慮:

Machine

還沒有:

Machine → Process → Route → Work Order → Lot

也還不用處理複雜的生產狀態。
所以我們可以先利用 Machine,把最基本的系統架構建立起來:

**Database Table** → **Model** → **Service** → **API** → **Frontend**

先讓第一筆真正的 MES 資料,可以從畫面一路走到 Database。
當這條路打通之後,下一個功能就可以沿用相同的架構繼續往下開發。

從小功能開始,慢慢建立依賴

如果今天一開始就寫 Work Order,我們會同時需要處理很多尚未存在的資料。
但如果從 Machine 開始:

Day 04
Machine

下一步再建立:

Machine
   ↓
Process

接著:

Machine
   ↓
Process
   ↓
Route

資料之間的關係會一層一層長出來。
等到我們真正開始寫 Work Order 時:

產品有了。
客戶有了。
途程有了。
製程有了。
機台也有了。

這時工單需要的資料就不必再靠 Mock 或寫死。
而是可以真正從前面已經完成的功能取得。

從研發角度看 MES

所以如果有人問我:

「開發 MES 第一個功能應該做什麼?」

我不一定會回答:
Machine。

因為不同 MES 的資料模型與需求一定不同。
我真正會先做的是:

找出依賴關係最少、又會被其他功能使用的基礎資料。

然後從底層開始,一層一層往上建立。
對我們目前這套 MES 而言:
Machine 就是一個很適合的起點。

今天我們完成的只是一個很普通的 CRUD。
但從下一篇開始,事情就要稍微變複雜了。

因為我們要開始建立:
製程(Process)。

而當 Process 開始跟 Machine 產生關係之後,我們第一次會碰到:

「資料與資料之間,要怎麼建立關聯?」

下一篇:
「從機台到製程:MES 的資料開始產生關聯了。」

認識我們
聯繫我們

章節列表


*提醒邦友,使用第三方服務/API 時,請務必評估資安風險與隱私保護
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言