البرمجة كائنية التوجه في أنظمة الأتمتة
البرمجة الكائنية: لغة الآلات تتكلم بالكائنات
تخيّل أنك تقف أمام خط إنتاج في مصنع سوري للمواد الغذائية. أمامك آلة تعبئة، وحزام ناقل، ومستشعر وزن، ولوحة تحكم. كل واحد من هذه المكونات له خصائص (سرعة، حالة، درجة حرارة) وسلوكيات (تشغيل، إيقاف، ضبط). هذا بالضبط ما تفعله البرمجة الكائنية (OOP) — تحوّل العالم الحقيقي إلى كائنات برمجية يمكن التحكم بها.
البرمجة الكائنية ليست مجرد أسلوب كتابة كود — إنها طريقة تفكير تجعل برامج التحكم الصناعي أكثر تنظيماً وقابلية للصيانة والتوسيع.
الصنف والكائن: المخطط والآلة الحقيقية
الصنف (Class) هو المخطط الهندسي — الرسم التقني الذي يصف كيف تُبنى الآلة. الكائن (Object) هو الآلة الفعلية التي بُنيت من هذا المخطط.
مثال عملي — لنمثّل محرّكاً كهربائياً:
class Motor:
def __init__(self, rated_power_kw, rated_rpm):
self.rated_power = rated_power_kw # الاستطاعة المقنّنة
self.rated_rpm = rated_rpm # السرعة المقنّنة
self.is_running = False # حالة التشغيل
self.current_rpm = 0 # السرعة الحالية
def start(self):
if not self.is_running:
self.is_running = True
self.current_rpm = self.rated_rpm
print(f"المحرك يعمل بسرعة {self.current_rpm} RPM")
def stop(self):
self.is_running = False
self.current_rpm = 0
print("المحرك توقف")
def get_status(self):
state = "يعمل" if self.is_running else "متوقف"
return f"الحالة: {state} | السرعة: {self.current_rpm} RPM"
الآن ننشئ كائنات فعلية — كل كائن هو محرك مستقل:
pump_motor = Motor(rated_power_kw=5.5, rated_rpm=1450)
conveyor_motor = Motor(rated_power_kw=2.2, rated_rpm=960)
pump_motor.start() # المحرك يعمل بسرعة 1450 RPM
print(conveyor_motor.get_status()) # الحالة: متوقف | السرعة: 0 RPM
لاحظ: من صنف واحد أنشأنا محركين مختلفين تماماً، كل واحد بخصائصه المستقلة. هذا جوهر فكرة الصنف والكائن.
التغليف: حماية الأجزاء الداخلية
التغليف (Encapsulation) يعني إخفاء التفاصيل الداخلية وعرض واجهة بسيطة فقط — تماماً كما تتعامل مع لوحة تحكم الآلة دون الحاجة لمعرفة تفاصيل الدارات الإلكترونية بداخلها.
class TemperatureController:
def __init__(self, setpoint):
self._setpoint = setpoint # درجة الحرارة المطلوبة
self._current_temp = 25.0 # القراءة الحالية
self._kp = 2.0 # معامل PID داخلي
self._output = 0.0 # خرج التحكم
def update_reading(self, sensor_value):
"""الواجهة العامة — يستدعيها المستخدم"""
self._current_temp = sensor_value
self._calculate_output() # الحساب الداخلي مخفي
def _calculate_output(self):
"""منطق داخلي لا يحتاج المستخدم لمعرفته"""
error = self._setpoint - self._current_temp
self._output = max(0, min(100, self._kp * error))
@property
def output_percent(self):
return self._output
@property
def setpoint(self):
return self._setpoint
@setpoint.setter
def setpoint(self, value):
if 0 <= value <= 200:
self._setpoint = value
else:
raise ValueError("درجة الحرارة خارج النطاق المسموح")
المستخدم يتعامل فقط مع update_reading و setpoint — لا يحتاج لمعرفة كيف يُحسب الخرج داخلياً. هذا يمنع الأخطاء ويسهّل الصيانة.
الوراثة: بناء عائلات من الآلات
الوراثة (Inheritance) تتيح لك إنشاء أصناف جديدة تبني على أصناف موجودة — كما أن المحرك الكهربائي والمحرك الهيدروليكي كلاهما "محرك" لكن لكل منهما خصائص إضافية.
class Actuator:
"""الصنف الأب: أي مشغّل صناعي"""
def __init__(self, name, max_force_n):
self.name = name
self.max_force = max_force_n
self.position = 0.0 # النسبة المئوية 0-100
def move_to(self, target_percent):
self.position = max(0, min(100, target_percent))
print(f"{self.name}: الموضع = {self.position}%")
def emergency_stop(self):
self.position = 0
print(f"{self.name}: توقف طارئ!")
class PneumaticCylinder(Actuator):
"""أسطوانة هوائية — ترث من Actuator"""
def __init__(self, name, max_force_n, stroke_mm, pressure_bar):
super().__init__(name, max_force_n)
self.stroke_mm = stroke_mm
self.pressure = pressure_bar
def extend(self):
self.move_to(100)
def retract(self):
self.move_to(0)
class ServoMotor(Actuator):
"""محرك سيرفو — ترث من Actuator وتضيف دقة الموضع"""
def __init__(self, name, max_force_n, resolution_bits):
super().__init__(name, max_force_n)
self.resolution = 2 ** resolution_bits
def move_to_angle(self, degrees):
percent = (degrees / 360.0) * 100
self.move_to(percent)
cylinder = PneumaticCylinder("CYL-01", 500, stroke_mm=200, pressure_bar=6)
servo = ServoMotor("SRV-01", 50, resolution_bits=12)
cylinder.extend() # CYL-01: الموضع = 100%
servo.move_to_angle(90) # SRV-01: الموضع = 25.0%
cylinder.emergency_stop() # CYL-01: توقف طارئ!
كلاهما يملك move_to و emergency_stop من الصنف الأب، لكن كل منهما يضيف سلوكه الخاص.
تعدد الأشكال: نفس الأمر، تنفيذ مختلف
تعدد الأشكال (Polymorphism) يعني أن نفس الأمر (مثلاً "شغّل") يتنفّذ بشكل مختلف حسب نوع الكائن — المحرك الكهربائي يتصرف بشكل مختلف عن الصمام الهوائي عند تلقي أمر التشغيل.
class ElectricValve(Actuator):
def move_to(self, target_percent):
if target_percent > 50:
self.position = 100 # الصمام إما مفتوح أو مغلق
print(f"{self.name}: الصمام مفتوح بالكامل")
else:
self.position = 0
print(f"{self.name}: الصمام مغلق")
class ProportionalValve(Actuator):
def move_to(self, target_percent):
self.position = target_percent # فتح نسبي مستمر
print(f"{self.name}: الفتح = {self.position}%")
devices = [
ElectricValve("V-101", 200),
ProportionalValve("PV-201", 200),
ServoMotor("SRV-02", 50, 12),
]
for device in devices:
device.move_to(75) # نفس الاستدعاء — نتائج مختلفة
الخرج:
V-101: الصمام مفتوح بالكامل
PV-201: الفتح = 75%
SRV-02: الموضع = 75%
هذا قوي جداً في الأتمتة — يمكنك كتابة كود تحكم عام يعمل مع أي نوع من المشغّلات.
نمذجة خط إنتاج كامل
لنجمع كل المفاهيم في نموذج لخط إنتاج بسيط:
class ProductionLine:
def __init__(self, name):
self.name = name
self._devices = [] # قائمة الأجهزة
self._is_running = False
def add_device(self, device):
self._devices.append(device)
def start_all(self):
print(f"--- تشغيل خط {self.name} ---")
self._is_running = True
for device in self._devices:
device.move_to(100) # تعدد الأشكال هنا!
def emergency_stop_all(self):
print(f"!!! توقف طارئ — خط {self.name} !!!")
self._is_running = False
for device in self._devices:
device.emergency_stop()
def status_report(self):
print(f"\n=== تقرير خط {self.name} ===")
for device in self._devices:
print(f" {device.name}: موضع={device.position}%")
line = ProductionLine("خط التعبئة")
line.add_device(PneumaticCylinder("CYL-دفع", 800, 300, 6))
line.add_device(ProportionalValve("PV-تعبئة", 150))
line.add_device(ServoMotor("SRV-ختم", 100, 16))
line.start_all()
line.status_report()
line.emergency_stop_all()
أنماط التصميم الشائعة في الأتمتة
نمط المراقب (Observer Pattern)
عندما يتغير مستشعر، يجب إعلام عدة أنظمة فرعية:
class Sensor:
def __init__(self, name):
self.name = name
self._value = 0
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def set_value(self, new_value):
self._value = new_value
for obs in self._observers:
obs.on_sensor_update(self.name, new_value)
class AlarmSystem:
def on_sensor_update(self, sensor_name, value):
if value > 80:
print(f"[تنبيه] {sensor_name} = {value} — تجاوز الحد!")
class DataLogger:
def on_sensor_update(self, sensor_name, value):
print(f"[سجل] {sensor_name} = {value}")
نمط آلة الحالة (State Machine)
الآلات الصناعية تتنقل بين حالات محددة:
class MachineState:
IDLE = "خامل"
STARTING = "بدء_التشغيل"
RUNNING = "يعمل"
ERROR = "خطأ"
STOPPING = "إيقاف"
class PackagingMachine:
def __init__(self):
self.state = MachineState.IDLE
def start(self):
if self.state == MachineState.IDLE:
self.state = MachineState.STARTING
# تهيئة المستشعرات...
self.state = MachineState.RUNNING
print("الآلة تعمل")
elif self.state == MachineState.ERROR:
print("يجب إزالة الخطأ أولاً!")
def report_error(self, code):
self.state = MachineState.ERROR
print(f"خطأ رقم {code} — الآلة متوقفة")
متى تستخدم OOP ومتى لا تستخدمها؟
| الحالة | الأسلوب المناسب |
|---|---|
| نمذجة آلات ومعدات لها حالات وسلوكيات | OOP |
| حسابات رياضية بسيطة (تحويل وحدات) | دوال عادية |
| أنظمة تحكم معقدة متعددة المكونات | OOP مع أنماط تصميم |
| سكربتات قصيرة لمهمة واحدة | لا حاجة لـ OOP |
| واجهات تواصل مع أجهزة PLC مختلفة | OOP مع تعدد الأشكال |
الخلاصة
البرمجة الكائنية تمنحك أدوات قوية لنمذجة أنظمة الأتمتة الصناعية:
- الأصناف والكائنات تمثّل الآلات والمكونات الفعلية
- التغليف يحمي المنطق الداخلي من التلاعب
- الوراثة تبني عائلات من الأجهزة المتشابهة
- تعدد الأشكال يتيح كود تحكم مرن وعام
- أنماط التصميم توفّر حلولاً مجرّبة للمشاكل الشائعة
ابدأ بنمذجة الآلات التي تعمل عليها — ستجد أن OOP تُترجم العالم الصناعي إلى كود بشكل طبيعي جداً.