شرح برنامه نویسی ماژولار در زبان C

نحوه تولید فایل هگز

شاید برای شما به عنوان یک برنامه نویس سخت افزار این سوال پیش آمده باشد که از زمان نوشتن برنامه (به زبان C) تا زمان تولید فایل Hex چه مراحلی طی می شود؟

برنامه های نوشته شده به زبان C  (فایل های سورس) پس از طی چند مرحله به فایل باینری قابل اجرا بر روی سخت افزار تبدیل خواهند شد. به روند طی شده جهت رسیدن از فایل های سورس (source) به فایل نهایی قابل اجرا بر روی سخت افزار، Build process یا به طور مختصر build  گفته می شود. همان طور که می دانید هر پروژه شامل تعدادی فایل برنامه با پسوند C یا C++  است. ابتدا فایل های C/C++  به طور مجزا توسط کامپایلر (compiler) کامپایل شده و فایل های object ایجاد می شوند. اما فایل های object قابل اجرا بر روی کامپیوتر نیستند، چرا که کامل نبوده و ممکن است وابستگی به فایل های object دیگر داشته باشند. در واقع فایل های object شامل کدهای کامپایل شده ای هستند که در آن ها به هیچ کدام از متغیرها یا بلوک های کد، آدرسی در حافظه نسبت داده نشده است. در این جا نیاز به ابزار دیگری به نام لینکر (linker) است. وظیفه ی لینکر این است که فایل های object را باهم دیگر ترکیب کرده و یک فایل نهایی قابل اجرا معمولا با پسوند(hex) ایجاد کند. لینکر اطلاعات فایل object و اطلاعات نقشه حافظه را از یک فایل سند لینکر برداشته و به متغیرها آدرس نسبت می دهد و بلوک های کد را به بهترین شکل مرتب کرده تا با حافظه منطبق شود. سند لینکر تمام آدرس های ثابت رجیسترهای سخت افزار و حافظه برنامه را دارد. برای build کردن برنامه، می توان از کامپایلر و لینکر به طور جداگانه استفاده کرد و یا از  IDE(Integrated Develipment Environment)  استفاده نمود. IDE شامل مجموعه ای از برنامه ها و ابزارهاست که در یک برنامه ی واحد، مجتمع شده اند. استفاده از IDE این برتری را دارد که مراحل مختلف به صورت خودکار و زنجیره ای انجام می شود و لازم نیست برنامه نویس به صورت دستی این مراحل را طی کند. برای مثال Atmel Studio یک IDE است.

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

خواننده ی این پست به احتمال زیاد یک برنامه نویس است. اما یک برنامه نویس حرفه ای یا آماتور؟ البته آماتور بودن بد نیست، مشکل آماتور ماندن است. در این قسمت از پست می خواهیم یکی از روش های حرفه ای شدن را معرفی کنیم.

برنامه نویسی که مجبور باشد برای هر پروژه جدید تمام کدها را بنویسد نمی تواند در بازار رقابت کند، چرا که برای هر پروژه باید از صفر کدنویسی کرده و در نتیجه زمان اجرای پروژه ها طولانی شده و از رقبا عقب می افتد. ممکن است این تصور برای شما پیش بیاید که هر پروژه متفاوت از پروژه دیگر است و باید برای آن کد نویسی جداگانه ای انجام داد. بله همین طور است اما بسیاری از قسمت های کوچک در پروژه های مختلف وجود دارد که به هم دیگر شباهت دارند. به عبارت دیگر اگر یک بار کد آن را نوشته باشید به راحتی می توانید در پروژه های بعدی با کمی تغییر از آن استفاده کنید. اما باید زبان برنامه نویسی هم قابلیت استفاده مجدد از کدها را داشته باشد. زبانی که استفاده می شود باید توانایی ایجاد کتابخانه های انعطلاف پذیر را داشته باشد، تا برنامه نویس بتواند از کتابخانه هایی که آزمایش (test)، اشکال زدایی (debug) و تایید (verify) شده اند در پروژه های آینده استفاده کند. همچنین لازم است امکان انطباق  کتابخانه با میکروکنترلرهای جدید وجود داشته باشد.

