تجرید سوراخ!

به تازگی خوندن کتاب Joel On Software از از Joel Spolsky رو تموم کردم که مقاله‌های خیلی خوبی داشت. یک قسمت از متنش که خیلی برام جالب بود و دوست دارم در موردش بنویسم در مورد Leaky Abstraction بود که ترجمه‌اش می‌کنم تجرید سوراخ! اگر کلمه تجرید براتون خیلی غریب هستش، هر جا که تو متن دیدینش به جاش بخونید abstraction.تجرید سوراخ یعنی چی؟ یعنی هر نوع تجریدی که باعث بشه شما همچنان نیاز داشته باشید تا جزییاتی از چیزی که روش تجرید انجام دادید رو بدونید. بذارید چند تا مثالی که خود Joel زده (با کمی تغییر) رو بگم که براتون واضح‌تر بشه:زبان SQL برای این طراحی شده که نیاز نداشته باشیم تا مرحله به مرحله به دیتابیس بگیم که چه کارهایی انجام بده تا اطلاعات مورد نظر ما رو بهمون برگردونه. مثلاً کافیه بگیم select * from products where id<10 and price>100 تا از جدول محصولات، محصولاتی که شماره‌شون کمتر از ۱۰ هستش و قیمتشون بیشتر از ۱۰۰ هستش رو پیدا بکنیم. حالا فرض کنید الگوریتم اجرای کویری اینطوری پیاده‌سازی شده که اول تمام ردیف‌هایی که شرط اول رو دارند رو پیدا می‌کنه و بعد شرط دوم رو چک می‌کنه. حالا اگر کویری select * from products where price>100 and id<10 رو اجرا کنیم، ممکنه خیلی بیشتر طول بکشه چون احتمالاً محصولات زیادی هستند که قیمتشون بیشتر از ۱۰۰ هستش و باید توی همه‌ی اون‌ها دنبال اون‌هایی که شماره‌شون کمتر از ۱۰ هستش بگردیم. SQL به ما قول داده بود که نیازی نداشته باشیم تا بدونیم چجوری یه کویری رو اجرا می‌کنه و چجوری باید اطلاعات رو از دیتابیس بخونیم، ولی چون سیستممون کند شده باید چنین کلک‌هایی رو یاد بگیریم تا دوباره سرعتش رو بهبود بدیم.وقتی توی زبان‌های سطح پایین، یه آرایه دو بعدی تعریف می‌کنیم. خیلی فرق داره که این آرایه دوبعدی رو ستونی پیمایش کنیم یا ردیفی و ممکنه سرعت برنامه‌مون رو تحت تاثیر قرار بده. قبلاً بهمون گفته بودند که RAM یعنی Random Access Memory! یعنی به هر جای RAM با سرعت یکسانی می‌شه دسترسی پیدا کرد. ولی خب در واقعیت اینجوری نیست، کلی مکانیزم cache و pagefault و ... وجود داره تا دسترسی‌های خطی سریعتر بشن. این نشون می‌ده که این تجرید هم سوراخه و ما برای بهبود سرعت برنامه‌مون باید دقیق بدونیم که مکانیزم دسترسی به RAM چطوری هستش.پروتکل شبکه TCP به ما یک ارتباط قابل اطمینان رو ارائه می‌ده. یعنی مطمئن هستش که دیتا خراب نشده، به ترتیب رسیده و ... . این در حالی هستش که این پروتکل روی پروتکل IP پیاده‌سازی شده که خودش یک پروتکل غیرقابل اطمینان هستش و صرفاً تمام تلاشش رو می‌کنه تا پکت‌ها رو به مقصد برسونه. بنابراین اگر در لایه IP مشکلی به وجود بیاد TCP قطعاً نمی‌تونه قول‌هایی که بهمون داده بود رو اجرا بکنه و دچار مشکل می‌شه.مثال‌های دیگری که خودم به ذهنم رسید و شاید براتون جالب باشه:فریم‌ورک وب جانگو خودش یک ORM ارائه می‌ده، تا دیگه به فکر ساختن جداول SQL و اینها نباشیم. خودش برامون جداول و ستون‌های مختلف رو می‌سازه، حواسش به تایپ‌های مختلف فیلدها هستش و چیزهایی از این قبیل. در واقع سعی می‌کنه که ما فقط نیاز داشته باشیم تا با یه سری object کار بکنیم و خودش این object ها رو به جداول دیتابیس مرتبط بکنه. اما بعضی وقت‌ها این تجرید سوراخ می‌شه و توابعی مثل select_related رو به وجود میاره تا ما بتونیم بهش راهنمایی بکنیم که کدوم جداول رو باید با جدول object فعلی join کنه تا سرعت بهتری در ادامه کار داشته باشیم. ولی اگر ندونیم SQL چیه و join چیه نمی‌تونیم سرعت کارمون رو بهبود بدیم.داکر، یک نوع تجرید برای اجرای هر برنامه‌ای بدون این که نیاز باشه نیازمندی‌هاش رو نصب کنیم و بدونیم که چجوری تنظیمش بکنیم هستش. در واقع همه‌ی اپلیکیشن‌ها رو به صورت یک سری container می‌بینه و می‌گه شما مستقل از این که بدونید توی container چه اتفاقی می‌افته می‌تونید اجراش بکنید و از امکاناتش استفاده بکنید. مثلاً من خود این وبلاگ رو با اجرای یک دستور تو داکر بالا اوردم. مشکل این تجرید هم اینجاست که ممکنه برای container شما یک مشکلی به وجود بیاد، و شما باید برید داخل container تا بفهمید دقیقاً مشکل کجاست و چجوری می‌شه حلش کرد. یه جورایی باید بدونید ساز و کار اپلیکیشنی که داخل container هستش چیه تا بتونید درستش بکنید.اعتراضاتی که به این استدلال‌ها وجود داره اینه که اکثرشون برای بهبود سرعت و کارایی هستش، اما خب ما هم در جهانی زندگی می‌کنیم که هزینه، سرعت و کارایی برامون مهم هستش و همیشه نمی‌تونیم به جای بهینه‌سازی منابعمون رو افزایش بدیم.مثال‌هایی که زدم لزوماً نمونه‌ای از تجرید سوراخ نبود ولی یه شباهت‌هایی بهش داشت. حرف اصلی‌ای که می‌خواستم بزنم اما چیز دیگری بود. افراد زیادی هستند که با استدلال این که لایه‌های تجرید بالاتری به وجود اومده، حس می‌کنند دونستن لایه‌های پایین بی‌ارزش هستش: چون جانگو خودش ORM داره دیگه لازم نیست SQL بلد باشم یا چون خود nginx می‌تونه به جانگو وصل بشه و از اون طرف می‌تونه جواب مرورگر رو هم بده لازم نیست بدونم http چیه. این استدلال‌ها در ظاهر درست هستند اما ممکنه در ادامه شما رو دچار مشکلات زیادی بکنند. ندونستن لایه زیرین ابزاری که باهاش کار می‌کنید ممکنه باعث بشه دیباگ کردنتون چندین برابر بیشتر طول بکشه و به جای چند دقیقه چند ساعت درگیر حلش باشید.برای یک برنامه‌نویس، بی‌اهمیت دونستن این که سیستم عامل و اینترنت چجوری کار می‌کنه چون که الان لینوکس و گوگل کروم وجود داره، همونقدر احمقانه هستش که بگیم چون ماشین حساب وجود داره دیگه لازم نیست جمع و ضرب یاد بگیریم.پس یه بار دیگه تاکید می‌کنم که این درس‌ها رو توی دانشگاه جدی بگیرید و فکر نکنید چون بلدید وبسایت بزنید، دیگه نیازی به دونستنشون ندارید.مقاله اصلی Joel در مورد تجرید سوراخ یه لینک خوب دیگه در مورد همین موضوع