Governance (การกำกับดูแล)

artifact หลักใน modular monolith style คือ module ซึ่งแทน domain หรือ subdomain หนึ่ง ๆ และมักจะแทนด้วยโครงสร้าง directory หรือ namespace (หรือโครงสร้าง package ในแพลตฟอร์ม Java) ดังนั้น หนึ่งในรูปแบบแรก ๆ ของ automated governance ที่สถาปนิกสามารถใช้ได้คือการนิยามและตรวจสอบให้แน่ใจว่า module ที่ใช้ใน architecture เป็นไปตามที่กำหนด

ในการเขียน automated governance check สถาปนิกใช้เครื่องมือหลากหลาย รวมถึง ArchUnit สำหรับแพลตฟอร์ม Java, ArchUnitNet และ NetArchTest สำหรับแพลตฟอร์ม .NET, PyTestArch สำหรับ Python และ TSArch สำหรับ TypeScript และ JavaScript pseudocode ใน Example 11-1 ทำให้แน่ใจว่า source code ทั้งหมดที่แสดงใน architecture ตัวอย่างใน Figure 11-2 อยู่ภายใต้ namespace ใด namespace หนึ่งในรายการที่แทน module แต่ละตัวที่นิยามไว้ในระบบ

Example 11-1. Pseudocode สำหรับตรวจสอบว่าโค้ดเป็นไปตาม module ที่ระบบนิยามไว้
# The following namespaces represent the modules in the system
LIST module_list = {
   com.orderentry.orderplacement,
   com.orderentry.inventorymanagement,
   com.orderentry.paymentprocessing,
   com.orderentry.notification,
   com.orderentry.fulfillment,
   com.orderentry.shipping
   }

# Get the list of namespaces in the system
LIST namespace_list = get_all_namespaces(root_directory)

# Make sure all the namespaces start with one of the listed modules
FOREACH namespace IN namespace_list {
   IF NOT namespace.starts_with(module_list) {
      send_alert(namespace)
   }
}

ถ้านักพัฒนาสร้าง namespace หรือ directory ระดับสูงเพิ่มเติมนอกเหนือจาก module ที่นิยามไว้และ namespace (หรือ directory) ที่เกี่ยวข้อง พวกเขาจะได้รับ alert ที่บอกว่า source code นั้นไม่เป็นไปตาม architecture

รูปแบบ governance นี้ทำงานได้ดีกับตัวเลือก monolithic structure ของ architecture style นี้ (ดู “Monolithic Structure” ) แต่ท้าทายกว่าเมื่อใช้ตัวเลือก modular structure (ดู “Modular Structure” ) เพราะโค้ดอาจไม่ได้อยู่ใน monolithic source code repository เดียวกัน ด้วยตัวเลือก modular structure แต่ละ module ต้องถูกทดสอบแยกกัน ดังที่แสดงใน Example 11-2 .

Example 11-2. Pseudocode สำหรับตรวจสอบ module InventoryManagement
# Get the list of namespaces in the system
LIST namespace_list = get_all_namespaces(root_directory)

# Make sure all the namespaces start with com.orderentry.inventorymanagement
FOREACH namespace IN namespace_list {
   IF NOT namepace.starts_with("com.orderentry.inventorymanagement") {
      send_alert(namespace)
   }
}

อีกวิธีหนึ่งในการกำกับดูแล modular monolith architecture คือการควบคุมปริมาณการสื่อสารระหว่าง module การนิยามว่าอะไรคือการสื่อสารที่ “มากเกินไป” เป็นเรื่องเชิงอัตวิสัยและแตกต่างกันไปในแต่ละระบบ แต่โดยส่วนใหญ่แล้ว สถาปนิกควรพยายามลดจำนวน interdependency ระหว่าง module ให้น้อยที่สุด Example 11-3 แสดง pseudocode สำหรับตรวจสอบให้แน่ใจว่า interdependency รวมสูงสุดไม่เกินขีดจำกัด 5 จุดของการสื่อสาร (หรือ coupling)

Example 11-3. Pseudocode สำหรับจำกัดจำนวน dependency ทั้งหมดของ module ใด ๆ
# Walk the directory structure, gathering modules and the source code files
# contained within those modules
LIST module_list = {
   com.orderentry.orderplacement,
   com.orderentry.inventorymanagement,
   com.orderentry.paymentprocessing,
   com.orderentry.notification,
   com.orderentry.fulfillment,
   com.orderentry.shipping
   }

MAP module_source_file_map
FOREACH module IN module_list {
  LIST source_file_list = get_source_files(module)
  ADD module, source_file_list TO module_source_file_map
}

# Determine how many references exist for each source file and send an alert if
# the system's total dependency count is greater than 5
FOREACH module, source_file_list IN module_source_file_map {
  FOREACH source_file IN source_file_list {
    incoming count = used_by_other_module(source_file, module_source_file_map) {
    outgoing_count = uses_other_module(source_file) {
    total_count = incoming count + outgoing count
  }
  IF total_count > 5 {
    send_alert(module, total_count)
  }
}

รูปแบบสุดท้ายของ automated governance คือการทำให้แน่ใจว่า module ยังคงเป็นอิสระจากกัน โดยการจำกัดไม่ให้ module หนึ่งเจาะจงคุยกับ module อื่น ตัวอย่างเช่น ใน Figure 11-2 module OrderPlacement ไม่ควรสื่อสารกับ module Shipping Example 11-4 แสดงโค้ด ArchUnit ในภาษา Java เพื่อกำกับดูแล dependency นี้

Example 11-4. โค้ด ArchUnit สำหรับกำกับดูแลข้อจำกัดของ dependency ระหว่าง module ที่เจาะจง
public void order_placement_cannot_access_shipping() {
   noClasses().that()
   .resideInAPackage("..com.orderentry.orderplacement..")
   .should().accessClassesThat()
   .resideInAPackage("..com.orderentry.shipping..")
   .check(myClasses);
}