Tuesday, January 23, 2007

Ruby 4

قسمت اول

قسمت دوم

قسمت سوم

Meta Programming

یکی از روش هایی که در Ruby زیاد استفاده می شود meta programming است. meta programming را بطور ساده می توان نوشتن کدی که کد دیگری را تولید می کند بیان کرد. meta programming در زبان های دیگر مانند جاوا و زبان های پلت فرم دات نت هم وجود دارد. در دات نت یک روش متداول برای این کار استفاده از Attribute ها است. یک مثال متداول استفاده از Attribute های WebMethod و WebService برای ساختن سرویس های وب هست. در جاوا تا قبل از JDK 1.5 روش متداول استفاده از XML برای این کار بود (برای مثال Axis برای تولید Stub های وب سرویس ها از XML استفاده می کرد) ولی بعد از معرفی Annotation ها(مکانیزمی شبیه Attribute ها در دات نت) در JDK 1.5 روش جایگزینی برای استفاده از XML مطرح شد. در هر حال ایده کلی برای meta programming در زبان های کامپایلری این است برنامه نویس اطلاعات اضافی را وارد کند(با استفاده از XML، Annotation، Attributes یا هر روش دیگری). سپس یک ابزار(مانند APT در جاوا) با بررسی این اطلاعات اضافی کدی را تولید کند که بتوان آنرا با استفاده از کامپایلر کامپایل کرد. روش های دیگری که برای meta programming در جاوا استفاده می شود تغیر در بایت کد کلاس ها هنگام load کردن کلاس ها، استفاده از dynamic proxy ها و تولید کلاس ها در زمان اجرا است که عمدتا روش های پیچیده ای هستند.

meta programming در Ruby بسیار ساده تر و متداول تر است. برای مثال مسئله دسترسی به فیلدهای یک شیئ را در نظر بگیرید. در جاوا راه حل متداول نوشتن متد های getter و setter و در C# استفاده از Property ها است. بطور معمول این مکانیزم ها یک کار را تکرار می کنند(getter ها مقدار فیلد را بر می گردانند و setter ها مقدار فیلد را تغییر می دهند). Ruby برای این کار راه حل جالبی دارد، در Ruby با استفاده از متدهای attr_reader و attr_writer می توان getter و setter و با استفاده از attr_accessor می توان هر دوی آنها را درست کرد. جالب این که این متد ها، متد های خاصی نیستند و تنها کاری که می کنند این است که رشته ای را درست کرده و برای اجرا به مفسر Ruby می دهند.

class FieldTest

attr_reader :r

attr_writer :w

attr_accessor :rw

def to_s

"@r, @w, @rw"

end

end

ft = FieldTest.new

ft.w = 111

ft.rw = "hello"

puts ft.r

یک راه حل ساده برای meta programming در Ruby استفاده از توابع eval است. این توابع معمولا یک رشته را به عنوان ورودی می گیرند و آن را اجرا می کند. فرض کنید می خواهیم کلاسی داشته باشیم که متد هایی با نام اعداد 1 تا 5 دارند و مقدار این اعداد را بر می گردانند، یک راه حل این است که 5 متد مختلف بنویسیم که مقادیر مورد نظر را بر می گردانند ولی یک راه حل بهتر در ادامه آورده شده:

class Numbers

nums = {'one' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5}

nums.each do |k, v|

module_eval "def #{k} \n #{v} \nend"

end

end

# Test class Numbers

n = Numbers.new

puts n.one # prints 1

puts n.two # prints 2

puts n.three # prints 3

puts n.four # prints 4

puts n.five # prints 5

متد module_eval رشته داده شده را به مفسر Ruby می فرستد تا آنرا اجرا کند. یک ویژگی بسیار مطلوب meta programming این است که حجم کد نوشته شده را بسیار کاهش می دهد(تصور کنید کلاس Numbers که در اینجا تنها در 4 خط نوشته شده در حالت عادی چه حجم زیادی می داشت) ولی ویژگی های مهم تری هم دارد که در ادامه به آن پرداخته ام.

