مازند آموز
جستجو برای:
سبد خرید 0
  • خانه
  • دوره های آموزشی و محصولات
  • تماس با ما
مازند آموز
ورود
[suncode_otp_login_form]
گذرواژه خود را فراموش کرده اید؟
عضویت
[suncode_otp_registration_form]

داده های شخصی شما برای پشتیبانی از تجربه شما در این وب سایت، برای مدیریت دسترسی به حساب کاربری شما و برای اهداف دیگری که در privacy policy ما شرح داده می شود مورد استفاده قرار می گیرد.

مازند آموز
  • خانه
  • دوره های آموزشی و محصولات
  • تماس با ما
شروع کنید
آخرین اطلاعیه ها
لطفا برای نمایش اطلاعیه ها وارد شوید
0

وبلاگ

مازند آموز > مقالات > برنامه نویسی > برنامه نویسی ماژولار و غیر ماژولار

برنامه نویسی ماژولار و غیر ماژولار

27 آبان 1404
ارسال شده توسط engrmh
برنامه نویسی، مهارت

بریم سرِ گپِ دوستانه درباره‌ی «برنامه‌نویسیِ ماژولار» در برابرِ «غیرماژولار»؛ مثلِ اینه که داریم مقایسه می‌کنیم بین یه آشپزخونه‌ی آپارتمانی شیک که هر کابینِ مشخصی یه کار می‌کنه، با یه انباری که همه‌ی قابلمه‌ و چاقو و برق‌وبُنالُف رو توی یه کارتنِ درب‌باز ریختی! هر دو غذا درست می‌کنن، ولی تفاوت توی «سرعتِ پیدا کردنِ» قاشقِ چای‌خوریه، توی «دردسرِ تمیز کردن»، توی «اضافه کردنِ» یه دستگاهِ جدید.


۱) تعریفِ ساده، مثلِ رسپی

ماژولار (Modular):
– می‌شیِنی یه «بخشِ مشخص» می‌سازی (مثلاً یه ماژولِ «محاسبهِ مالیات» یا «مدیریتِ LED»).
– اون بخش فقط یه درگاهِ کوچیکِ عمومیِ (interface) داره که بقیه ازش استفاده می‌کنن؛ داخلِ خودش مثلِ قلعه‌اس، هیچ‌کس حق نداره مستقیم بره توی کشوهای درونیِ اون.
– اگر فردا خواستی قلعه رو عوض کنی، فقط همون درگاه رو حفظ می‌کنی؛ بقیهِ برنامه متوجه نمی‌شه.

غیرماژولار (Monolithic):
– همه‌چی توی یه فایلِ ۲۰۰۰ خطی یا یه کلاسِ «God-Object» ریخته.
– متغیری لازم داری؟ می‌ری وسطِ کد نفرِ مقابل، خطِ ۱۵۳۴، عوضش می‌کنی!
– اگر بخوای یه قابلیتِ جدید بیاری، مجبوری چراغِ مطالعه بیاری، چون نمی‌دونی کدوم خط ممکنه بترکه.


۲) یه مثالِ ملموسِ «کدنویسی» برات می‌نویسم

فرض کن باید یه LED روشن کنیم، بعد دکمه‌ای داریم که وقتی زدی، روشن‌موندنش چشمک‌زن بشه.

حالتِ غیرماژولار (همه‌چی تویِ main.c ریخته):

#include <avr/io.h>

int main(void){
    DDRB &= ~(1 << PB0); // دکمه‌ی ورودی
    DDRB |=  (1 << PB5); // LED خروجی
    uint8_t mode = 0;    // 0=ثابت روشن، 1=چشمک
    while(1){
        if(!(PINB & (1 << PB0))){ // دکمه زده شد؟
            _delay_ms(50); // دbounce ساده
            if(!(PINB & (1 << PB0)))
                mode = !mode;
        }
        if(mode){
            PORTB ^= (1 << PB5);
            _delay_ms(200);
        } else {
            PORTB |= (1 << PB5);
        }
    }
}

