طراحی دادهمحور دهههاست که به شکلهای مختلف وجود دارد، اما نخستین بار در سال ۲۰۰۹، نوئل لوپیس (Noel Llopis) آن را بهطور رسمی با همین نام معرفی کرد. اینکه آیا طراحی دادهمحور را میتوان یک پارادایم برنامهنویسی دانست یا نه، همچنان محل بحث است. بسیاری معتقدند که میتوان از آن در کنار سایر پارادایمهای برنامهنویسی، مانند برنامهنویسی شیگرا، رویهای یا تابعی استفاده کرد. از یک نظر، حق با آنهاست، طراحی دادهمحور میتواند در کنار پارادایمهای دیگر به کار گرفته شود، اما این موضوع مانع از آن نمیشود که آن را رویکردی برای توسعه نرمافزار در مقیاس بزرگ بدانیم.
سایر پارادایمهای برنامهنویسی نیز تا حدی در کنار یکدیگر کار میکنند. یک برنامهنویس Lisp میداند که برنامهنویسی تابعی میتواند با برنامهنویسی شیگرا همزیستی داشته باشد. به همین ترتیب، یک برنامهنویس C بهخوبی میداند که برنامهنویسی شیگرا میتواند در کنار برنامهنویسی رویهای به کار گرفته شود. بنابراین، بهجای پرداختن به این بحثها، طراحی دادهمحور را بهعنوان ابزار مهم دیگری در نظر میگیریم، ابزاری که بهاندازه سایر رویکردها میتواند در کنار آنها به کار گرفته شود.
امروزه حتی دستگاههایی که در جیب خود حمل میکنیم، از پردازندههای چندهستهای بهره میبرند. به همین دلیل، یادگیری روشهایی برای توسعه نرمافزار که وابستگی کمتری به اجرای ترتیبی دارند، اهمیت زیادی پیدا کرده است. یکی از مزایای رویکرد دادهمحور، فاصله گرفتن از الگوی ارسال پیام میان اشیا و انتظار برای دریافت پاسخ فوری است.
برنامهنویسی با تمرکز جدی بر شناخت جریان دادهها، زمینه را برای برداشتن گام بعدی بهسوی GPGPU و سایر روشهای محاسباتی فراهم میکند. این رویکرد به مدیریت حجم پردازشی موردنیاز برای جان بخشیدن به بازیهای ویدئویی کمک میکند. نیاز به طراحی دادهمحور در آینده بیشتر هم خواهد شد؛ زیرا انتزاعهای نرمافزاری و تفکر ترتیبی به گلوگاه عملکرد رقبای شما تبدیل خواهند شد، درحالیکه توسعهدهندگانی که رویکرد دادهمحور را میپذیرند، عملکرد بهتری خواهند داشت.
همهچیز به دادهها مربوط میشود
داده تنها چیزی است که در اختیار داریم. برای ایجاد یک تجربه کاربری، باید دادهها را تغییر دهیم. هنگام باز کردن یک سند، دادهها را بارگذاری میکنیم. دادهها همان گرافیک نمایشدادهشده روی صفحه، سیگنالهای ناشی از فشردن دکمههای دسته بازی، اطلاعاتی هستند که باعث میشوند بلندگوها امواج صوتی تولید کنند، و مبنای محاسبه ارتقای سطح شخصیت بازی و حتی تشخیص موقعیت شما توسط دشمنی هستند که به سمتتان شلیک میکند.
دادهها مشخص میکنند که انفجار دینامیت چقدر طول کشیده است و هنگام افتادن روی تیغهها، چند حلقه از دست دادهاید. آنها همچنین موقعیت و سرعت فعلی تکتک ذرات موجود در صحنه زیبایی را مشخص میکنند که پایان بازی را رقم میزند. این بازی از روی دیسک بارگذاری شده و از طریق مجموعهای از تبدیلها به بخشی از تجربه شما تبدیل میشود، تبدیلهایی که سختافزار آنها را اجرا میکند، دستورالعملهای رمزگشاییشده آنها را هدایت میکنند، اسمبلرها دستورالعملها را سازماندهی میکنند، کامپایلرها اسمبلرها را هدایت میکنند و کد منبع ورودی کامپایلرها را تشکیل میدهد.
هیچ برنامهای بدون دادههایش معنایی ندارد. Adobe Photoshop بدون تصاویر، چیزی نیست. بدون قلمموها، لایهها و میزان فشار قلم نیز کاربردی نخواهد داشت. Microsoft Word بدون نویسهها، فونتها و شکست صفحه بیمعناست. FL Studio بدون رویدادها ارزشی ندارد و Visual Studio نیز بدون کد منبع چیزی برای کار کردن ندارد.
تمام برنامههایی که تاکنون نوشته شدهاند، با هدف تولید دادههای خروجی بر اساس دادههای ورودی ساخته شدهاند. شکل این دادهها ممکن است بسیار پیچیده باشد یا آنقدر ساده که اصلا نیازی به مستندسازی نداشته باشد، اما همه برنامهها داده تولید میکنند و برای انجام کار خود به داده نیاز دارند. اگر برنامهای به دادههای قابلتشخیص و معنادار نیاز نداشته باشد، در بهترین حالت چیزی جز یک اسباببازی یا نمونه نمایشی فناوری (Tech Demo) نخواهد بود.
دستورالعملها نیز نوعی داده هستند. آنها حافظه اشغال میکنند، از پهنای باند استفاده میکنند و میتوان آنها را تبدیل، بارگذاری، ذخیره و تولید کرد. طبیعی است که یک توسعهدهنده دستورالعملها را داده در نظر نگیرد، اما در سختافزارهای قدیمیتر و کممحدودیتتر، تفاوت چندانی میان این دو وجود نداشت.
اگرچه در بیشتر سختافزارهای امروزی، بخش حافظه اختصاصیافته به فایلهای اجرایی در برابر تغییر یا آسیب محافظت میشود، این سازوکار نسبتا جدید همچنان یک انتخاب در طراحی سختافزار است. معماری اصلاحشده هاروارد (Modified Harvard Architecture) نیز برای دادهها و دستورالعملها از یک فضای حافظه مشترک استفاده میکند. بنابراین، دستورالعملها همچنان داده محسوب میشوند و خود آنها نیز چیزی هستند که تغییر میدهیم.
ما دستورالعملها را میگیریم و آنها را به اجرا درمیآوریم. تعداد، اندازه و دفعات اجرای آنها اهمیت دارد. وقتی بدانیم برای حل یک مسئله میتوانیم از میان دستورالعملهای مختلف انتخاب کنیم، زمینه برای بهینهسازی فراهم میشود. شناخت ویژگیهای دادهها به ما کمک میکند تصمیم بگیریم چگونه آنها را پردازش کنیم. همچنین، آگاهی از نتیجه اجرای دستورالعملها اطلاعات لازم را در اختیارمان میگذارد تا تشخیص دهیم کدام دستورالعملها ضروریاند، کدام فقط هزینه پردازشی اضافی ایجاد میکنند و کدام را میتوان با گزینههایی معادل اما کمهزینهتر جایگزین کرد.
این موضوع مبنای استدلال برای استفاده از رویکرد دادهمحور در توسعه نرمافزار است، اما هنوز یک عنصر مهم را نادیده گرفتهایم. تمام این دادهها و تبدیلهای آنها، از رشتههای متنی گرفته تا تصاویر و دستورالعملها، باید روی بستری اجرا شوند.
گاهی این بستر کاملا انتزاعی است، مثلا یک ماشین مجازی که روی سختافزاری ناشناخته اجرا میشود. گاهی نیز با سختافزاری مشخص سروکار داریم و میدانیم از کدام CPU و GPU استفاده میکنیم و چه مقدار حافظه و پهنای باند در اختیار داریم. در هر دو حالت، دادهها صرفا اطلاعاتی انتزاعی نیستند، بلکه روی سختافزاری مشخص وجود دارند و همان سختافزار باید آنها را پردازش کند.
در اصل، طراحی دادهمحور رویکردی برای طراحی نرمافزار است که در آن، تبدیل دادههای ساختاریافته بهگونهای طراحی میشود که ویژگیهای سختافزار هدف و الگوها و انواع پردازشهای موردنیاز، معیارهای اصلی تصمیمگیری باشند.
گاهی دادهها تعریف دقیقی ندارند و گاهی نیز شناخت سختافزار به همین اندازه دشوار است. بااینحال، در بیشتر موارد، شناخت مناسب از سختافزار میتواند به تقریباً هر پروژه نرمافزاری کمک کند.
اگر خروجی نهایی یک برنامه داده باشد، تمام ورودیهای آن را بتوان به شکل داده نمایش داد و بدانیم که پردازش دادهها در خلا انجام نمیشود، میتوان روش توسعه نرمافزاری را بر پایه این اصول بنا کرد: شناخت دادهها و نحوه تبدیل آنها، با در نظر گرفتن این موضوع که سختافزار چگونه دادههایی با حجم، نرخ ورود و ویژگیهای آماری مشخص را پردازش خواهد کرد.
با تکیه بر این مبانی، میتوانیم مجموعهای از اصول پایه را تعریف کنیم که مشخص میکنند چه چیزی یک روش توسعه را دادهمحور میکند.
دادهها و آمار
یکی از برداشتهای نادرست رایج درباره طراحی دادهمحور این است که تمام هدف آن جلوگیری از خطاهای کش (Cache Miss) است. حتی اگر تمام تمرکز این رویکرد بر جلوگیری از خطاهای کش و سازماندهی ساختارهای داده بهگونهای بود که دادههای پراستفاده و کماستفاده از یکدیگر جدا شوند، باز هم میتوانست ابزار مفیدی برای مجموعه ابزارهای یک برنامهنویس باشد. اما طراحی دادهمحور به تمام جنبههای داده توجه دارد.
برای نوشتن کتابی درباره جلوگیری از خطاهای کش، صرفا ارائه چند توصیه درباره سازماندهی ساختارهای داده کافی نیست. باید درک کنیم که هنگام اجرای برنامه، واقعا چه اتفاقی درون رایانه رخ میدهد. از سوی دیگر، آموزش کامل این موضوع در یک کتاب نیز دشوار است، زیرا بسیاری از جزئیات آن به نسل خاصی از سختافزار و زبانهای برنامهنویسی وابستهاند.
بااینحال، طراحی دادهمحور به یک زبان خاص یا مجموعهای از سختافزارهای غیرمعمول محدود نیست. هرچند C++ زبانی است که میتواند بیشترین بهره را از این رویکرد ببرد، این روش برای هر سختافزاری که گلوگاههای عملکردی نامتوازن دارد نیز مفید است.
ساختار دادهها اهمیت دارد، اما مقادیر آنها و نحوه پردازش و تبدیلشان نیز به همان اندازه مهماند، حتی ممکن است اهمیت بیشتری داشته باشند. برای مثال، داشتن چند عکس از یک یوزپلنگ برای تعیین سرعت دویدن آن کافی نیست. باید آن را در محیط طبیعیاش مشاهده کنید تا بتوانید هزینه واقعی کند بودن را درک کنید.
مدل طراحی دادهمحور بر خود دادهها متمرکز است، یعنی دادههای جاری، دادههای واقعی و دادههایی که حامل اطلاعاتاند.
در مقابل، طراحی شی محور بر تعریف مسئله تمرکز دارد. اشیا موجودیتهای واقعی نیستند، بلکه بازنماییهای انتزاعی از موقعیتی هستند که مسئله در آن حل میشود. اشیا دادههای موردنیاز برای بازنمایی خود را دستکاری میکنند، بدون آنکه لزوما سختافزار، الگوهای واقعی دادهها یا حجم آنها را در نظر بگیرند.
به همین دلیل، طراحی شی محور به شما اجازه میدهد نسخههای اولیه یک برنامه را بهسرعت بسازید. میتوانید تعریف مسئله یا نسخه اولیه سند طراحی را مستقیما به کد تبدیل کنید و در مدت کوتاهی راهحلی ابتدایی ارائه دهید.
طراحی دادهمحور رویکرد متفاوتی دارد. بهجای اینکه فرض کند شناخت چندانی از سختافزار نداریم، فرض میکند هنوز شناخت کاملی از ماهیت واقعی مسئله به دست نیاوردهایم. در این رویکرد، طرحواره دادهها (Data Schema) در اولویت دوم قرار میگیرد.
هرکسی که یک نرمافزار نسبتا بزرگ نوشته باشد، احتمالا تجربه کرده است که ساختار فنی و طراحی یک پروژه در طول توسعه آنقدر تغییر میکنند که بخش بسیار کمی از پیشنویس اولیه بدون تغییر در نسخه نهایی باقی میماند.
طراحی دادهمحور با پرهیز از این فرض که طراحی اولیه باید حتما در ساختار نهایی نرمافزار حفظ شود، از اتلاف منابع جلوگیری میکند. پیشرفت در این رویکرد از طریق حل مسئله فعلی صورت میگیرد: کدهای سطح بالا توالی رویدادها را کنترل میکنند و طرحوارهای را مشخص میکنند که به دادهها در آن مقطع معنایی موقت میدهد.
طراحی دادهمحور از دادههایی که مشاهده شدهاند یا انتظار میرود در اختیار داشته باشیم، راهنمایی میگیرد. بهجای برنامهریزی برای تمام حالتهای ممکن یا تلاش برای سازگار کردن سیستم با هر شرایطی، ترجیح داده میشود الگوریتم بر اساس محتملترین ورودیها انتخاب شود.
بهجای آنکه از ابتدا برای توسعهپذیری برنامهریزی کنیم، بهتر است ابتدا راهحلی ساده و قابلجایگزینی بسازیم که مسئله فعلی را حل کند. میتوان قابلیت توسعه را بعدا اضافه کرد و با استفاده از تستهای واحد، مطمئن شد که تغییرات جدید عملکرد صحیح قبلی را مختل نمیکنند.
خوشبختانه، روشی وجود دارد که با استفاده از تکنیکهایی که سالها پیش برای کار با پایگاههای داده توسعه یافتهاند، میتوان ساختار دادهها را بدون نیاز به پیچیدگی زیاد، توسعهپذیر طراحی کرد.
دیدگاهها
ثبت دیدگاه