Aspect Oriented Programming:

AOP یکی از روش های برنامه نویسی است که این روز ها خیلی در مورد آن صحبت می شود. AOP قابلیت های بسیاری به زبان های شیئ گرا اضافه می کند. بسیاری AOP را بعد از روش های ساخت یافته و شیئ گرا، بزرگترین تحول در دنیای برنامه نویسی دانسته اند. نکته جالب توجه این است که وقتی با Ruby کار می کنید، نیاز چندانی به AOP پیدا نمی کنید. عمده کارهایی که در AOP با آن مواجه هستید، اضافه کردن یک متد به یک کلاس، جایگزین کردن یک متد با یک متد جدید و اجرای یک کد قبل یا بعد از یک متد است. در Ruby به راحتی می توانید تمام این کارها را انجام دهید. مثلا فرض کنید بخواهید قبل از اینکه متد sort از کلاس Array فراخوانی شود، رشته ای را چاپ کنیم تا از فرا خوانی این متد باخبر شویم. کافی است کلاس Array را باز کنیم، متد sort را به old_sort تغییر نام دهیم و متد sort جدیدی را تعریف کنیم، در متد جدید کافی است رشته مورد نظر را چاپ کنیم و بعد متد قدیمی را فراخوانی کنیم:

class Array

alias_method :old_sort, :sort

def sort

puts 'Array.sort called !'

old_sort

end

end

#Test new sort

a = [3, 2, 4, 1, 4]

puts a.sort

# Output:

# Array.sort called !

# 1 2 3 4 4

البته یکی از ویژگی های زبانهایی که از AOP پشتیبانی می کنند(مانند AspectJ) پشتیبانی از wildcard ها است که چنین چیزی بطور استاندارد در Ruby پشتیبانی نمی شود.

Database:

یکی از مسائل مهمی که هر زبان برنامه نویسی باید برای حل آن فکری بکند کار کردن با پایگاه داده در آن زبان است. زبان های مختلف راهکار های متعددی برای این مسئله ارائه داده اند، در جاوا استاندارد ساده JDBC شاید اولین تلاش در این زمینه بود. بعد از آن ارائه EJB ها (با همه سر و صدایش) و سپس راه حل های مختلف بر پایه Object Relational Mapping مثل Hibernate، iBatis و Apache OJB نشان از تلاش های گسترده در این زمینه دارد. در دنیای دات نت هم کپی های این ORM ها مثل NHibernate و iBatis.NET، تکنولوژی هایی مثل ADO.NET و در نهایت ابتکار جدید ماکروسافت به نام LINQ وجود دارد. نکته مشترکی که در تمام این راه حل ها وجود دارد static بودن زبانی است که راه کار به وسیله آن پیاده سازی شده.

اما در پایگاه داده هم Ruby راه حل ساده خود را دارد. راه حل Ruby برای این کار ActiveRecord نام دارد. فرض کنید که در پایگاه داده خود جدولی به نام Students دارید که دو فیلد name و id دارد. قطعه کد زیر یک رکورد به جدول Students اضافه می کند:

ActiveRecord::Base.establish_connection(:adapter => "mysql",

:host => "127.0.0.1",

:username => "root",

:password => "",

:database => "Uni")

class Student <

ActiveRecord::Base

# Fields are fetched from database automatically

end

stu = Student.new

stu.name = 'mohsen'

stu.id = 12345

stu.save

هنگامی که کلاسی از ActiveRecord::Base ارث می برد، این کلاس بطور اتوماتیک فیلدهای پایگاه داده را به کلاس مورد نظر اضافه می کند، نکته جالب این است که ActiveRecord برای پیدا کردن فیلدها به دنبال جدولی هم نام با کلاس(ولی بصورت جمع) می گردد. این راه حل در Ruby زیاد استفاده می شود و باعث ساده شدن کار می شود. البته اگر جداول ما نام دیگری هم داشته باشند می توان ActiveRecord را برای استفاده از آن بکار برد ولی در این حالت باید اسم جدول برای آن مشخص شود.