کار می‌کنه؛ ولی حالا بخوام تعدادِ چشمک‌هارو محدود کنم، یا LED دوم اضافه بشه، یا دکمهِ دوم بیاد، باید بری داخلِ همین حلقه‌ی عظیم، دستکاری کنی. اگر یه هم‌تیمی بیاد، می‌گه «این mode کجا تعریف شده؟» باید بیفتی دنبالِ خطِ ۹!

حالتِ ماژولار (هرکسی توِ خونه‌ی خودشه):

led.h

#pragma once
#include <stdint.h>
void led_init(void);
void led_on(void);
void led_toggle(void);
void led_blink(uint8_t times);

led.c

#include "led.h"
#include <avr/io.h>
#include <util/delay.h>
static uint8_t blink_count = 0;
static uint16_t delay_ms = 200;

void led_init(void){ DDRB |= (1 << PB5); }
void led_on(void){ PORTB |= (1 << PB5); blink_count=0; }
void led_toggle(void){ PORTB ^= (1 << PB5); }
void led_blink(uint8_t times){ blink_count = times*2; }

// تایمرِ ۱ms صدا بزن این ISR رو صدا بزن:
void led_tick(void){        // هر ۱ms صدا زده می‌شه
    static uint16_t cnt=0;
    if(blink_count){
        if(++cnt >= delay_ms){
            cnt=0;
            led_toggle();
            blink_count--;
        }
    }
}

button.h

#pragma once
#include <stdbool.h>
void button_init(void);
bool button_was_pressed(void); // rising-edge

button.c

#include "button.h"
#include <avr/io.h>
static bool last_state = true;
bool button_was_pressed(void){
    bool current = (PINB & (1 << PB0)) != 0;
    bool edge = (!last_state && current);
    last_state = current;
    return edge;
}

main.c

#include "led.h"
#include "button.h"

int main(void){
    led_init();
    button_init();
    while(1){
        if(button_was_pressed())
            led_blink(5);   // ۵ بار چشمک
        led_tick();         // تیکِ ۱ms
        _delay_ms(1);
    }
}

حالا اگر بخوای LED دوم بیاری، فقط یه فایلِ led2.c می‌سازی؛ اگر بخوای دکمهِ دوم بیاری، button2.c رو می‌زنی. هیچ‌کس نمی‌دونه داخلِ اون ماژول چه متغیرهایی هست؛ فقط «اینترفیس» رو می‌بینه.


۳) فرقِ کلیِ تفکیک‌شده

ویژگیغیرماژولارماژولار
اندازهِ فایلچند هزار خطهر فایل < ۳۰۰ خط
وابستگیِ متقابل (Coupling)بالا؛ هرکی هرکی رو می‌شناسهکم؛ فقط از طریقِ اینترفیس
تست‌پذیریباید کل برنامه بیاد بالاهر ماژول رو جداگانه یونیت‌تست می‌کنی
reuseباید کُپی‌پیست کنی و دستکاریهمون led.c رو می‌بری پروژهِ بعدی
سرعتِ اولیهِ توسعهسریع می‌نویسی، ولی اشکال‌گیری کُندکندترِ شروع، ولی اشکال‌گیری سریع
همکاریِ تیمی«کی خطِ ۱۵۳۴ رو عوض کرد؟!»«فقط تویِ led.c تغییر دادم»

۴) یه استعارهِ دیگه

غیرماژولار = یه قوطیِ شیرِ خشک‌شده؛ اگر بخوای فقط کاکائو بریزی، مجبوری کلِ درب رو بشکنی.
ماژولار = شیشهِ ادویه‌ایِ درب‌دارِ جدا؛ فقط زعفرون رو برمی‌داری، بقیه جاشون باقی می‌مونن.


۵) چه جوری ماژولار بنویسم؟ (چک‌لیستِ کوچیک)

