در پروژههای مبتنی بر Odoo، یکی از چالشهای مهم، طراحی یک ساختار پردازشی قابل توسعه و ماژولار است. ساختاری که بتواند پردازشها را به صورت داینامیک مدیریت کند، اولویتبندی انجام دهد و وابستگی بین مراحل مختلف را کنترل نماید.
برای رسیدن به این هدف از Decorator Pattern استفاده میکنیم — الگویی که ریشه در مفاهیم AOP (Aspect Oriented Programming) دارد و به ما اجازه میدهد رفتار (Behavior) متدها را بدون تغییر در منطق اصلی، گسترش دهیم.
⚙️ معرفی Decoratorهای پردازش
در این مدل سه Decorator اصلی داریم:
@process
مشخص میکند که یک متد از یک کامپوننت، به عنوان یک پردازش مستقل در نظر گرفته میشود.
این دکوراتور میتواند ویژگیهایی مانند:
- name: نام پردازش
- priority: ترتیب اجرا
را دریافت کند.
@pre_process
لیستی از پردازشهایی را مشخص میکند که باید قبل از اجرای متد فعلی انجام شوند.
@post_process
لیستی از پردازشهایی را مشخص میکند که باید بعد از اجرای متد فعلی انجام شوند.
🧠 نمونه پیادهسازی
class ProcessingComponent2(AbstractComponent):
_name = COM2
_usage = USAGE2
_apply_on = APPLY_ON2
_collection = COLLECTION
@process(name=PROCESS0)
def process_0(self, **kwargs):
"""Process 0"""
process_counter[COM2][PROCESS0] += 1
process_log.append((COM2, PROCESS0))
@process(name=PROCESS1)
@pre_process(PROCESS0)
def process_1(self, **kwargs):
"""Process 1"""
process_counter[COM2][PROCESS1] += 1
process_log.append((COM2, PROCESS1))
در این مثال، process_1 فقط زمانی اجرا میشود که process_0 قبل از آن انجام شده باشد.
🧱 معماری شیءگرا (OOP) و رجیستری پردازشها
هر کامپوننت دارای یک رجیستری پردازش مستقل است که ساختار آن بر پایه مفاهیم OOP طراحی شده است.
این رجیستری، مجموعهای از پردازشها را با جزئیات مربوط به پیشپردازشها و پسپردازشها نگه میدارد.
ساختار رجیستری
class ProcessRegisteryItem():
def __init__(self):
self.method = ""
self.priority = 10
self.pre_process = []
self.post_process = []
def add_pre_process(self, **kwargs):
ref = ProcessRegisteryRef(**kwargs)
self.pre_process.append(ref)
def add_post_process(self, **kwargs):
ref = ProcessRegisteryRef(**kwargs)
self.post_process.append(ref)
class ProcessRegisteryRef():
def __init__(self):
self.name = ""
self.usage = ""
self.apply_on = ""
self.collection = ""
self.component_name = ""
خصوصیات کلیدی:
- هر ورودی رجیستری شامل نام پردازش، متد اصلی، و لیستی از پیشپردازشها و پسپردازشها است.
- این رجیستری برای هر کامپوننت بهصورت جداگانه نگهداری میشود.
🔁 رفتار در بازنویسی متدها (Override)
در OOP، زمانی که شما یک متد را در کلاس فرزند بازنویسی میکنید (override)،
سیستم بهصورت خودکار متد قبلی را از رجیستری حذف کرده و متد جدید را جایگزین میکند.
به این ترتیب، کنترل دقیق و انعطافپذیری در توسعه ماژولها حفظ میشود.
🧩 Decoratorهای سطح کلاس
اگر دکوراتور @pre_process یا @post_process روی خود کلاس اعمال شود،
این قوانین بهصورت سراسری برای تمام پردازشهای تعریفشده در آن کلاس اعمال میشوند.
به بیان دیگر، تمام متدهای پردازشی موجود در آن کلاس، از همان وابستگیها پیروی خواهند کرد.
🚫 جلوگیری از حلقههای پردازشی (Cycle Detection)
یکی از مهمترین محدودیتها در این معماری، جلوگیری از ایجاد حلقههای وابستگی است.
شما مجاز نیستید پردازشها را به گونهای لینک کنید که چرخهای بین آنها شکل گیرد.
در صورت تشخیص حلقه (Cycle)، سیستم خطا صادر میکند تا از بروز رفتارهای غیرقابل پیشبینی جلوگیری شود.
🧭 جمعبندی
با استفاده از این ساختار:
- میتوانید بهسادگی پردازشها را ماژولار و قابل توسعه طراحی کنید.
- بدون تغییر در منطق موجود، وابستگیها و ترتیب اجرا را کنترل کنید.
- از طریق رجیستری، تصویر دقیقی از روابط بین پردازشها در هر کامپوننت در اختیار داشته باشید.
این الگو، یکی از کاربردیترین شیوهها برای مدیریت پردازشها در معماری Odoo است و توسعهپذیری سیستم را به شکل قابل توجهی افزایش میدهد.
آیا مایل هستی نسخه انگلیسی (technical blog post) همین متن را هم برای انتشار در GitHub یا Medium بنویسم؟