همچنین ActiveRecord قادر است روابط یک به چند و چند به چند بین جداول را به کلاس های برنامه map کند، ولی در اینجا قصد پرداختن به جزئیات این مسئله را ندارم.

نکته ای که باید به آن توجه کرد این است که داینامیک بودن Ruby و امکان اضافه کردن فیلد به کلاس در زمان اجرا باعث شده بتوان چنین قابلیتی را پیاده سازی کرد و در زبانهای کامپایلری امکان پیاده سازی چنین راهکاری وجود ندارد.

Web:

شاید آن چیزی که باعث متداول شدن Ruby شد پلت فرم وبی بود که بر روی این زبان ایجاد شده بود. این پلت فرم Ruby on Rails نام دارد و تغیرات زیادی را در طرز تفکر توسعه دهندگان در دنیای وب ایجاد کرده. پرداختن به Ruby on Rails خود بحث مفصلی است که در این کوچک نوشته نمی گنجد!

معایب Ruby:

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

نکته اول اینکه Ruby یک زبان اسکریپتی است و مسلما به مراتب کند تر از زبان های کامپایلری است، ولی این نکته را هم بگویم که سرعت اجرا یکی از فاکتورهای یک زبان است و بستگی زیادی به پیاده سازی آن دارد. امروزه با توجه به کاهش قیمت سخت افزار و افزایش سرعت کامپیوترها از اهمیت سرعت اجرا به شدت کاسته شده و فاکتورهای دیگری در زبان های برنامه نویسی اهمیت پیدا کرده اند(البته زبان های اسکریپتی را دست کم نگیرید و فراموش نکنید که ویکیپدیا یکی از بزرگترین سایت های اینترنت بر روی PHP کار می کند)

نکته دوم اینکه استفاده از یک زبان اسکریپتی به معنی این است که سورس کد برنامه شما در دسترس همه قرار دارد که در بسیاری از موارد قابل قبول نیست(البته می توان از تکنیک هایی مثل Obfuscation هم استفاده کرد ولی در هر حال این کار هم مشکلات خاص خود را دارد)

نکته سوم اینکه هنگامی که با یک زبان کامپایلری کار می کنید بسیاری از مشکلات احتمالی در زمان کامپایل چک می شود و در زمان اجرا با مشکلات کمتری روبرو هستید. برای پی بردن به بسیاری از مشکلات در Ruby باید برنامه خود را اجرا کنید. از این رو برنامه های نوشته شده به زبان Ruby وابستگی زیادی به Unit Testing و Code Coverage دارند.

نکته چهارم اینکه Ruby هنوز به اندازه لازم به تکامل نرسیده. هنوز انجام یک پروژه بزرگ با جاوا ریسک کمتری را تحمیل می کند. هنوز ابزار های توسعه در Ruby در اوایل کار خود قرار دارند و راه درازی تا رسیدن به آنجایی که امروزه ابزارهای زبان هایی مثل جاوا و دات نت قرار دارند باقی مانده.

کلام آخر:

راستش را بخواهید خیلی مسائل در مورد Ruby ماند که من نتوانستم در مورد آن بنویسم. فعلا نه وقت کافی برای این کار دارم و نه حال و حوصله این کار را. برای همین هم سعی کردم هر طور که شده این پست، آخرین پست من در باره این زبان باشد. حتما این موضوع را از طرز نوشته ام احساس کرده اید. در هر حال توصیه می کنم اگر به این زبان علاقه مند شده اید دست به کار شوید و مفسر Ruby و یک IDE مناسب را download کنید و شروع به کد نویسی کنید. در ابتدای کار شاید برایتان عجیب باشد که چقدر راحت می توان به این زبان کد نوشت.