۱) Single Responsibility: هر فایل/کلاس فقط یه «علتِ تغییر» داشته باشه.
۲) Interface واضح: تابع‌هایِ عمومی رو توی .h یا public بذار؛ بقیه static یا private بماند.
۳) وابستگیِ یک‌طرفه: led.c می‌تونه تایمر صدا بزنه، ولی تایمر نباید بره داخلِ led.c دستکاری کنه.
۴) کپسوله‌سازی (Encapsulation): متغیرهایِ داخلی رو static کن کسی نبینه.
۵) ** Dependency Injection:** اگر button نیاز داره «زمانِ فعلی» رو بفهمه، بهش یه اشاره‌گرِ تابعِ get_millis() بده، نه اینکه مستقیم millis_counter رو بخونه.


۶) یه نمونهِ «ماژولارِ» پیشرفته‌تر (C++)

led.hpp

#pragma once
#include <cstdint>
class Led{
public:
    enum Mode{ ON, OFF, BLINK };
    Led(volatile uint8_t& port, uint8_t pin);
    void set(Mode m, uint16_t period_ms=0);
    void tick(); // هر ۱ms صدا زده بشه
private:
    volatile uint8_t& port_;
    uint8_t pin_;
    Mode mode_;
    uint16_t counter_;
};

حالا اگر بخوای LEDِ RGB بسازی، فقط یه RgbLed می‌سازی که درونش سه‌تا Led داره؛ کسی بیرون نمی‌دونه پین‌ها کجا وصل‌ان.


۷) وقتی «ماژولار» بیش‌ازحد بشه (Over-Engineering)

– فایل‌هایِ ۵۰ تا برای یه LED ساده!
– اینترفیسِ ۷ لایه‌ای برای رسیدن از دکمه تا LED!
اصطلاحاً «ماژولارِ افراطی» می‌شه؛ تعادل رو رعایت کن؛ اگر پروژه‌ت ۵۰۰ خطِ، همون دو تا ماژول کافیه.


۸) جمع‌بندیِ یک‌جمله‌ای

کدنویسیِ ماژولار = می‌سازی «قطعه‌هایِ لِگویی» که هرکدوم رو می‌تونی جداگانه بسازی، تست کنی، عوض کنی، بفروشی(!) بدون اینکه کلِ قلعه خراب بشه.

قبلی زبان های برنامه نویسی Embedded
بعدی برنامه نویسی ماژولار و غیر ماژولار در زبان JavaScript

پست های مرتبط

27 آبان 1404

برنامه نویسی ماژولار و غیر ماژولار در زبان JavaScript

engrmh
ادامه مطلب

27 آبان 1404

زبان های برنامه نویسی Embedded

engrmh
ادامه مطلب

27 آبان 1404

الگوریتم، تفکر منطقی و حل مسئله

engrmh
ادامه مطلب

27 آبان 1404

تفاوت برنامه نویسی و کد نویسی

engrmh
ادامه مطلب

27 آبان 1404

زبان های برنامه نویسی

engrmh
ادامه مطلب
جستجو برای:
پشتیبانی
دسته‌ها
  • برنامه نویسی
  • فریلنسر
  • مهارت
برچسب‌ها
الگوریتم برنامه نویسی تفکر منطقی حل مسئله دسکتاپ مهارت موبایل وب کد نویسی

مازند آموز
آموزش با طعم شیرین
دسترسی سریع
  • خانه
  • دوره ها
  • مقالات
  • تماس با ما
خبرنامه

چیزی را از دست ندهید، ثبت نام کنید و در مورد شرکت ما مطلع باشید.

© 1404. تمامی حقوق برای مازندافزار پارس محفوظ است.

فرانت اند

  • 5 دوره

بک اند

  • 1 دوره

برنامه نویسی

  • 6 نوشته

فریلنسر

  • 1 نوشته

مهارت

  • 5 نوشته
برای مشاهده خریدهای خود باید وارد حساب کاربری خود شوید
Facebook Twitter Youtube Instagram Whatsapp