PDA

View Full Version : گفتگو: گفتگویی با آلکس استپانوف سال 1995



rahnema1
چهارشنبه 29 اردیبهشت 1395, 17:57 عصر
الکس استپانوف Alex Stepanov دانشمند روسی الاصل مقیم آمریکا خالق کتابخانه STL و در عرصه ++C و برنامه نویسی یکی از چهره های مهم به حساب می آید.متن زیر مصاحبه ای است که در سال 1995 توسط مجله drdobbs با وی ترتیب داده شده اگرچه تاریخ مصاحبه قدیمیه و حتی این مجله در سال 2014 تعطیل شده و خود استپانوف هم ژانویه امسال 2016 میلادی از شرکت A9 بازنشسته شده اما هنوز این مصاحبه و مطالب اون تازگی داره هم از جهت نوستالژیک و هم آشنایی با دیدگاههای ایشان (برنامه نویسی عام ، STL ، شیء گرایی و اهمیت زبان ++C/C و ...). سعی کردم مصاحبه را به صورت روان ترجمه کنم امیدوارم بتونم مصاحبه ها یا مطالب بیشتری از ایشان یا افراد مهم دیگه اینجا ارائه بدم. هر کسی هم که مایله اصل گفتگو را مطالعه کنه در اینجا (http://www.drdobbs.com/cpp/standards-stepanov-stroustrup-and-steven/228700420) قرار داره

-سوال:در مورد علاقه طولانی مدتتان به برنامه نویسی عام (generic programming) صحبت بفرمایید.
-جواب:در اواخر دهه ۷۰ میلادی شروع به فکر کردن در مورد برنامه نویسی عام کردم در آن زمان این مطلب را دریافته بودم که بعضی الگوریتم ها به پیاده سازی ساختمان داده بستگی ندارند بلکه به تعدادی خصوصیات مفهومی اساسی آن ساختمان بستگی دارند. شروع کردم به بررسی الگوریتمهای مختلف و فهمیدم که بیشتر الگوریتم ها را می توان بدون وابستگی به پیاده سازی به مرحله ای از انتزاع (abstraction) رساند که کارایی الگوریتم پایین نیاید. کارایی، از دغدغه های اساسی من است. این احمقانه است که یک الگوریتم را به صورتی به انتزاع برسانیم که وقتی آن را از حالت انتزاع به نمونه اصلی برگردانیم کارایی اون از بین برود.
در آن زمان من فکر می کردم راه درست برای انجام این نوع مطالعه این است که یه زبان برنامه نویسی را ایجاد کنیم. در نتیجه با دو نفر از دوستانم به نام Deepak Kapur که در حال حاضر پروفسور در دانشگاه ایالتی نیویورک است و David Musser که پروفسور موسسه پلی تکنیک Rensselaer است این کار را شروع کردیم. در آن زمان هر سه در مرکز تحقیقاتی جنرال الکتریک کار می کردیم. ما شروع به کار روی یک زبان به نام Tecton کردیم که این زبان به افراد اجازه می داد که الگوریتم را به وسیله چیزی به نام ساختمانهای عام (generic structure) بیان کند. این ساختمانهای عام در واقع مجموعه ای از «نوع ها» و خصوصیات آنها بود. در واقع یه سری مطالب به زبان ریاضی. ما دریافتیم که می شود یک جبر را تعریف کنیم که موضوع آن عملیات روی این ساختمانها باشد در نتیجه می شود آنها را اصلاح کرد می شود چیزهایی به آن اضافه کرد و کارهای مختلفی را روی آنها انجام داد.
ایده های جالبی داشتیم اما این تحقیق ما به نتایج عملی منجر نشد زیرا Tecton یک زبان functional بود. ما به ایده های Backus معتقد بودیم که باید از سبک برنامه نویسی وان نیومن رها بشویم و نمی خواستیم که در زبان ما اثرات جانبی (side effect) وجود داشته باشه. که این محدودیتی برای ما ایجاد کرد که نتوانیم با الگوریتمهای زیادی که در آنها مفهوم «حالت» (state) و «اثرات جانبی» وجود داشت کار کنیم.
در خصوص Tecton در اواخر دهه ۷۰ به نکته جالبی پی بردم این نکته این بود که مفهومی که از نوع داده انتزاعی (abstract data type)در آن زمان پذیرفته شده بود دارای یک محدودیت اساسی است. ما معمولا به این صورت در نظر می گیریم که نوع داده انتزاعی به ما درمورد رفتار اشیاء می گوید اما در مورد پیاده سازی صحبتی نمی کند. عموما این گونه پذیرفته شده که پیچیدگی یک عملیات (operation)، بخشی از پیاده سازی است و انتزاع، در مورد پیچیدگی صحبتی نمی کند. یکی از مواردی که از نکات مرکزی برنامه نویسی عام است، این است که پیچیدگی یا حداقل مفهومی کلی از پیچیدگی را باید با یک عملیات مربوط کرد.
یک مثال می زنم. شما stack را به عنوان یک نوع داده انتزاعی در نظر بگیرید. خب اینکه در مورد stack دو عملیات push و pop را در داشته باشیم که مثلا با push یک چیزی وارد stack بشود سپس با استفاده از pop همون چیز را بازیابی کنید این به تنهایی کافی نیست بلکه نکته مهم دیگری که باید توجه بشود این است که عملیات push بدون توجه به اندازه stack باید در یک زمان ثابت انجام بشود. اگر من stack را طوری پیاده سازی کنم که با هر push که انجام می دهم کند تر و کندتر بشود دیگه کسی علاقه ای به استفاده از این stack نخواهد داشت.
درست است که لازمه که پیاده سازی را از رابط (interface) جدا کنیم اما این نباید به قیمت صرفنظر کردن از پیچیدگی باشد. پیچیدگی باید به عنوان بخشی از قرارداد نانوشته بین یک ماژول و کاربر آن باشد. علت معرفی مفهوم نوع داده انتزاعی، امکان پذیر کردن ماژولهای نرم افزاری قابل تعویض بود.در صورتی ماژولها، قابل تعویض خواهند بود که از نظر پیچیدگی رفتار مشابهی داشته باشند.اگر من یک ماژول را با ماژول دیگر جایگزین کنم که از نظر کاری که انجام می دهند یکسان باشند اما هزینه پیچیدگی متفاوتی داشته باشند، کاربر این کد به طرز ناخوشایندی غافلگیر می شود. من هر چه قدر که بخواهم می توانم با او در مورد انتزاع داده ها صحبت کنم اما نهایتا از کد من استفاده نخواهد کرد.بخشی از رابط، باید شامل بیان پیچیدگی باشد.
حدود سال 1983 من بعد از جنرال الکتریک به دانشگاه پلی تکنیک رفتم و شروع به کار در زمینه الگوریتمهای گراف کردم. یاور اصلی من Aaron Kershenbaum بود که الان در IBM هست. او یک متخصص در زمینه الگوریتمهای گراف و شبکه بود و من او را متقاعد کردم بعضی ایده های برنامه نویسی مرتبه بالا (high order programming) و عام، قابل اعمال روی الگوریتم های گراف است. بودجه هایی در دست او بود و از من حمایت کرد تا با او این ایده ها را روی الگوریتمهای شبکه های واقعی اعمال کنیم. او علاقه داشت که یک تولباکس شامل کامپوننتهای مرتبه بالا و عام ایجاد کند تا در آن برخی از این الگوریتمها را بتوان پیاده سازی کرد. چون بعضی الگوریتمهای شبکه آنقدر پیچیده هستند که علیرغم اینکه به صورت نظری تحلیل شده اند اما اصلا پیاده سازی نشده اند. من تصمیم گرفتم از یکی از گونه های زبان LISP به نام Scheme جهت ساخت این تولباکس استفاده کنم. Aaron و من یک کتابخانه بزرگ از کامپوننتها را به زبان Scheme توسعه دادیم که در آن از انواع مختلف تکنیکهای برنامه نویسی بهره برده بودیم. هدف اولیه، الگوریتمهای شبکه بود. بعدا Dave Musser که هنوز در جنرال الکتریک بود به ما پیوست که ما کمپوننتهای بیشتری ایجاد کردیم که یک کتابخانه نسبتا بزرگ شد. آن کتابخانه در دانشگاه توسط دانشجویان تحصیلات تکمیلی مورد استفاده قرار گرفت اما استفاده تجاری از آن نشد. در طول این فعالیت متوجه شدم که «اثرات جانبی» اهمیت دارند چون عملیات روی گراف را نمی توان بدون اثرات جانبی انجام داد. وقتی بخواهیم فقط یک راس گراف را اصلاح کنیم نمیتونیم (نباید) کل گراف را کپی کنیم. نتیجه ای که از این مطلب گرفتم این بود که در ساخت الگوریتمهای عام می شود تکنیکهای مرتبه بالا را با استفاده کنترل شده اثرات جانبی ترکیب کرد. اثرات جانبی لزوما بد نیستند .آنها در صورتی بد هستند که استفاده درستی از آنها نشود.
در تابستان 1985 دوباره به موسسه تحقیقاتی جنرال الکتریک دعوت شدم تا برنامه نویسی مرتبه بالا را تدریس کنم. که در آنجا نحوه ایجاد الگوریتمهای پیچیده را با استفاده از این تکنیک ارائه می دادم. یکی از افرادی که در آنجا حضور داشت Art Chen مدیر Information Systems Laboratory بود. به حدی تحت تاثیر قرار گرفته بود که از من خواست که آیا می توانم کتابخانه ای جهت کارهای صنعتی را با استفاده از این تکنیکها با زبان Ada بنویسم که البته با تامین و پشتیبانی وی همراه خواهد بود. به علت اینکه یک استادیار بی بضاعت بودم پیشنهاد را قبول کردم در حالیکه در آن زمان اصلا هیچ چیز در مورد زبان Ada بلد نبودم. در ساخت کتابخانه Ada با Dave Musser همکار شدم. پروژه مهمی بود چون با تغییر مسیر از یک زبان با نوع پویا مثل Scheme به یک زبان با نوع ایستا مثل Ada باعث شد اهمیت سیستم نوع قوی (strong typing) را متوجه بشوم. هر کسی می داند سیستم نوع قوی کمک به یافتن خطاها می کند. من فهمیدم که سیستم نوع قوی در برنامه نویسی عام در زبان Ada وسیله ای جهت طراحی هست. این خصوصیت نه تنها وسیله ای جهت گرفتن باگها بلکه وسیله ای جهت فکر کردن بود. این مساله منجر به ایده تجزیه متعامد فضای کامپوننت شد. من دریافتم که کامپوننتهای نرم افزاری به گروههای مختلفی تعلق دارند. هنرمندان عرصه برنامه نویسی شیء گرا فکر می کنند هر چیزی Object است. هنگامی که روی کتابخانه عام Ada کار می کردم فهمیدم که این گونه نیست. چیزهایی هستند که Object هستند در واقع چیزهایی که حالت دارند و حالت آنها تغییر می کند Object هستند. همچنین چیزهایی هستند که Object نیستند. یک جستجوی دودویی Object نیست. در واقع یک الگوریتم است. علاوه بر این در آن زمان دریافتم که با تجزیه فضای کامپوننت به چندین بعد متعامد ما می توانیم تعداد کامپوننتها را کم کنیم و مهم تر از آن ما می توانیم یک چارچوب مفهومی را برای نحوه طراحی فراهم کنیم.
سپس جهت کار در گروهی که روی کتابخانه های ++c کار می کرد به من شغلی پیشنهاد شد. از من سوال کردند که آیا می توانم (ایده هایم) را در ++c پیاده کنم. خب من ++C را بلد نبودم ولی به آنها جواب مثبت دادم. اما من ایده هایم را نتوانستم در ++C پیاده کنم چون در سال ۱۹۸۷ هنوز template در ++C وجود نداشت که برای این سبک برنامه نویسی لازم است. تنها سازوکار جهت رسیدن به عامیت، وراثت بود که ناکافی بود.
حتی اکنون هم وراثت در ++C کاربرد چندانی جهت برنامه نویسی عام ندارد. بگذارید توضیح بدهم. خیلی ها تلاش کرده اند تا از وراثت جهت پیاده سازی ساختمان های داده و کلاسهای محتوی (container class) استفاده ببرند. اما اکنون می دانیم این تلاشها موفقیت آمیز نبوده. وراثت در ++C و سبک برنامه نویسی مرتبط با آن به شدت محدود هست. امکان ندارد که یک طراحی ـ که مثلا شامل یک عملگر ساده مثل تساوی باشد ـ را پیاده سازی کرد که بتوانیم درست ازش استفاده کنیم. مثلا در راس سلسله مراتب کلاس شما کلاس پایه ای به نام X باشد و یک عملگر تساوی مجازی (virtual) برای کلاس X تعریف کنید که آرگومانی از نوع X بگیرد، سپس کلاسی به نام Y را از کلاس X مشتق کنید. نتیجه تساوی چه می شود؟ در این تساوی Y با X مقایسه می شود!
به عنوان یک مثال دیگه از حیوانات استفاده می کنیم (طرفداران شیء گرایی به حیوانات علاقه دارند.) کلاس پستانداران را تعریف کنید و کلاس زرافه را از آن مشتق کنید. یک تابع عضو به نام جفتگیری برای پستاندار تعریف کنید که پستاندار با پستاندار جفتگیری می کند و یک پستاندار را بر می گرداند. وقتی زرافه از پستاندار مشتق می شود دارای تابعی به نام جفت گیری می شود که در آن زرافه با پستاندار جفت گیری می کند و یک پستاندار را بر می گرداند. و قطعا این چیزی نیست که شما می خواهید. خب جفت گیری اهمیت چندانی برای برنامه نویسان ندارد اما «تساوی» اهمیت دارد. من حتی یک الگوریتم را ندیدم که نوعی از تساوی در آن استفاده نشده باشد.
برای چنین مسائلی نیاز به template می باشد. اینجا شما یک کلاس template برای پستانداران دارید که یک تابع عضو به نام جفت گیری دارد که پستاندار را می گیرد و پستاندار را بر می گرداند. وقتی این template را با زرافه نمونه سازی کنید تابع جفت گیری آن گونه که باید باشد می شود. بنابراین template از این نظر سازوکار قدرتمندتری هست.
در هر صورت من قادر بودم که کتابخانه ای بزرگ از الگوریتم ها را ایجاد کنم که بعدا بخشی از کتابخانه Unix System Laboratory Standard Component شد. من در آزمایشگاههای Bell در صحبت با افرادی نظیر Andy Koenig و Bjarne Stroustrup در مورد برنامه نویسی چیزهای زیادی یاد گرفتم. و متوجه شدم که ++C/C یک زبان برنامه نویسی مهم با چارچوبهایی اساسی است که نمی شود آنها را نادیده گرفت. مشخصا یادگرفتم که اشاره گر ها خیلی خوب هستند. البته منظورم اشاره گرهای معلق (dangling pointer) نیست. منظورم اشاره گر به stack نیست. اما منظورم این است که مفهوم کلی اشاره گر یک ابزار قدرتمند می باشد. که مفهوم آدرس به صورت فراگیر استفاده می شود. به صورت غلط تصور می شود که اشاره گر ها تفکر ما را به صورت متوالی (sequential) در می آورد. نه این طور نیست. بدون استفاده از مغهوم اشاره گر نمی توانیم بعضی الگوریتم های موازی را بیان کنیم. مثلا اگر بخواهیم مجموع n عدد را به صورت موازی بیان کنیم، ما نمی توانیم این کار را انجام بدهیم مگر اینکه بگوییم که اولین عدد با دومین عدد جمع می شود و سومین عدد با چهارمین عدد جمع می شود. یعنی به نوعی اندیس گذاری نیاز داریم. به نوعی از آدرس نیاز داریم تا هر الگوریتم را بیان کنیم، چه متوالی چه موازی. مفهوم آدرس یا موقعیت مفهومی اساسی در شکل دادن فرایندهای محاسباتی (الگوریتم ها) هست.
اکنون بگذارید به این بپردازیم که چرا C زبان بزرگی است. معمولا تصور می شود که C که یک ترفند (hack) هست، به این علت موفق بوده که Unix را با آن نوشتند.من موافق با این نظر نیستم. در مدت زمانی طولانی معماری کامپوتر متحول شده، نه به این علت که افرادی باهوش در فکر این بوده اند که چگونه معماری ها را متحول کنند ـ البته در این مدت افراد باهوش، معماریهای برچسب دار (tagged) را معرفی کردندـ بلکه به علت نیاز برنامه نویسان مختلف جهت حل مسائل واقعی بوده است. کامپیوترهایی که فقط قادر بودند با اعداد کار کنند به کامپیوترهایی با حافظه قابل آدرس دهی با بایت ،قابل آدرس دهی با فضای آدرس تخت و قابل آدرس دهی با اشاره گر تبدیل شدند. این تحولی طبیعی بود که بازتاب مسائل در حال رشدی بود که افراد می خواستند حل کنند. C که هوش Dennis Ritchie را نشان می دهد یک مدل حداقلی را از کامپیوتری که در طی ۳۰ سال متحول شده بود ارائه کرد. C یک ترفند یک شبه نبوده. همان طور که کامپیوترها جهت حل مسائل مختلف متحول شدند و C هم مدل حداقلی این گونه کامپیوتر شد و در نتیجه تبدیل به یک زبان بسیار قدرتمند جهت حل مسائل مختلف در حوزه های مختلف و در عین حال با کارایی بسیار بالا شد. ضمن اینکه مدل ماشین پشت زبان C را می شود فهمید. یعنی برای یک مهندس با سطح متوسط، فهم مدل ماشین C راحت تر از فهمیدن مدل ماشین Ada یا حتی Scheme است. C موفق شد چونکه کار درست را انجام می داد نه به خاطر اینکه AT&T آن را ترویج می کرد یا اینکه Unix را با آن نوشته اند.
زبان ++C موفق بوده چون Bjarne به جای درگیر شدن عمیق در ابداع یک مدل ماشین جدید، با C شروع کرد و سعی کرد با وارد کرد تکنیکهای برنامه نویسی کلی تر اما در چارچوب این مدل ماشین، زبان C را تکامل بیشتری بدهد. مدل ماشین C بسیار ساده است. ما حافظه را داریم که در آن چیزهای مختلف قرار می گیرند. ما اشاره گر به عناصر متوالی حافظه داریم. که به راحتی قابل فهم است. ++C این مدل را می گیرد اماچیزهایی که در حافظه قرار می گیرند را گسترده تر از ماشین C می کند، زیرا C تعداد محدودی نوع داده دارد. البته ساختارها (structure) در C وجود دارند که سیستم نوع قابل توسعه ای را امکان پذیر می کند اما در این سیستم امکان تعریف عملیات برای ساختار وجود ندارد که باعث محدودیت در توسعه پذیری سیستم نوع می شود. ++C مدل ماشین C را به سمت یک سیستم نوع «حقیقتا» قابل توسعه برد.
در سال 1988 به آزمایشگاههای HP رفتم که در آنجا جهت کار بر روی کتابخانه های عام به کار گرفته شدم. اما برای چندین سال به جای کار بر روی کتابخانه، روی درایور دیسک کار می کردم که هیجان انگیز بود اما در تضاد با آن موضوع تحقیقاتی بود. در سال 1992، Bill Worley که رئیس آزمایشگاه من بود یک پروژه الگوریتم ترتیب داد که من مدیر آن شدم در نتیجه دوباره برگشتم سراغ توسعه کتابخانه عام. در آن زمان template در ++C وجود داشت. دیدم که Bjarne با طراحی template کار حیرت آوری انجام داده. من قبلا در آزمایشگاه Bell در بحثهای اولیه در خصوص طراحی template مشارکت کرده بودم و با جزمیت به Bjarne گفته بودم که او باید template های ++C را تا جایی که امکان دارد مشابه بخشهای عام زبان Ada ایجاد کند. فکر می کنم آنگونه با جزمیت با Bjarne بحث کردم که او تصمیمی مخالف آن گرفت. من برخلاف بعضی که فقط بر اهمیت ایجاد template های کلاس باور داشتند به ایجاد template های تابع هم فکر می کردم. اما در عین حال فکر می کردم تابعهای template باید شبیه بخشهای عام Ada کار کنند یعنی به طور صریح باید نمونه سازی (instantiation) شوند. Bjarne به حرف من گوش نداد و سازوکاری برای تابع template طراحی کرد که تابع template به صورت ضمنی با استفاده از سازوکار سربارگذاری، نمونه سازی می شد. این تکنیک خاص برای کار من نقش حیاتی پیدا کرد چون فهمیدم که این امکان را به من می دهد که بسیاری کارها را که در Ada امکان پذیر نبود انجام بدهم. بنابراین من این طراحی خاص که Bjarne انجام داد را به عنوان کاری حیرت آور می دانم و خیلی خوشحالم که توصیه من را گوش نکرد.

rahnema1
چهارشنبه 29 اردیبهشت 1395, 17:57 عصر
-سوال:ذهنیات اولیه شما در مورد STL چه بود و اهداف اصلی آن چه بود؟
-جواب:در سال 1992 وقتی که پروژه شکل گرفت هشت نفر در آن بودند. کم کم گروه تحلیل رفت و نهایتا دو نفر باقی ماندند، من و خانم Meng Lee. با اینکه Meng نسبت به این حوزه تازه کار بود ـ او قبلا در بیشتر فعالیتهای حرفه ایش روی کامپایلرها کار کرده بودـ در عین حال ایده کلی برنامه نویسی عام را پذیرفته بود و معتقد بود که این روش می تواند توسعه نرم افزار را متغیر کند در حالیکه تعداد کمی به این عقیده باور داشتند. فکر کنم بدون کمک او نمی توانستم STL را ایجاد کنم. (یعنی واژه های کلمه STL از دو بخش STepanov و Lee تشکیل شده ...!). ما کتابخانه بزرگی نوشتیم که شامل مقدار زیاد کد با مقدار زیاد ساختمان داده و الگوریتم و اشیاء تابع و اداپتورها و ... بود. کد زیادی ایجاد شد اما مستندات نداشت. کار ما به عنوان یک پروژه تحقیقاتی دیده شد که هدف آن نشان دادن این بود که می توان الگوریتمها را تا جای ممکن به صورت عام ایجاد کرد و در عین حال بسیار کارا باشند. زمان زیادی را صرف اندازه گیری کردیم و به این نکته رسیدیم که می توانیم این الگوریتم ها را تا جای ممکن به صورت عام در بیاوریم و در عین حال مثل کد دست نویس کارایی داشته باشد. در سرعت و کارایی این سبک برنامه نویسی مشکلی وجود ندارد. کتابخانه در حال رشد بود اما معلوم نبود که آیا به صورت یک پروژه در می آید یا نه. چند اتفاق مبارک رخ داد تا کتابخانه به STL منجر شد.
چه وقت و چرا شما تصمیم گرفتید STL را به عنوان بخشی از استاندارد ANSI/ISO زبان ++C پیشنهاد بدهید؟
در تابستان 1993، Andy Koenig به استانفورد آمد تا یک درس ++C را ارائه کند. من بخشی از کارمان را به او نشان دادم. و فکر کنم به طرز هوشمندانه ای از آن کار شگفت زده شد. او از من دعوت کرد که در جلسه ماه نوامبر کمیته استانداردسازی ANSI/ISO زبان ++C که در سان خوزه تشکیل می شد سخنرانی کنم. عنوان سخنرانی من «علم برنامه نویسی ++C» بود. سخنرانی تقریبا مباحث تئوری بود. خلاصه اش این بود که قانونهای اساسی وجود دارند که عملیات اصلی روی عناصر ++C را به هم مرتبط می کنند که لازم است از این قوانین تبعیت شود. من مجموعه ای از این قوانین را معرفی کردم که کارشان مرتبط کردن عملیات های اصلی مثل سازنده ها، انتساب و تساوی بود. زبان ++C هیچ محدودیتی را اعمال نمی کند. مثلا شما می توانید یک عملگر تساوی تعریف کنید که عمل ضرب را انجام دهد. ولی درستش این است که تساوی باید تساوی باشد و همچنین باید یک عملیات انعکاسی باشد. A باید مساوی با A باشد. باید تقارن داشته باشد یعنی اگر A مساوی B بود، پس B هم باید مساوی A باشد.و نیز باید متعدی باشد. در واقع اصول موضوعه ریاضی. عملیات تساوی، برای عملیات های دیگر هم اساس و پایه است. اصول موضوعه ای برای مرتبط کردن سازنده و تساوی وجود دارد. اگر ما شیئی را با استفاده از سازنده کپی از روی یک شیء دیگر بسازیم، دو شیء باید مساوی باشند.در ++C این قانون اجباری نیست. اما این از قانونهای اساسی است که باید از آن پیروی کنیم. تساوی باید شیء های مساوی ایجاد کند...
به این ترتیب من تعدادی اصول موضوعه را نشان دادم که بین این عملیات ها پیوند برقرار می کرد. کمی هم در مورد اصول موضوعه تکرارگرها (iterator) صحبت کردم و چند الگوریتم عام را که روی تکرارگرها کار می کرد نشان دادم. یک سخنرانی دوساعته و نسبتا خشک بود. که البته استقبال خیلی خوبی از آن شد. در آن موقع فکر نمی کردم که از این به عنوان بخشی از استاندارد استفاده بشود چون عموما این جور فکر می شد که این یک تکنیک پیشرفته برنامه نویسی است که نباید در «جهان واقعی» مورد استفاده قرار بگیرد. فکر می کردم برنامه نویسهای کاربردی، اصلا علاقه ای به این کار ندارند.
سخنرانی در ماه نوامبر انجام شد و اصلا به ANSI فکر نمی کردم تا ژانویه رسید. در ۶ ژانویه ایمیلی از طرف Andy Koenig ـ که ویرایشگر مستندات پروژه استاندارد بود ـ دریافت کردم که گفته بود اگر من می خواهم که کتابخانه ام به عنوان بخشی از استاندارد بشود باید یک پروپوزال تا ۲۵ ژانویه تهیه کنم و بفرستم. من جواب دادم Andy ، تو احمقی؟ که جواب داد: بله من احمقم، ولی نمی خواهی امتحانش کنی؟
در آن زمان کدها زیاد بود اما مستندات نداشتیم. یعنی مستندات برای یک پروپوزال رسمی خیلی کم بود. Meng و من ۸۰ ساعت در هفته کار کردیم تا توانستیم در زمانی که در ایمیل مشخص شده بود پروپوزال را آماده کنیم. در این مدت تنها کسی که می دانست آماده می شود Andy بود. او تنها حامی ما بود و در این مدت کمکهای زیادی کرد. پروپوزال را فرستادیم و منتظر ماندیم. هنگام تهیه پروپوزال چیزهای مختلفی تعریف کردیم. وقتی که چیزی را می نویسید مخصوصا اگر به عنوان پروپوزال به استاندارد معرفی می کنید انواع و اقسام اشتباهات در طراحیتان را کشف می کنید. ما مجبور شدیم از موقع ایمیل ژانویه تا جلسه بعدی که در ماه مارس در سان دیه گو انجام می شد جزء به جزء کدهای کتابخانه را دوباره پیاده سازی کنیم. بعد باید پروپوزال را بازبینی می کردیم چون هنگام نوشتن کد اشتباهات بسیاری را پیدا کردیم.
-سوال:لطفا مباحثات و مناظرات بعد از ارائه پروپوزال به کمیته را شرح دهید. حمایتها و مخالفتها را بیان کنید.
-جواب:ما فکر می کردیم نتیجه ای از آن بیرون نیاید. من سخنانم را انجام دادم که به خوبی استقبال شد. انتقاداتی بود که بیشتر آنها به این شکل بود: این پرورپوزال خیلی زیاد است، خیلی دیر است، در جلسه قبل قرار شد پروپوزال های عمده پذیرفته نشوند، چیز خیلی پر حجمی است، بزرگترین پروپوزالی که تابه حال آمده، مقدار زیادی مطالب کاملا جدید ... . رأی گیری انجام شد و در کمال تعجب اکثریت قریب به اتفاق رای دادند که پروپوزال در جلسه بعدی بررسی شود و در جلسه بعدی که در واترلو کانادا برگزار می شود رای گیری انجام شود.
و Bjarne Stroustrup تبدیل به یک حامی قدرتمند STL شد. افراد زیادی با پیشنهادها، اصلاحات و بازبینی های خودشان کمک کردند. Bjarne به مدت یک هفته به اینجا آمد که با ما کار کند. Andy به طور ثابت کمک می کرد. ++C زبان پیچیده ای است و همیشه معلوم نیست که مثلا فلان ساختار چه معنی می دهد. تقریبا هر روز من با Andy و Bjarne صحبت می کردم و می پرسیدم که فلان کار یا کار دیگه در ++C قابل انجام هست یانه. تشکر ویژه از Andy می کنم. او بود که فکر کرد که STL را می توان به عنوان بخشی از استاندارد قرار داد. Bjarne مهم ترین شخصی بود که STL را در کمیته جا انداخت. افراد دیگری هم بودند که کمک کردند: Mike Vilot رییس گروه کتابخانه استاندارد،Nathan Myers از Rogue Wave و Larry Podmolik از مهندسین مشاور Andersen. افراد زیادی بودند... .
کتابخانه STL که ما در سان دیه گو ارائه دادیم با نگارش رایج آن زمان ++C ایجاد شده بود. از ما خواسته شد که کتابخانه را با قابلیتهای استاندارد جدید ANSI/ISO که بعضی از این قابلیتها هنوز پیاده سازی نشده بود بازنویسی کنیم. وقت زیادی از Bjarne و Andy گرفته شد که تایید کنند که ما این قابلیتهایی که هنوز در زبان پیاده سازی نشده اند را به درستی در نوشتن کتابخانه استفاده کردیم.
این درخواست بود که محتوی ها (containers) مستقل از مدل حافظه (memory model) باشند که البته خواسته سنگینی بود چون در آن موقع، زبان ++C مدل حافظه نداشت. یعنی این درخواست وجود داشت که سازوکاری جهت انتزاع مدلهای حافظه ارائه شود.[علتش این بود که] نسخه های اولیه STL فرض گرفته بود که اندازه یک محتوی را می شود به صورت یک عدد صحیح از نوع size_t بیان کرد و نیز می توان فاصله بین دو تکرارگر را با عدد صحیح از نوع ptrdiff_t بیان نمود. درنتیجه به ما گفته می شد چرا یک حالت انتزاعی از اینها ایجاد نمی کنید؟ این خواسته در واقع یک کار شاق بود چون خود زبان ++C هم یک حالت انتزاعی نسبت به آن در خود نداشت، یعنی آرایه های C و ++C را با این دو نوع نمی شود توصیف کرد. [که اینها باعث شد] سازوکاری به نام «تخصیص دهنده» (allocator) ابداع کردیم که اطلاعات مربوط به مدل حافظه را در خود کپسوله می کرد. که پیامدها و تاثیرهای برجسته ای بر هر جزء کتابخانه داشت. ممکن است این سوال را بپرسید که چه رابطه ای بین مدل حافظه از یک طرف و الگوریتمها و رابط محتوی ها از طرف دیگر ممکن است وجود داشته باشد. خب اگر ما نتوانیم [به علت وجود مدلهای مختلف حافظه]از مثلا size_t استفاده کنیم در واقع نمی توانیم از مثلا *T استفاده کنیم که این به خاطر وجود انواع مختلف اشاره گر مثل *T و * T huge و ... است. در نتیجه نمی توانیم از ارجاع (reference) استفاده کنیم زیرا به علت مدلهای مختلف حافظه انواع مختلف ارجاع را هم خواهیم داشت. اینها تاثیرات مهمی بر کتابخانه گذاشت.
مساله مهم دیگر این بود که ساختمانهای داده پیوندی (associative) را به ساختمانهای داده های موجود در کتابخانه اضافه کنیم. که ساده به نظر می رسید اما اینکه جزئی از استاندارد باشد مساله را سخت می کرد چون باید چیزی طراحی می شد که کاربران برای سالها به عنوان ساختمان محتوی از آن استفاده کنند. STL از نظر ساختمانهای محتوی یک دوگانه را تشکیل می دهد. دو نوع کلاس محتوی داریم: توالی ها (sequences) و محتوی های پیوندی (associative containers). که در واقع به ترتیب متناظر هستند با حافظه معمولی و حافظه قابل آدرس دهی با محتوا (content-addressable). کتابخانه STL پشتوانه مفهومی دارد که نحوه عمل این محتوی ها را توضیح می دهد.
وقتی من به واترلو رسیدم، Bjarne زمان زیادی به من توضیح می داد که نباید نگران باشم. ممکن است با شکست مواجه بشویم اما به بهترین نحو کار را انجام دادیم ما سعی خودمان را کردیم و باید شجاع باشیم. سطح انتظار، پایین بود. انتظار داشتیم که اکثریت مخالف باشند. بعضی مخالفت ها وجود داشت که البته در اقلیت قرار داشتند. وقتی در واترلو رای گیری شد کاملا غافلگیرانه بود چون ۸۰ در صد موافق و ۲۰ درصد مخالف بودند. همه انتظار یک نبرد و جنجال را می کشیدند. نبردی وجود داشت اما رای اکثریت بر این قرار گرفت.
-سوال:تاثیر STL بر کتابخانه ای که تحت پیش نویس فوریه ۱۹۹۴ ANSI/ISO منتشر شد چه بود؟
-جواب:کتابخانه STL در واترلو در پیش نویس جای داده شد. مستندات STL به چند بخش تقسیم شد و هر کدام در قسمتهای مختلف فصل کتابخانه پیش نویس جای گرفتند. Mile Vilot مسوول این کار بود. من در کارهای ویرایش، شرکت فعالانه نداشتم. من عضو کمیته نبودم اما هر وقت تغییری برای STL پیشنهاد داده می شد، توسط من انجام می گرفت. کمیته کاملا ملاحظه می کرد.
-سوال:تغییرات متعددی بر روی template ها توسط کمیته پذیرفته شده. کدام یک بر روی STL تاثیر داشته؟
-جواب:قبل از پذیرش STL دو تغییر وجود داشت که توسط STL بازبینی شده مورد استفاده قرار گرفت. یکی قابلیت داشتن تابع عضو template بود. این به طور گسترده در STL استفاده شد که موجب می شد هر نوع محتوی را از هر نوع محتوی دیگر بسازیم. یک سازنده داریم که توسط آن می توانیم از روی list یا محتوی های دیگر یک vector بسازیم. سازنده به صورت template داریم که پارامتر template آن یک تکرارگر است که اگر شما دو تکرارگر را به سازنده محتوی معرفی کنید موجب می شود که محتوی، از روی عناصری که در محدوده این دو تکرارگر قرار دارد ساخته شود. یک محدوده، شامل عناصری است که می توان با دو تکرارگر یا دو اشاره گر تعمیم یافته یا دو آدرس مشخص کرد. قابلیت جدید دوم که در STL استفاده شد پارامترهای template بودند که خودشان هم template هستند. که تخصیص دهنده هایی که پیشنهاد دادیم توسط این قابلیت پیاده سازی شدند.
-سوال:آیا ملزومات STL باعث شد که در template تغییراتی صورت بگیرد؟
-جواب:در Valley Forge، پیشنهادی توسط Bjarne مبنی بر اضافه کردن تخصصی کردن جزئی (partial specialization) ارائه شد که باعث می شد بسیاری از الگوریتم ها و کلاسها کارایی بالاتری پیدا کنند و مساله اندازه کد را هم حل می کرد. من با Bjarne روی پروپوزال کار کردم و این مساله به خاطر نیاز به بالاتر بردن کارایی STL انجام شد. کمی در مورد تخصصی کردن جزئی توضیح می دهم. در حال حاضر [قبل از تخصصی کردن جزئی] می توانیم یک تابع template داشته باشیم که مثلا پارامتر آن کلاس T باشد به این صورت
swap(T&, T&)
که کارش جابجا کردن دو پارامتر هست. این عام ترین روش swap هست. اگر بخواهیم swap را تخصصی تر کنیم و مثلا برای یک نوع خاص، عملیات معینی انجام شود، مثلا می توانیم تابع زیر را داشته باشیم
swap(int&, int&)
که مثلا دو عدد صحیح را با یک روش متفاوت جابجا می کند. اما قبلا این که یک حالت بینابین برای تخصصی کردن جزئی داشته بشیم میسر نبود. مثلانمی شد یک تابع template به صورت زیر داشته باشیم:
template <class T> void swap(vector<T>&, vector<T>&);
که روشی خاص برای جابجا نمودن vector ها می باشد که از لحاظ کارایی اهمیت خاصی دارد. اگر دو vector را با عام ترین روش swap جابجا کنیم ـ که ۳ عملیات انتساب را در بر می گیردـ موجب می شود vector ها سه مرتبه کپی شوند که زمان مصرف شده رابطه خطی دارد. اما اگر این حالت تخصصی کردن swap را برای vector ها داشته باشیم یک عملیات با زمان ثابت خواهیم داشت که موجب می شود اشاره گر های موجود در سرایند vector جابجا شوند. با این کار عملیات sort را می توان بر روی vector ی از vector ها با سرعت خیلی بالاتر انجام داد. با STL فعلی ـ بدون تخصصی کردن جزئی ـ تنها روش برای سریع کردن این است که برای هر نوع خاص از vector مثل < vector<int یک swap اختصاصی تعریف شود که قابل انجام است اما بار زیادی بر دوش برنامه نویس می افتد [حجم کدی که برنامه نویس می نویسد زیاد می شود]. موارد بسیار زیادی هست که تخصصی کردن جزئی باعث سریعتر شدن الگوریتمها در کار با کلاسهای عام می شود. می توانیم یک swap کاملا عام، یک swap کمتر عام، و یک swap باز هم کمتر عام و یک swap کاملا اختصاصی داشته باشیم. اگر از تخصصی کردن جزئی استفاده کنیم کامپایلر بهترین گزینه را از بین اینها انتخاب می کند. مثال دیگر copy است. هم اکنون الگوریتم copy یک توالی از عناصر که توسط تکرارگرها مشخص شده را پیمایش می کند و یک به یک آنها را کپی می کند. اما با تخصصی کردن جزئی می توانیم یک تابع template تعریف کنیم به شکل زیر:
template <class T> T ** copy(T**,T**,T**);
در اینجا محدوده ای از اشاره گر ها توسط memcpy با کارایی بالا کپی می شود. چون ما داریم اشاره گر ها را کپی می کنیم لازم نیست نگران ساخته شدن و تخریب اشیاء باشیم فقط کافیه که بیتها را با memcpy کپی کنیم. فقط یک بار کپی انجام می شود و در تمام کتابخانه به همین نحو است و کاربر هیچ نگرانی نخواهد داشت. ما می توانیم الگوریتم ها را برای بعضی نوع ها تخصصی کنیم . خب این تغییر بسیار مهمی بود و تا جایی که می دانم خوشبختانه در Valley Forge هم از آن استقبال شده و بخشی از استاندارد خواهد شد.
-سوال:چه نوع برنامه هایی غیر از کتابخانه استاندارد به بهترین نحو می توانند از STL بهره ببرند؟
-جواب:من امیدوارم که STL سبکی از برنامه نویسی به نام برنامه نویسی عام را معرفی کند. بر این باورم که این سبک برای انواع برنامه ها ، کاربرد دارد که همان نوشتن الگوریتم و ساختمان داده ها با عام ترین روش می باشد. هر آنچه که بشود با جستجوی دودویی آن را جستجو کرد را می توان با الگوریتم ها عام جستجو کرد. حد اقل نیازمندی هایی که این الگوریتم بر پایه آن است عبارتند از نیازمندیهایی که مورد استفاده کد است. امیدوارم همین مساله برای تمام کامپوننت های نرم افزاری اتفاق بیفتد. که در این صورت ما کاتالوگ های استاندارد را خواهیم داشت که کاربران نیازی به نوشتن اینها نخواهند داشت.
این در واقع همان رویای Doug McIlroy می باشد که طی یک مقاله معروف که در سال 1969 در خصوص کارخانه کامپوننت ها منتشر کرد. STL مثالی از تکنولوژی برنامه نویسی است که چنین کارخانه های کامپوننت را ممکن می کند. البته تلاش زیادی لازم است ـ نه فقط تلاس تحقیقاتی ـ بلکه تلاش صنعتی که برای برنامه نویسان چنین کاتالوگی فراهم شود که به عنوان وسیله ای باشد که بشود کامپوننت های لازم را با آن پیدا کرد و کامپوننتها را به هم چسباند و برآورده شدن مفروضات پیچیدگی آنها را تایید نمود.
-سوال:کتابخانه STL مدلهای محتوی های مانا را پیاده سازی نکرده است. محتوی هایی مثل map و multimap را به طور مشخص می توان به عنوان محتوی با حافظه مانا معرفی نمود به طوری که به صورت اندیسهای معکوس به اشیاء مانای موجود در پایگاه داده استفاده شوند. آیا شما در این جهت کاری انجام داده اید یا اینکه چنین چیزی پیاده سازی شده؟
-جواب:افراد مختلفی به این نکته اشاره کرده اند. STL به یک دلیل روشن، مانایی را پیاده سازی نکرده. STL در آن زمان تا حد ممکن بزرگ بود. فکر نکنم کامپوننتی از این بزرگتر توسط کمیته استاندارد تصویب شده باشد. اما مانایی چیزی است که تعدادی در مورد آن فکر کرده اند. هنگام طراحی STL و مخصوصا هنگام طراحی کامپوننت تخصیص گر، Bjarne دید که تخصیص گر ها را ـ که مدلهای حافظه را کپسوله می کنند ـ می توان جهت کپسوله کردن یک مدل حافظه مانا مورد استفاده قرار داد. این دریافت Bjarne مهم و جالب بود. چندین شرکت پایگاه داده شیء گرا به این مساله توجه دارند. در اکتبر 1994 در جلسه ای که Object Database Management Group ترتیب داده بود شرکت کردم. در خصوص STL سخنرانی کردم و علاقه زیادی وجود داشت که محتوی های موجود در رابط کتابخانه خود را مطابق STL کنند. اما توجه چندانی به تخصیص گر ها نمی شد. البته بعضی اعضای Group در پی این بودند که آیا می توان از تخصیص گر ها جهت پیاده سازی مانایی استفاده کرد. من انتظار دارم ذخیره مانای اشیاء با سبک و در چارچوب STL را طی یک سال آینده پیاده سازی کنند.
-سوال:آیا سازندگان کامپایلر جهت پیاده سازی STL در تولیداتشان با شما کار کرده اند؟
-جواب:بله. تماسهای زیادی از سازندگان کامپایلر با من برقرار شده. Pete Becker از شرکت Borland بی نهایت کمک کرد. او کد هایی نوشت که با آن می توانستیم تخصیص گر ها را برای انواع مدلهای حافظه کامپایلرهای Borland پیاده سازی کنیم. شرکت Symantec تصمیم دارد برای کامپایلر مکینتاش خودش STL را پیاده سازی کند. Edison Design Group کمک زیادی کرد. ما حمایتهای زیادی از بیشتر سازندگان کامپایلر داشتیم.
-سوال:کتابخانه STL شامل template هایی می شود که از مدل حافظه کامپایلرهای MS-DOS که 16 بیتی است پشتیبانی می کند. با تاکیدی که هم اکنون روی ۳۲ بیتی می شود ـ کامپایلرها و سیستم عامل های مدل مسطح ـ آیا فکر می کنید که این رویکرد مدل حافظه معتبر باقی خواهد ماند؟
-جواب:خارج از معماری اینتل، مدل حافظه یک شیء است که اطلاعاتی درخصوص اینکه یک اشاره گر چیست، اندازه عددصحیح ونوع های مختلف مرتبط با این اشاره گر، نوع ارجاعی مرتبط با این اشاره گر و ... در خود جای می دهد. انتزاعی کردن آن از این جهت اهمیت دارد که ما بخواهیم انواع دیگر حافظه مثل حافظه مانا، حافظه اشتراکی و غیره را معرفی کنیم. یک خصوصیت زیبای STL این است که تنها جایی که در آن کد های مربوط به نوع های مختص به ماشین آمده ـ مثلا اشاره گر ها و ارجاع های واقعی ـ در حدود تنها 16 خط کد نوشته شده. هر چیز دیگر مثل محتوی ها و الگوریتم ها به صورت انتزاعی ایجاد شده اند بدون اینکه چیزی در خصوص ماشین در آنها ذکر شده باشد. از جهت قابل حمل بودن، تمام چیزهای مربوط به ماشین که شامل آدرس یا اشاره گر و مانند اینها می شود درون یک سازوکار کاملا قابل فهم کوچک جای داده شده اند. در عین حال، تخصیص گر ها در STL به اندازه تجزیه ساختمان داده ها و الگوریتم های اساسی اهمیت ندارند.
-سوال:کمیته استاندارد ANSI/ISO زبان C موارد مختص به سکو مثل مدل حافظه را به عنوان جزئیات پیاده سازی به حساب آورده و تلاشی در جهت کد کردن آنها نداشته. آیا کمیته ++C دیدگاه متفاوتی دارد و اگر بله چرا؟
-جواب:فکر کنم از نظر مدلهای حافظه، STL از استاندارد ++C جلوتر است. اما تفاوت مهمی بین C و ++C وجود دارد. ++C سازنده و و عملگر new را دارد که با مدل حافظه سر و کار دارند و جزئی از زبان هستند. اکنون این مساله اهمیت دارد که چیزهایی مثل عملگر new را به گونه ای تعمیم بدهیم که همان گونه که محتوی های STL ، تخصیص گر ها را به صورت پارامتر دریافت می کنند ، اینها هم تخصیص گر ها را دریافت کنند. البته این مساله نسبت به زمان قبل از تایید STL اهمیت کمتری دارد زیرا ساختمانهای داده STL عمدتا نیاز به عملگر new را برطرف کرده اند. در اکثر موارد نباید آرایه ها را تخصیص دهی حافظه کنیم چون STL این کار را به طرز کاملا موثر انجام می دهد. من نیازی به استفاده از new در کدهای خودم ندارم و توجه زیادی به کارایی دارم. این کدی که نوشتم نسبت به زمانی که از new استفاده کنم کارایی بیشتری نشان می دهد. با مقبولیت یافتن STL عملگر new هم به نوعی کنار می رود. همچنین STL مساله delete کردن را هم حل کرده است چون مثلا یک vector را در نظر بگیرید هنگامی که از یک بلاک خارج می شویم، مخرب آن باعث تخریب آن می شود. و نیازی نیست مثل موقعی که از new استفاده می کردیم نگران آزاد کردن حافظه باشیم. STL نیاز به جمع آوری زباله (garbage collection) را می تواند کاملا به حداقل برساند. استفاده صحیح از محتوی ها ما را قادر می کند آنچه که بخواهیم را بدون نیاز به مدیریت اتوماتیک حافظه انجام دهیم. سازنده ها و مخرب های STL تخصیص حافظه را به خوبی انجام می دهند.
-سوال:کمیته جنبی کتابخانه استاندارد ++C دارد فضای نام های استاندارد و قواعدی جهت مواجهه با استثناها تعریف می کند. آیا کلاسهای STL هم فضای نام و استثناها را خواهند داشت؟
-جواب:بله همین طوره. اعضای کمیته دارند روی آن کار می کنند و کار بزرگی دارند انجام می دهند.
-سوال:تعریف های احتمالی توسط استاندارد به چه صورت با تعریف های موجود STL متفاوت خواهد بود؟ آیا کمیته تاثیری در تغییرات آن خواهد داشت یا طراحی آن تحت کنترل دقیقتری است؟
-جواب:به نظر می رسد اجماع بر این قرار گرفته که نباید تغییر عمده ای در STL صورت بگیرد.
-سوال:با توجه پیش بینی اینکه STL جزء استاندارد می شود برنامه نویسان چگونه می توانند تجربه اولیه ای از آن داشته باشند؟
-جواب:آنها می توانند سرآیند (header) های STL را از سایت butler.hpl.hp.com و در زیر شاخه stl/ دانلود کنند و آن را تحت کامپایلرهای Borland یا IBM یا هر کامپایلری که به اندازه کافی قوی باشد که بتواند STL را کامپایل کند کامپایل کنند. تنها راه یادگیری یک سبک برنامه نویسی، انجام برنامه نویسی است. لازم است که مثالها را ببینند و برنامه ها را به این سبک بنویسند.
-سوال:شما دارید با P.J. (Bill) Plauger در نوشتن یک کتاب درخصوص STL همکاری می کنید. تاکید کتاب بر چیست و در چه زمانی قرار است منتشر شود؟
-جواب:قرار شده که در تابستان 1995 منتشر شود و قرار است یک پیاده سازی مشروح از STL باشد. که شبیه کتابهای Standard C Library و Draft Standard C++ Library نوشته Bill خواهد بود. او می خواهد کتابش در زمینه مرجع مستندات استاندارد در استفاده از STL اولین باشد. امیدوارم بتوانم با Bjarne مقاله ای در زمینه اندرکنشهای بین زبان و کتابخانه درچارچوب C++/STL بنویسم که ممکن است به یک کتاب دیگر منجر شود.
کارهای زیاد دیگری لازم است که صورت گیرد. برای موفق شدن STL ، کاربران بایستی با تجربه کردن این سبک برنامه نویسی، تحقیقاتی انجام دهند. کتابها و مقالات بیشتری باید در خصوص نحوه برنامه نویسی به این سبک نوشته شوند. کلاسهای درس لازم است تشکیل شود، خودآموزها لازم است نوشته شوند. ابزارهایی باید نوشته شوند که با آن بشود داخل کتابخانه جستجو و مرور کرد. STL یک چاچوب (framework) است و خیلی خوب می شود که ابزاری جهت مرورکردن این چارچوب داشته باشیم.
-سوال:ارتباط بین برنامه نویسی عام و برنامه نویسی شیء گرا چیست؟
-جواب:از یک لحاظ دنباله طبیعی ایده های اصلی برنامه نویسی شیء گراست یعنی جداکردن رابط از پیاده سازی و رفتار چندریختی کامپوننت ها. اما اختلاف عمیقی هم وجود دارد. برنمه نویسی شیء گرا بر عناصر دستور زبانی ساختار برنامه تاکید می کند. شما باید حتما از وراثت استفاده کنید، شما باید از کلاسها استفاده کنید باید از object ها استفاده کنید و object ها پیام می فرستند. برنامه نویسی عام با این مساله شروع نمی کند که ما باید از وراثت استفاده کنیم یا نکنیم. بلکه با این مساله شروع می کند که ابتدا تلاش می کند یک دسته بندی از چیزهای موجود و نحوه رفتار آنها انجام دهد. مثلا اینکه دوچیز مساوی هستند به چه معنی است، روش صحیح تعریف تساوی چیست؟ نه اینکه فقط کنش های تساوی را تعریف کنیم. ما می توانیم تساوی را عمیق تر تحلیل کنیم و به این نکته برسیم که به یک مفهوم عام از تساوی برسیم به این شکل که در صورتی دو چیز مساوی هستند که اجزاء آنها یا حداقل اجزاء اساسی آنها با هم مساوی باشند. می شود یک دستورالعمل برای عملیات تساوی داشته باشیم. می شود بحث کرد که اشیا از چه گونه هایی هستند. مثلا توالی ها هستند. عملیاتهایی روی توالی ها انجام می شود. پشتوانه مفهومی این عملیاتها چیست؟ چه نوع از توالی ها را از نظر به صرفه بودن پیچیدگی باید به کاربر پیشنهاد دهیم؟ چه نوع الگوریتم هایی برای توالی ها وجود دارد؟ چه نوع تابع مرتب سازی نیاز داریم؟ سپس بعد از اینکه اینها را انجام دادیم، بعد از اینکه یک دسته بندی مفهومی از کامپوننت ها را داشتیم می توانیم نحوه پیاده سازی آن را بررسی کنیم. آیا به template نیاز است؟ لازم است از وراثت استفاده شود؟ به ماکرو نیاز می شود؟ از چه نوع تکنولوژی موجود در زبان استفاده کنیم؟ ایده اساسی برنامه نویسی عام، عبارت است از دسته بندی کامپوننت های نرم افزاری انتزاعی و رفتار آنها تا به یک دسته بندی استاندارد برسیم. نقطه شروع عبارت است از الگوریتم ها و ساختمان های داده واقعی و کارا نه خود زبان. البته برنامه نویسی عام در این زبان انجام می شود. ما نمی توانیم برنامه نویسی عام را بدون استفاده از یک زبان انجام دهیم. STL در ++C انجام شده. شما می توانید آن را در زبان Ada یا مثلا زبانهای دیگر پیاده سازی کنید. این پیاده سازی ها کمی متفاوت خواهند بود اما نکات اساسی است که باید در همه رعایت شود. جستجوی دودویی در همه آنها باید باشد، مرتب سازی در همه آنها باید باشد. کمی اصلاحات که توسط زبان تحمیل می شود بر معنا و مفهوم محتوی ها اعمال می شود. در بعضی زبانها می توانیم بیشتر از وراثت استفاده کنیم، در بعضی زبانها باید از template استفاده کنیم. پس اختلاف اساسی این دو رویکرد این است که برنامه نویسی عام از پشتوانه مفهومی و تفکیک مفاهیم شروع می شود. مثلا تصمیم می گیریم که یک کامپوننت به نام swap داشته باشیم. و بعدا ترسیم می کنیم که این کامپونند در زبانهای مختلف چگونه کار خواهد کرد. تاکید بر پشتوانه مفهومی و دسته بندی مفهومی است اما شیء گرایی تاکید محکمتری ـ وبه نظر من تاکید بیش از حدی ـ بر نحوه نوشتن برنامه ها می کند یعنی تاکید بر استفاده از سلسله مراتب کلاسها. برنامه نویسی شیء گرا به شما نحوه ایجاد سلسله مراتب کلاسها را توضیح می دهد اما در خصوص اینکه درون این سلسله مراتب کلاسها چه چیزی باید باشد توضیحی ارائه نمی دهد.
-سوال:شما آینده STL و برنامه نویسی عام را چگونه می بینید؟
-جواب:من قبلا به رویای برنامه نویسان اشاره کردم که عبارت بود از اینکه مجموعه هایی استاندارد از کامپوننت های انتزاعی با رابطهای قابل فهم و مطابق با یک سبک و سیاق مشترک وجود داشته باشد. برای این کار لازم است تلاش بیشتری جهت توسعه پشتوانه علمی این سبک برنامه نویسی صورت گیرد. STL این کار را با دسته بندی مفهومی بعضی کامپوننت های مهم تا حدی شروع کرده. لازم است کار بیشتری صورت بگیرد. هدف این است که مهندسی نرم افزار از کاردستی به یک رشته مهندسی تبدیل شود. لازم است دسته بندی از مفاهیم اساسی و قوانینی که بر این مفاهیم حاکم است صورت گیرد البته اینها باید کاملا فهمیده شود باید روی آنها فکر شود و هر برنامه نویس باید آنها را بداند حتی اگر نتواند به درستی آنها را توضیح دهد. خیلی از افراد ریاضی را بلدند اگرچه در خصوص جابجایی (commutativity) چیزی نشنیده اند. کسی که از دبیرستان فارغ التحصیل شود می داند که 2+5 برابر است با 5+2. اما همه آنها نمی دانند که این عبارت است خاصیت جابجایی جمع. امیدوارم که بیشتر برنامه نویسان خصوصیات مفهومی اساسی مربوط به عملیاتهای اساسی را یاد بگیرند. انتساب به چه معناست؟ تساوی چه معنی می دهد ؟ و چگونه می توان ساختمان داده ایجاد کرد.
در حال حاضر ++C بهترین وسیله برای این سبک برنامه نویسی است. من زبانهای مختلف را امتحان کرده ام و فکر می کنم ++C این ترکیب جالب انتزاع و کارایی را ممکن می سازد. در عین حال، فکر می کنم می شود زبانی را بر اساس C و بسیاری از بینش هایی که ++C به جهان معرفی کرده طراحی کرد که برای این سبک برنامه نویسی مناسب تر باشد که فاقد بعضی کمبودهای زبان ++C مخصوصا سایز زیادش باشد. STL با مفاهیم سر و کار دارد. مثلا تکرارگر چیست؟ جواب این سوال این نیست که مثلا بگوییم یک کلاس یا یک نوع، از نظر STL این سوال جوابش یک «مفهوم» است. ( به شکل رسمی تر به قول Bourbaki عبارت است از یک نوع ساختاری یا از نظر منطق دانان عبارت است از نظریه یا از نظر تئوری نوع ها عبارت است از یک sort ) در یک زبان مثلا می توان تکرارگر جلو رونده (forward) تعریف کرد که تنها به عنوان یک مفهوم در STL تعریف شده والبته چنین مفهومی در ++C وجود ندارد. سپس می توان تکرارگر جلو رونده را به تکرارگر دوطرفه (bidirectional) تغییر دهیم. سپس می توان آن را تبدیل به تکرارگر تصادفی (random) کرد. امکان این وجود دارد که زبانی طراحی کنیم که حتی سهولت بیشتری برای این سبک برنامه نویسی فراهم کند. کاملا معتقدم که آن زبان باید به همان اندازه C و ++C از نظر نردیکی به ماشین کارایی داشته باشد. و بر این باورم که می توان زبانی ساخت که از یک طرف همجواری نزدیک به ماشین را فراهم کند و از طرف دیگر توانایی این را داشته باشد که با چیزهای خیلی انتزاعی کار کند. فکر می کنم که حتی انتزاع می تواند در اینجا از انتزاع ++C بالاتر باشد در حالیکه ماشین هر دو هم یکسان باشد. فکر می کنم برنامه نویسی عام می تواند تحقیقات مربوط به زبان را تحت تاثیر قرار دهد و زبانهایی خواهیم داشت که استفاده از آنها راحت باشد و جهت این سبک برنامه نویسی هم مناسب باشند. از اینجا شما می توانید نتیجه بگیرید که کار بعدی من چه خواهد بود.