مراجع:

[1] Beyond Java, By Bruce A. Tate, O'Reilly, September 2005, ISBN: 0-596-10094-9

[2] Ruby Cookbook, By Lucas Carlson, Leonard Richardson, O'Reilly, July 2006, Print ISBN-13: 978-0-59-652369-5

[3] Programming Ruby, The Pragmatic Programmers’ Guide, Second Edition, Dave Thomas

Thursday, January 04, 2007

Open Source(1)

استاد مارتین فاولر در آن مقاله Is Design Dead? خودشان یک جمله ای دارد که برای من خیلی جالب بود: "In software any term means many things". حتما شما هم خیلی اوقات این قضیه را احساس کرده اید. یک کلمه را که از چهار نفر مختلف سوال کنی، پنج تا برداشت مختلف از آن دارند، و البته شاید هیچ کدام آنها درست نباشد و در عین حال هیچ کدام هم غلط نباشد.

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

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

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

تاریخچه اپن سورس:

با وجود اینکه هیچ وقت از تاریخ خوشم نمی آمد، ولی نمی دانم چرا تاریخچه ها را دوست داشتم. تاریخچه اپن سورس هم تاریخچه جالبی است. البته لفظ اپن سورس عمر زیادی ندارد و اولین بار سال 1998 بود که بکار برده شد. ولی پروژه های اپن سورس سابقه اش به پیش از این سال بر می گردد. بیشتر مطالب این قسمت را از کتاب Understanding Open Source Software Development چاپ Addison Wesley با مقدار زیادی تغییر(یا بهتر بگویم با مقدار زیادی تحریف!) آورده ام. سعی کرده ام هر جایی که لازم بوده لینک اضافی هم بگذارم.

در طول تاریخ چند ده ساله نرم افزار چند اتفاق افتاده که روی وضعیت کنونی دنیای اپن سورس خیلی موثر بوده. سعی کرده ام در اینجا چند تا از این اتفاقات را بطور مختصر بررسی کنم، این تاریخ مختصر را بدون هیچ دلیل خاصی به سه دوره کاملا بی ربط تقسیم کرده ام:

از توسعه یونیکس تا انتشار BSD:

يکي از اتفاقات جالب و موثر در اين زمينه، رأي دولت آمريکا بر ضد غول مخابراتي AT&T بود، در سال 1956 دولت آمريکا شرکت AT&T را از ورود به زمينه هاي غير مخابراتي منع کرد، اين رأي باعث شد که سيستم عامل يونيکس که در آزمايشگاه bell بوسيله دنيس ريچي و کن تامپسون توسعه يافته بود نتواند به فروش برسد، داستان از اين قرار بود که تامپسون علاقه مند به اجراي بازي Space Travel بر روي کامپيوتر PDP-7 بود و براي اين کار يک سيستم عامل کامل نوشت(راست و دروغش باشد پای آن هایی که این داستان را تعریف کرده اند ولی در هر حال این پایه همان سیستم عاملی شد که بعدا اسمش را یونیکس گذاشتند)! چون AT&T از فروش محصولات غير مخابراتي منع شده بود، متن يونيکس را در بين دانشگا هها و مؤسسات تحقيقاتي توزيع کرد.

يکي ديگر از حرکتهاي مؤثر در اين زمينه توزيع نرم افزارهاي دانشگاه برکلي بود که در سال 1977 شروع شد، گروه BSD سيستم عامل يونيکس را توسعه داد و ويژگيهاي جديدي را به آن اضافه کرد، اين سيستم عامل بعدها در Arpanet مورد استفاده قرار گرفت. گروه BSD همچنين پروتکل TCP/IP رابر روي سيستم عامل خود پياده سازي کرد، که بعدها باعث توسعه سريع اينترنت شد .