کارکنان یک مجموعه تغییر می کنند و حتی اگر ثابت باشند، حافظه ی انسان بازه ی زمانی محدودی را به خاطر می آورد. هر سیستمی نیاز به ارتقا و به روز رسانی دارد و اگر برنامه ی آن به شیوه ی درستی نوشته و مستند سازی نشده باشد، درک و تغییر آن مشکل می شود.

 بنابراین برنامه ی خوب، برنامه ای است که امکان درک و تغییر آن در هر زمان وجود داشته باشد (نه فقط به وسیله ی طراح اولیه، بلکه به وسیله افراد دیگر). علاوه بر موارد فوق لازم است به این نکته توجه شود که در اجرای پروژه های بزرگ و پیچیده اگر از سبک برنامه نویسی مناسبی استفاده نشود، نگهداری و اشکال زدایی برنامه بسیار مشکل می شود، هزینه ها افزایش می یابد و امکان موفقیت طرح به حداقل می رسد. همچنین گاهی لازم است پروژه های بزرگ به اجزای کوچکتری خرد شوند و هر بخش را فرد و یا تیم مستقلی پیاده سازی کند. با استفاده از سبک برنامه نویسی ماژولار، می توانیم کتابخانه هایی ایجاد کنیم که به سادگی قابل تغییر و قابل استفاده در پروژه های دیگر هستند. اما برنامه نویسی ماژولار چیست؟

مفهوم ماژول نرم افزاری

ماژول به معنای مولفه و یا جزئی از برنامه است که خود شامل تعدادی تابع مرتبط با یکدیگر است. معمولا مجموع توابعی که داخل یک ماژول قرار می گیرند عملکرد خاصی را پیاده سازی می کنند. برخی از ماژول ها فرآیندی را بر روی داده انجام می دهند. در این نوع ماژول ها، بخشی از برنامه به عنوان مشتری، سرویسی را از ماژول درخواست می کند و ماژول آن درخواست را پاسخ می دهد. برخی از ماژول ها نیز ارتباط برنامه با یک سخت افزار داخلی (مانند پورت های سریال، مبدل آنالوگ به دیجیتال و …) یا خارجی (مانند نمایشگر LCD، صفحه کلید، سنسور و …) را برقرار می کنند.

 هر ماژول شامل دو بخش پیاده سازی و واسط (Interface) است. در بخش پیاده سازی، بدنه ی توابع قرار می گیرند و شامل چگونگی انجام یک موضوع است. در بخش واسط نحوه ی استفاده از توابع، در اختیار کاربر (مشتری سرویس) قرار می گیرد. این بخش، شامل اطلاعاتی است که برای استفاده از یک موضوع مورد نیاز است.

یکی از دلایل اساسی استفاده از ماژول این است که بتوان بخش های لازم از یک موضوع را مشخص و بخش های غیر ضروری را پنهان کرد. به پنهان سازی جزئیات غیر ضروری، Abstraction گفته می شود. از این مفهوم در طراحی بسیاری از وسایل استفاده می شود. به عنوان مثال زمانی که یک خودرو را می رانیم لزوما نیاز نیست که از نحوه ی عملکرد موتور و سایر اجزا آن آگاهی داشته باشیم، بلکه کافی است که واسط استفاده موتور(شامل پدال های کلاچ، ترمز و گاز) در اختیارمان باشد و نحوه ی به کارگیری این واسط را بدانیم. در برنامه نویسی نیز، Abstraction مفهوم بسیار ارزشمندی است که در زبان های شی گرا (مانند java و C++) به شکل عالی و در زبان های ماژولار به شکل ابتدایی از آن پشتیبانی شده است.

در نهایت باید به این موضوع اشاره شود که متاسفانه زبان C از شی گرایی و برنامه نویسی ماژولار پشتیبانی نمی کند، اما با استفاده از فایل های سورس (source) و هدر (header) می توان تا حدودی به شیوه ی ماژولار برنامه نویسی کرد. می توانید در پست کتابخانه نویسی در زبان C با مفهوم برنامه نویسی ماژولار در این زبان آشنا شده و به صورت عملی کتابخانه نویسی را تمرین کنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *