حالت تاریک
فصل ۱ — توسعهٔ تکاملی پایگاه داده
آبشارها جاذبههای گردشگری فوقالعادهای هستند؛ اما بهعنوان راهبرد سازماندهی پروژههای توسعهٔ نرمافزار، بهشکل خیرهکنندهای بد هستند.
— Scott Ambler
فرایندهای مدرن نرمافزار — که به آنها متدولوژی هم میگویند — همگی ماهیت تکاملی دارند و از شما میخواهند هم تکراری (iterative) و هم افزایشی (incremental) کار کنید. نمونههایی از این فرایندها عبارتاند از: Rational Unified Process (RUP)، Extreme Programming (XP)، Scrum، Dynamic System Development Method (DSDM)، خانوادهٔ Crystal، Team Software Process (TSP)، Agile Unified Process (AUP)، Enterprise Unified Process (EUP)، Feature-Driven Development (FDD) و Rapid Application Development (RAD). در کار تکراری، هر بار کمی از یک فعالیت — مانند مدلسازی، تست، کدنویسی یا استقرار — انجام میدهید، سپس کمی دیگر، و همینطور ادامه میدهید. این رویکرد با رویکرد سریالی متفاوت است؛ در آنجا ابتدا همهٔ نیازمندیهایی که قرار است پیادهسازی شوند را مشخص میکنید، سپس طراحی دقیق میسازید، بعد مطابق آن طراحی پیادهسازی میکنید، تست میکنید و در نهایت سیستم را مستقر میکنید. در رویکرد افزایشی، سیستم را بهجای یک انتشار بزرگ، در قالب مجموعهای از انتشارها (release) سازماندهی میکنید.
علاوه بر این، بسیاری از فرایندهای مدرن چابک (agile) هستند؛ برای سادگی، آنها را تکاملی و بسیار مشارکتی مینامیم. وقتی تیم رویکرد مشارکتی دارد، فعالانه بهدنبال راههای کار مؤثر با هم میگردد؛ حتی باید تلاش کنید ذینفعان پروژه — مانند مشتریان کسبوکار — عضو فعال تیم باشند. Cockburn (2002) توصیه میکند «داغترین» روش ارتباطی متناسب با موقعیت را بپذیرید: گفتوگوی رودررو دور یک وایتبرد را بر تماس تلفنی ترجیح دهید، تماس تلفنی را بر ایمیل، و ایمیل را بر ارسال سند مفصل. هرچه ارتباط و همکاری در تیم توسعهٔ نرمافزار بهتر باشد، شانس موفقیت بیشتر است.
اگرچه روشهای تکاملی و چابک در جامعهٔ توسعهدهندگان بهخوبی پذیرفته شدهاند، در جامعهٔ داده همینطور نیست. بیشتر تکنیکهای دادهمحور ماهیت سریالی دارند و ایجاد مدلهای نسبتاً دقیق را پیشنیاز «مجاز بودن» پیادهسازی میدانند. بدتر آنکه این مدلها اغلب baseline میشوند و تحت کنترل تغییر قرار میگیرند تا تغییرات به حداقل برسد — اگر به نتیجهٔ نهایی نگاه کنید، در واقع باید آن را فرایند جلوگیری از تغییر نامید. مشکل اینجاست: تکنیکهای رایج توسعهٔ پایگاه داده با واقعیت فرایندهای مدرن توسعهٔ نرمافزار همخوان نیستند؛ لازم نیست همیشه اینطور باشد.
فرض ما این است که متخصصان داده باید تکنیکهای تکاملی مشابه توسعهدهندگان را بپذیرند. شاید بگویید توسعهدهندگان باید به رویکردهای سنتی و «آزمودهشده» جامعهٔ داده بازگردند؛ اما روزبهروز بیشتر مشخص میشود که روشهای سنتی خوب کار نمیکنند. در فصل ۵ کتاب Agile & Iterative Development، Craig Larman (2004) شواهد پژوهشی و همچنین حمایت گستردهٔ رهبران فکری جامعهٔ فناوری اطلاعات (IT) از رویکردهای تکاملی را جمعبندی میکند. نتیجهٔ نهایی این است که تکنیکهای تکاملی و چابک رایج در جامعهٔ توسعه، بسیار بهتر از تکنیکهای سنتی رایج در جامعهٔ داده عمل میکنند.
برای متخصصان داده امکان پذیرش رویکردهای تکاملی در همهٔ جنبههای کار وجود دارد، اگر بخواهند. گام اول بازاندیشی «فرهنگ داده» در سازمان IT است تا نیازهای تیمهای پروژهٔ مدرن را منعکس کند. روش Agile Data (AD) (Ambler 2003) دقیقاً همین کار را میکند و مجموعهای از فلسفهها و نقشها برای فعالیتهای دادهمحور مدرن را توصیف میکند. این فلسفهها نشان میدهند داده یکی از جنبههای مهم نرمافزار کسبوکار است؛ یعنی توسعهدهندگان باید در تکنیکهای داده ماهرتر شوند و متخصصان داده باید فناوریها و مهارتهای توسعهٔ مدرن را بیاموزند. روش AD میپذیرد هر تیم پروژه منحصربهفرد است و باید فرایندی متناسب با موقعیت خود دنبال کند. بر اهمیت نگاه فراتر از پروژهٔ جاری برای مسائل سازمانی نیز تأکید میشود؛ همچنین بر نیاز به انعطاف متخصصان سازمانی — مانند DBA عملیاتی و معماران داده — برای همکاری چابک با تیمهای پروژه.
گام دوم برای متخصصان داده — بهویژه مدیران پایگاه داده — پذیرش تکنیکهای جدیدی است که کار تکاملی را ممکن میسازد. در این فصل، این تکنیکهای حیاتی را بهاختصار مرور میکنیم؛ بهنظر ما مهمترین آنها بازآرایی پایگاه داده (database refactoring) است که محور این کتاب است. تکنیکهای توسعهٔ تکاملی پایگاه داده عبارتاند از:
- بازآرایی پایگاه داده — تکامل تدریجی طرحوارهٔ موجود پایگاه داده، تکهتکه، برای بهبود کیفیت طراحی بدون تغییر معناشناسی.
- مدلسازی دادهٔ تکاملی — مدلسازی تکراری و افزایشی جنبههای دادهٔ سیستم، مانند سایر جنبهها، تا طرحوارهٔ پایگاه داده همگام با کد برنامه تکامل یابد.
- تست رگرسیون پایگاه داده — اطمینان از اینکه طرحوارهٔ پایگاه داده واقعاً کار میکند.
- مدیریت پیکربندی (configuration management) مصنوعات پایگاه داده — مدلهای داده، تستهای پایگاه داده، دادهٔ آزمون و موارد مشابه مصنوعات مهم پروژهاند و باید مانند سایر مصنوعات مدیریت شوند.
- محیطهای ایزولهٔ توسعهدهنده (developer sandboxes) — توسعهدهندگان به محیط کاری اختصاصی نیاز دارند تا بخشی از سیستمی که میسازند را تغییر دهند و قبل از یکپارچهسازی با همتیمیها آن را به کار بیندازند.
اکنون هر تکنیک را با جزئیات بیشتر بررسی میکنیم.
۱.۱. بازآرایی پایگاه داده
بازآرایی (refactoring) (Fowler 1999) روشی منضبط برای اعمال تغییرات کوچک در کد منبع است تا طراحی بهبود یابد و کار با آن آسانتر شود. جنبهٔ حیاتی بازآرایی این است که معناشناسی رفتاری کد را حفظ میکند — در بازآرایی چیزی اضافه یا حذف نمیکنید؛ فقط کیفیت را بهتر میکنید. مثال بازآرایی: تغییر نام عملیات getPersons() به getPeople(). برای پیادهسازی، باید تعریف عملیات و سپس هر فراخوانی آن در سراسر کد برنامه را تغییر دهید. بازآرایی تا وقتی کامل نیست که کد دوباره مثل قبل اجرا شود.
بهطور مشابه، بازآرایی پایگاه داده تغییری ساده در طرحوارهٔ پایگاه داده است که طراحی را بهبود میدهد و هم معناشناسی رفتاری و هم اطلاعاتی را حفظ میکند. میتوانید جنبههای ساختاری طرحواره — مانند تعاریف جدول و نما — یا جنبههای عملکردی — مانند stored procedure و trigger — را بازآرایی کنید. هنگام بازآرایی طرحواره، نهتنها خود طرحواره، بلکه سیستمهای بیرونی متصل به آن — مانند برنامههای کسبوکار یا استخراج داده — نیز باید بازنگری شوند. بازآرایی پایگاه داده از بازآرایی کد دشوارتر است؛ پس باید محتاط باشید. بازآرایی پایگاه داده در فصل ۲ و فرایند انجام آن در فصل ۳ با جزئیات توضیح داده میشود.
۱.۲. مدلسازی دادهٔ تکاملی
هرچه شنیده باشید، تکنیکهای تکاملی و چابک صرفاً «کد و تعمیر» (code and fix) با نام جدید نیستند. هنوز باید نیازمندیها را کاوش کنید و قبل از ساخت، معماری و طراحی را فکر کنید؛ یکی از راههای خوب، مدلسازی قبل از کدنویسی است. شکل ۱.۱ چرخهٔ عمر Agile Model-Driven Development (AMDD) (Ambler 2004; Ambler 2002) را نشان میدهد. در AMDD، در ابتدای پروژه مدلهای اولیه و سطحبالا میسازید که دامنهٔ مسئله و معماری بالقوه را مرور میکنند. یکی از مدلهای معمول، مدل مفهومی/دامنهٔ «لاغر» است که موجودیتهای اصلی کسبوکار و روابطشان را نشان میدهد (Fowler and Sadalage 2003). شکل ۱.۲ نمونهای برای یک مؤسسهٔ مالی ساده است. میزان جزئیات این نمونه همان چیزی است که در ابتدای پروژه لازم دارید؛ هدف این است که مسائل اصلی را زود فکر کنید بدون سرمایهگذاری بیمورد در جزئیات — جزئیات را بعداً بهصورت just-in-time (JIT) پر میکنید.
شکل ۱.۱. چرخهٔ عمر Agile Model-Driven Development (AMDD).
شکل ۱.۲. مدل مفهومی/دامنه برای یک مؤسسهٔ مالی فرضی با UML.
مدل مفهومی شما با رشد درک دامنه طبیعتاً تکامل مییابد، اما سطح جزئیات ثابت میماند. جزئیات در مدل شیء (که میتواند خود کد منبع باشد) و مدل دادهٔ فیزیکی (PDM) ثبت میشوند. این مدلها تحت هدایت مدل دامنهٔ مفهومی و همزمان با سایر مصنوعات برای حفظ سازگاری توسعه مییابند. شکل ۱.۳ PDM دقیقی را نشان میدهد که در پایان چرخهٔ سوم توسعه وجود دارد. اگر «چرخهٔ ۰» یک هفته و چرخههای توسعه دو هفتهای باشند (برای پروژههای کمتر از یک سال معمول است)، این PDM در پایان هفتهٔ هفتم پروژه وجود دارد. PDM نیازمندیهای داده و محدودیتهای legacy پروژه تا آن لحظه را منعکس میکند. نیازمندیهای داده برای چرخههای آینده در همان چرخهها بهصورت JIT مدلسازی میشوند.
شکل ۱.۳. مدل دادهٔ فیزیکی (PDM) دقیق با UML.
مدلسازی دادهٔ تکاملی آسان نیست. باید محدودیتهای دادهٔ legacy را در نظر بگیرید؛ و همانطور که میدانیم، منابع دادهٔ legacy اغلب موجودات خطرناکیاند که پروژهٔ نرمافزاری غافل را آسیب میزنند. خوشبختانه متخصصان دادهٔ خوب تفاوتهای ظریف منابع دادهٔ سازمان را میشناسند و این تخصص را بهراحتی بهصورت JIT — همانقدر که در رویکرد سریالی — به کار میگیرند. هنوز باید قراردادهای هوشمندانهٔ مدلسازی داده را رعایت کنید، همانطور که practice «Apply Modeling Standards» در Agile Modeling پیشنهاد میکند. نمونهٔ مفصل مدلسازی دادهٔ تکاملی/چابک در آدرس www.agiledata.org/essays/agileDataModeling.html موجود است.
۱.۳. تست رگرسیون پایگاه داده
برای تغییر امن نرمافزار موجود — چه برای بازآرایی و چه برای افزودن قابلیت — باید بتوانید بعد از تغییر تأیید کنید چیزی را نشکستهاید؛ یعنی باید بتوانید تست رگرسیون کامل اجرا کنید. اگر چیزی خراب شد، یا تعمیر کنید یا تغییرات را برگردانید. در جامعهٔ توسعه، رایج شده برنامهنویسان مجموعهٔ تست واحد کامل را همزمان با کد دامنه بسازند؛ در واقع چابککاران ترجیح میدهند قبل از کد «واقعی»، کد تست بنویسند. همانطور که کد منبع برنامه را تست میکنید، آیا پایگاه داده را هم نباید تست کنید؟ منطق مهم کسبوکار در پایگاه داده — بهصورت stored procedure، قواعد اعتبارسنجی داده و قواعد یکپارچگی ارجاعی (RI) — پیادهسازی شده و باید بهطور کامل تست شود.
توسعهٔ تستاول (Test-First Development — TFD)، که به Test-First Programming هم معروف است، رویکرد تکاملی است؛ ابتدا باید تستی بنویسید که شکست بخورد، سپس کد عملکردی جدید. همانطور که نمودار فعالیت UML شکل ۱.۴ نشان میدهد، گامهای TFD اینهاست:
شکل ۱.۴. رویکرد توسعهٔ تستاول.
- سریع یک تست اضافه کنید — بهقدری که تستها اکنون شکست بخورند.
- تستها را اجرا کنید — اغلب کل مجموعه، هرچند برای سرعت شاید زیرمجموعهای — تا مطمئن شوید تست جدید واقعاً شکست میخورد.
- کد عملکردی را بهروز کنید تا تست جدید را پاس کند.
- دوباره تستها را اجرا کنید. اگر شکست خوردند به گام ۳ برگردید؛ وگرنه از نو شروع کنید.
مزایای اصلی TFD: مجبورتان میکند قبل از پیادهسازی قابلیت جدید آن را فکر کنید (در عمل طراحی دقیق میکنید)، اطمینان میدهد کد تست برای اعتبارسنجی کار دارید، و جسارت میدهد بدانید میتوانید سیستم را تکامل دهید چون میتوانید بفهمید تغییر چیزی را نشکسته یا نه. همانطور که مجموعهٔ تست رگرسیون کامل برای کد منبع، بازآرایی کد را ممکن میسازد، مجموعهٔ تست رگرسیون کامل برای پایگاه داده، بازآرایی پایگاه داده را ممکن میکند (Meszaros 2006).
توسعهٔ رانشمحور تست (Test-Driven Development — TDD) (Astels 2003; Beck 2003) ترکیب TFD و بازآرایی است. ابتدا با TFD کد مینویسید؛ وقتی کار کرد، با بازآرایی در صورت نیاز کیفیت طراحی را حفظ میکنید. هنگام بازآرایی باید تستهای رگرسیون را دوباره اجرا کنید.
پیامد مهمی این است که احتمالاً به چند ابزار تست واحد نیاز دارید — حداقل یکی برای پایگاه داده و یکی برای هر زبان برنامهنویسی در برنامههای بیرونی. خانوادهٔ XUnit (مثلاً JUnit برای Java، VBUnit برای Visual Basic، NUnit برای .NET و OUnit برای Oracle) خوشبختانه رایگان و نسبتاً یکدستاند.
۱.۴. مدیریت پیکربندی مصنوعات پایگاه داده
گاهی تغییری در سیستم ایدهٔ بدی است و باید به حالت قبلی برگردانید. مثلاً تغییر نام ستون Customer.FName به Customer.FirstName ممکن است ۵۰ برنامهٔ بیرونی را بشکند و هزینهٔ بهروزرسانی آنها فعلاً زیاد باشد. برای فعالسازی بازآرایی پایگاه داده، موارد زیر را تحت کنترل مدیریت پیکربندی قرار دهید:
- اسکریپتهای DDL برای ایجاد طرحوارهٔ پایگاه داده
- اسکریپتهای بارگذاری/استخراج/مهاجرت داده
- فایلهای مدل داده
- متادیتای نگاشت شیء/رابطهای (O/R)
- دادهٔ مرجع (reference data)
- تعاریف stored procedure و trigger
- تعاریف view
- محدودیتهای یکپارچگی ارجاعی
- سایر اشیای پایگاه داده مانند sequence، index و غیره
- دادهٔ آزمون
- اسکریپتهای تولید دادهٔ آزمون
- اسکریپتهای تست
۱.۵. محیطهای ایزولهٔ توسعهدهنده
sandbox محیطی کاملاً عملیاتی است که در آن سیستم ساخته، تست و/یا اجرا میشود. sandboxهای مختلف را برای امنیت جدا نگه دارید — توسعهدهندگان باید در sandbox خود بدون ترس از آسیب به کارهای دیگران کار کنند، گروه QA/تست باید بتواند تست یکپارچهسازی سیستم را امن اجرا کند، و کاربران نهایی بدون نگرانی از خراب شدن دادهٔ منبع یا عملکرد سیستم توسط توسعهدهندگان، سیستم خود را اجرا کنند. شکل ۱.۵ سازماندهی منطقی sandboxها را نشان میدهد — «منطقی» میگوییم چون محیط بزرگ/پیچیده ممکن است هفت یا هشت sandbox فیزیکی داشته باشد، محیط کوچک/ساده شاید دو یا سه تا.
شکل ۱.۵. sandboxهای منطقی برای امنیت توسعهدهندگان.
برای بازآرایی موفق طرحوارهٔ پایگاه داده، توسعهدهندگان به sandbox فیزیکی اختصاصی، کپی کد منبع برای تکامل، و کپی پایگاه داده برای کار و تکامل نیاز دارند. با محیط اختصاصی، میتوانند امن تغییر دهند، تست کنند، و بپذیرند یا برگردانند. وقتی مطمئن شدند بازآرایی پایگاه داده عملی است، آن را به محیط مشترک پروژه promote میکنند، تست میکنند، و تحت کنترل تغییر قرار میدهند تا بقیهٔ تیم هم بگیرند. در نهایت تیم کار خود — شامل همهٔ بازآراییهای پایگاه داده — را به محیطهای دمو و/یا پیشتولید promote میکند. این promote اغلب یکبار در هر چرخهٔ توسعه است، اما بسته به محیط میتواند بیشتر یا کمتر باشد (هرچه بیشتر promote کنید، شانس بازخورد ارزشمند بیشتر است). در نهایت، پس از پذیرش و تست سیستم، در تولید مستقر میشود. فصل ۴ «استقرار در تولید» این فرایند promote/استقرار را با جزئیات بیشتر پوشش میدهد.
۱.۶. موانع تکنیکهای توسعهٔ تکاملی پایگاه داده
اگر دربارهٔ موانع رایج پذیرش تکنیکهای این کتاب صحبت نکنیم، قصور کردهایم. اولین مانع — و سختترین — فرهنگی است. بسیاری از متخصصان دادهٔ امروز در دههٔ ۱۹۷۰ و اوایل ۱۹۸۰ شروع کردند، وقتی رویکردهای code-and-fix رایج بود. جامعهٔ IT فهمید این رویکرد کد کمکیفیت و سختنگهداری میدهد و تکنیکهای سنگین و ساختیافتهای را پذیرفت که هنوز بسیاری دنبال میکنند. بهخاطر این تجربهها، اکثر متخصصان داده فکر کردند تکنیکهای تکاملی انقلاب فناوری شیء در دههٔ ۱۹۹۰ بازگشت همان code-and-fix دههٔ ۱۹۷۰ است؛ منصفانه است بگوییم بسیاری از شیءگرایان واقعاً آنطور کار میکردند. آنها رویکردهای تکاملی را با کیفیت پایین یکی دانستند؛ اما همانطور که جامعهٔ چابک نشان داد، لازم نیست اینطور باشد. نتیجه این است که بیشتر ادبیات دادهمحور در تفکر سنتی و سریالی گذشته غرق مانده و عمدتاً رویکردهای چابک را از دست داده است. جامعهٔ داده کار زیادی برای جبران دارد و زمان میبرد.
مانع دوم کمبود ابزار است، هرچند تلاشهای متنباز (حداقل در جامعهٔ Java) سریع شکاف را پر میکنند. تلاش زیادی برای ابزارهای نگاشت O/R و مقداری برای ابزار تست پایگاه داده شده، اما هنوز کار زیادی باقی است. همانطور که چند سال طول کشید تا فروشندگان ابزار برنامهنویسی قابلیت بازآرایی را در IDEها بگنجانند — امروز سخت است IDE مدرنی بدون این قابلیت پیدا کنید — چند سال طول میکشد تا فروشندگان ابزار پایگاه داده همین کار را بکنند. نیاز به ابزارهای قابلاستفاده و انعطافپذیر برای توسعهٔ تکاملی طرحوارهٔ پایگاه داده آشکار است؛ جامعهٔ متنباز شروع به پر کردن شکاف کرده و احتمالاً فروشندگان تجاری هم در نهایت همین کار را خواهند کرد.
۱.۷. آنچه آموختید
رویکردهای تکاملی توسعه که ماهیت تکراری و افزایشی دارند، استاندارد de facto توسعهٔ نرمافزار مدرناند. وقتی تیم پروژه این رویکرد را انتخاب میکند، همه — از جمله متخصصان داده — باید تکاملی کار کنند. خوشبختانه تکنیکهای تکاملی وجود دارد که به متخصصان داده امکان کار تکاملی میدهد: بازآرایی پایگاه داده، مدلسازی دادهٔ تکاملی، تست رگرسیون پایگاه داده، مدیریت پیکربندی مصنوعات دادهمحور، و sandboxهای جداگانهٔ توسعهدهنده.