نرم افزارهاي مهمي که توسط اين گروه توسعه يافت BIND(سرور(DNS و Send Mail(mail server) بود، این نرم افزارها هنوز هم بطور گسترده ای مورد استفاده قرار می گیرد.

در سال 1984 با اتمام انحصار، AT&T برعليه BSD شکایت کرد، دعواي اين دو که تا اوايل 1990 نيز ادامه يافت، باعث شد که بسياري از توسعه دهندگان به فکر توسعه سيستم عامل هاي ديگري همانند Linux ، Free BSD و Open BSD بيافتند. تأثير مهمي که داستان BSD بروي جنبش نرم افزارهاي متن باز گذاشت، تغيير در ايدئولوژي ها و نحوۀ نگرش جديد رهبران اين جنبش بود.

از درایور پرینتر تا بزرگترین پروژه تاریخ:

یکی دیگر از حوادث مهمی که در تاریخ نرم افزارهای متن باز اتفاق افتاده تاسیس بنیاد نرم افزارهای آزاد (FSF=Free Software Foundation) توسط ریچارد استالمن است. داستان به آن زمانی مربوط می شود که استالمن در آزمایشگاه هوش مصنوعی دانشگاه MIT کار می کرد و اولین پرینتر لیزر جت شرکت زیراکس را دریافت کرد. گویا درایور این پرینتر مشکل کوچکی داشته که به راحتی قابل حل بوده، به همین خاطر استالمن از شرکت زیراکس می خواهد که سورس برنامه را در اختیار او قرار بدهند تا او بتواند تغییرات مورد نظرش را بر روی آن اعمال کند ولی زیراکس از این کار امتناع می کند. بعد از این اتفاق هست که استالمن به این نتیجه می رسد که نرم افزار باید آزاد باشد و از MIT استعفا می کند و در سال 1985 بنیاد نرم افزارهای آزاد را تاسیس می کند(این که یک نفری به خاطر یک اشکال در درایور پرینتر به این نتیجه برسد که نرم افزار باید آزاد باشد و بعد از آن از جایی مثل MIT استعفا بدهد و برود یک موسسه تاسیس کند، در نگاه اول خیلی احمقانه به نظر می رسد ولی بعدا توضیح می دهم که این نگرش و حرکت استالمن چه تاثیری بزرگی بر دنیای نرم افزار داشته است)

ايدئولوژي FSF براين قرار بود که عبارت copyright – all rights reserved بايد به عبارت copyleft-all rights reversed تغيير يابد. تحت مفهوم copyleft هر کسي اجازه استفاده از نرم افزار، کپي کردن و تغيير آن را دارد، و حتي مي تواند دوباره آن را توزيع کند، ولي نمي تواند ديگران را در استفاده از آن محدود کند. همین ایدئولوژی باعث شکل گیری اصطلاح Free Software و مجوز GPL شد. این اصطلاح به خاطر ابهامی که در کلمه Free در زبان انگلیسی وجود دارد بعدا مورد انتقادات بسیاری قرار گرفت (بر خلاف تمام مواردی که معمولا دوستان کامپیوتری می گویند که در زبان فارسی معنی فلان کلمه وجود ندارد یا چند کلمه انگلیسی تنها یک معنی فارسی دارد، در این مورد فارسی واقعا شاهکار کرده. در فارسی دو کلمه آزاد(همان معنی که مد نظر استالمن بوده) و رایگان(همان معنی که مد نظر استالمن نبوده) وجود دارد که در انگلیسی به هر دوی آنها Free می گویند. همین ابهام بوده که باعث شده برخی این عبارت را به مفت افزار ترجمه کنند(زیاد جدی نگیرید)).

استالمن پس از تاسیس FSF نرم افزار های زیادی از جمله ویرایشگر emacs و مجموعه کامپایلرهای GCC را تولید کرد. ابزارهایی که استالمن و دوستانش تولید کردند بعدها در لینوکس مورد استفاده قرار گرفت و همچنین سیستم عامل لینوکس تحت مجوز GPL (مجوزی که استالمن ارائه داده بود) منتشر شد.

اتفاق مهم دیگری که همه با آن آشنا هستند شروع به کار لینوس تروالدز بر روی سیستم عامل لینوکس بود(بر سر تلفظ کلمه Linux اختلاف نظرهای زیادی وجود دارد ولی در اینجا من از همان لفظ متداول لینوکس استفاده می کنم).

تروالدز که یک دانشجوی 21 ساله بود و در دانشگاه هلسینکی درس می خواند در سال 1991 تصمیم گرفت سیستم عامل مینیکس(minix) را طوری تغییر دهد که قابلیت اجرا بر روی IBM PC 386 را داشته باشد. سیستم عامل مینیکس همان سیستم عاملی هست که توسط آندرو تننبام تولید شده و اگر کتاب سیستم عامل تننبام را دیده باشید سورس کد این سیستم عامل تقریبا نیمی از صفحات این کتاب را گرفته است.

نکته جالب این است که تروالدز در اولین اعلام عمومی خود، بیان می کند که برای تفریح این سیستم عامل را نوشته و قرار نیست که یک سیستم عامل حرفه ای تولید کند. ولی در هر حال، دست روزگارش چنان رقم زند که پس از گذشت چند سال به یکی از قدرتمند ترین سیستم عامل های جهان مبدل شد. در حال حاظر برآورد می شود که بیش از چهل هزار نفر در توسعه لینوکس مشارکت داشته باشند، همین مسئله هست که باعث شده تروالدز ادعا کند بزرگترین پروژه تاریخ را به جهانیان عرضه کرده.

از وب سرور آپاچی تا به امروز:

يکي ديگر از سالهاي به يادماندني، سال 1995 بود. سالي که در آن گروهي از توسعه دهندگان تصميم به توسعه وب سرور آپاچي گرفتند. وب سرور آپاچي براساس وب سروري که قبلاً توسط راب مک کول توسعه يافته بود با اضافه کردن تعدادي patch به آن توســعه يافت. به همين دليــــــل است که آنرا Apache Server (کــه خوانده مي شودA Patchy Server) نام نهادند.

بنياد نرم افزاري آپاچي(ASF=Apache Software Foundation) که در آن زمان تشکيل شد، امروز به يکي از بزرگترين گروههاي نرم افزاري تبديل شده است.

تا سال 1998 هنوز اصطلاح اپن سورس مطرح نشده بود و عمدتا از اصطلاح Free Software که توسط استالمن مطرح شده بود استفاده می شد. سال 1998 سالی بود که اصطلاح اپن سورس در جلسه ای که با حظور تعدادی از افراد از جمله اریک ریموند برگزار شد بوجود آمد. در همان سال و بعد از این جلسه بود که Netscape سورس مرورگر معروف خود را با نام Mozilla و تحت یک مجوز اپن سورس ارائه کرد (استاد ویکیپدیا این موضوع را مفصل تر توضیح داده اند)

بعد از سال 1998 و با مطرح شدن اصطلاح اپن سورس و مقبولیت عمومی آن پیشرفت های زیادی در این زمینه حاصل شد. توسعه اینترنت هم به گسترش اپن سورس خیلی کمک کرد. در حال حاظر دنیای نرم افزار به جایی رسیده که می توان تقریبا هر سیستم کوچک یا بزرگ نرم افزاری را با استفاده از ابزارهای اپن سورس تولید کرد (امری که شاید پنج سال پیش ممکن نبود). بسیاری از ابزارهای اپن سورس رقبای جدی برای محصولات تجاری هستند و بسیاری دیگر از محصولات اپن سورس حتی رقیب جدی تجاری ندارند. بعدا بیشتر در این مورد توضیح می دهم و سعی میکنم مثال هایی هم بیاورم.