Thursday, January 17, 2008

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

interface NaturalNum {

boolean isZero();

NaturalNum next();

NaturalNum prev();

NaturalNum add(NaturalNum n);

NaturalNum sub(NaturalNum n);

}

class Zero implements NaturalNum {

public static final Zero INSTANCE = new Zero();

private Zero() {}

public NaturalNum add(NaturalNum n) { return n; }

public boolean isZero() { return true; }

public NaturalNum next() { return new Successor(this); }

public NaturalNum prev() { throw new RuntimeException(); }

public NaturalNum sub(NaturalNum n) {

if(n.isZero()) return this;

else throw new RuntimeException();

}

public String toString() { return ""; }

}

class Successor implements NaturalNum {

private final NaturalNum p;

public Successor(NaturalNum n) { this.p = n; }

public NaturalNum add(NaturalNum n) { return this.prev().add(n.next()); }

public boolean isZero() { return false; }

public NaturalNum next() { return new Successor(this); }

public NaturalNum prev() { return p; }

public NaturalNum sub(NaturalNum n) {

return n.isZero() ? this : this.prev().sub(n.prev());

}

public String toString() { return prev() + "1"; }

}

public class NaturalNumberTest {

public static void main(String[] args) {

NaturalNum three = Zero.INSTANCE.next().next().next();

NaturalNum four = Zero.INSTANCE.next().next().next().next();

System.out.println(three);

System.out.println(four);

System.out.println(three.add(four));

System.out.println(four.sub(three));

}

}

Saturday, December 08, 2007

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

1- فایرفاکس و بچه هایش: انصافا فایرفاکس جزء ابزارهایی است که اگر نبود زندگی برای من خیلی سخت می شد، به علاوه من خودم از ایده فایرفاکس (XUL) خیلی لذت می برم. همین ایده بوده که باعث شده این هم Add-On بدرد بخور برای این مرورگر وجود داشته باشه. روی فایرفاکس من فعلا این Add-On ها نصب هست:

Adblock Plus, Clip to OneNote, Customize Google, DOM Inspector, Downloads in Tab, DownThemAll, Header Spy, Live HTTP Headers, Locationbar, Menu Editor, President Ahmadinejad Countdown, Right Encoding, Save Link in Folder, Scrap Book, Stumble Upon, Web Search Pro, Yahoo Mail Notifier

2- یاهو ساید بار و بچه هایش: ساید بار های زیادی برای سیستم عامل ویندوز وجود داره ولی من بدون هیچ دلیل خاصی ساید بار یاهو رو ترجیح می دم (شاید به خاطر اینکه محمد رشتی این رو به من توصیه کرده). دو تا از ویجت های جالب یاهو ساید با که خیلی به من کمک می کنه، یکی تقویم جلالی هست که بوسیله یک نفر به نام محمد پروشانی نوشته شده (که من ایشون رو نمی شناسم ولی ازشون خیلی تشکر می کنم). یکی Todo List هست که به وسیله Kurt Papake نوشته شده و من از ایشون هم تشکر می کنم.

3- OneNote و هنرهایش: به نظر من OneNote یکی از محصولات بی نظیر ماکروسافت هست. اگر سرتان خیلی شلوغ است توصیه می کنم حتما از این ابزار استفاده کنید. OneNote رو خود مهرداد به من پیشنهاد داد.

4- تاندربرد و وب میل: Thunderbird به همراه Add-On وب میلش ابزار خیلی خوبی هست برای کسی که لپ تاپ دارد و گاهی اوقات به اینترنت وصل هست و گاهی اوقات نیست خیلی مفید است.

5- KMPlayer و VLC Player: این دو تا از اون مدیا پلیرهایی هستند که همه نوع فایلی رو پخش می کنه. حتما امتحانشون کنید.

6- 7z و سادگیش: یک Archive Manager ساده، سریع و بی دردسر، که من به خاطر اپن سورس بودنش او رو به WinRar ترجیح می دم.

7- TortoiseSVN و اطمینان قلبش: یک interface (؟) برای سیستم ویرایش SVN که خیلی خوب با Explorer ویندوز integrate شده. جدای از پروژه های کاری، همه پروژه های درسی، سمینارها، مقاله ها و هر چیز در حال توسعه ای روی هارد درایو من، روی SVN قرار داره. این کار به آدم این اطمینان رو میده که خراب کاری هاش (مخصوصا توی شرایط حساس) هزینه زیادی نداره و با چند تا کلیک می تونید وضعیت رو به شرایط مطلوب بر گردونید. خوبی TortoiseSVN این هست که نیازی به نصب سرور نداره و خودش به صورت مستقل روی یک کامپیوتر شخصی می تونه مورد استفاده قرار بگیره.

8- TrueCrypt: وقتی امنیت بعضی از فایل ها برای شما مهم باشه، TrueCrypt می تونه خیلی مفید باشه. این ابزار یک درایو مجازی با محتویات رمز شده در اختیار کاربر قرار میده. یکی از ویژگی های مهم این نرم افزار کارایی خیلی بالای اون هست. شما می تونید درایو هایی رمز شده با حجم چند گیگا بایت داشته باشید و خیلی راحت فایلهاتون رو از/به اون کپی کنید. TrueCrypt دقیقا شبیه یک هارد درایو عادی برای شما کار میکنه.

9- eclipse و groovy: جدای از نوشتن برنامه های درست و حسابی با eclipse خیلی اوقات نیاز پیدا می کنید که چند خط اسکریپت برای انجام کاری بنویسید. من معمولا این کار رو توی محیط eclipse و با استفاده از جاوا یا groovy انجام میدم. البته این مساله بستگی به تسلط شما به محیط و زبان برنامه نویسی داره.

10- vim: قبلا در مورد vim یک پست داشتم. ویرایشگر جالبی هست.

11- Excel و Statistica: مجموعه آفیس ماکروسافت در مجموع یکی از شاهکارهای مایکروسافت محسوب میشه (با وجود اینکه خیلی از محصولات ماکروسافت خوشم نمیاد ولی آفیس واقعا جالبه)، خوب excel یکی از ابزارهایی هست که زیاد از اون استفاده می کنم. بعضی اوقات که توی excel نمیشه کاری رو به راحتی انجام داد استفاده از Statistica خیلی می تونه کمک بکنه. Statistica یک نرم افزار آماری خیلی قوی هست، یکی از ویژگی های جالب این نرم افزار این هست که در عین قدرتمند بودن خیلی ساده میشه ازش استفاده کرد و نیاز به آموزش زیادی نداره.

12- Paint.NET: به جای نرم افزار Paint ویندوز من از یک نرم افزاری به نام Paint.NET استفاده می کنم. خوبی این نرم افزار این هست که در عین سادگی خیلی از عملگرهای لازم برای تغییر تصویر رو داره.

13- Vidalia: این نرم افزار یک interface برای استفاده از Tor هست. Tor یک شبکه توزیع شده برای بی نام و نشان (Anonymous) ماندن بر روی اینترنت هست. Tor حداقل دو تا مشکل عمده رو حل می کند. اول اینکه با استفاده از اون می تونید به سایت هایی که اجازه دسترسی کاربران ایرانی رو نمیدن دسترسی داشته باشید (چون استفاده از Tor باعث میشه از دید سرور، آدرس IP شما چیز دیگری به نظر برسه). دوم اینکه Tor برای شما Port Forwarding انجام میده. در جاهایی مثل دانشگاه ها و شرکت ها، که معمولا پورت های غیر ضروری به وسیله firewall بسته شده، شما می تونید با استفاده از این نرم افزار اون نرم افزارها رو اجرا کنید!

Sunday, July 15, 2007

کپی غیر قانونی نرم افزار

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

Wednesday, June 06, 2007

گوگل

چند وقتی هست که سرم خیلی شلوغ هست، خیلی شلوغ تر از آنکه وقت کنم چیزی بنویسم. هفته ای 10 روز کار دارم! برای همین هم چند وقتی هست که هیچ پستی نداشته ام. بعضی از دوستان هم فرموده بودند خیلی طولانی می نویسی، سعی می کنم این بار کوتاه تر بنویسم.

نمی دانم چقدر گوگل را می شناسید و نمی دانم آیا تا بحال اسامی سرگی برین و لارنس پیج به گوشتان خورده یا نه. همین قدر بگویم که این دو نفر موسسین گوگل بوده اند. یکی از نکات جالب در مورد گوگل این است که ساختار داخلی آن تا حد زیادی برای دنیا ناشناخته است. به نظر می رسد صاحبان این غول اینترنتی خیلی دلشان نمی خواهد رقبا از کارشان سر در بیاورند. ولی در هر حال برخی از مقالاتی که در مورد گوگل منتشر شده نکات جالبی را در مورد آن به ما یاد می دهد. یکی از معدود مقالاتی که در مورد ساختار داخلی گوگل منتشر شده مقاله ای است با عنوان The Anatomy of a Large-Scale Hypertextual Web Search Engine. فکر می کنم این مقاله سال 1998 یا 1999 بوده که منتشر شده(این مقاله ای که در دست من است تاریخ انتشار ندارد ولی از متن آن می توان این تاریخ را حدس زد). توی دنیای کامپیوتر این مقاله یکی از مقالاتی هست که citation خیلی بالایی دارد(نشان از اهمیت و اعتبار این مقاله دارد). یکی از زیباترین و هوشمندانه ترین مواردی که در این مقاله می توانید یاد بگیرید الگوریتم رتبه دهی صفحات (Page Ranking) در گوگل هست. الگوریتم رتبه بندی در موتورهای جستجو از چند جهت اهمیت دارد. یا بهتر بگویم باید چند ویژگی را داشته باشد.

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

ویژگی دوم که شاید از ویژگی اول هم مهمتر باشد این است که الگوریتم رتبه بندی صفحات باید به شکلی باشد که نتوان به راحتی و با تغییر محتوای*** صفحات بر روی آن تاثیر زیادی گذاشت. این نکته را در نظر بگیرید که برای خیلی از شرکت ها این نکته اهمیت زیادی دارد که هنگام جستجوی عبارات خاصی سایت آن شرکت در صفحه اول جستجوی گوگل قرار بگیرد. مثلا یک شرکت فروشنده لپ تاپ خیلی علاقه دارد وقتی کلمه لپ تاپ توی گوگل جستجو می شود سایت آن ها هم در صفحه اول لیست شود. خیلی از شرکت ها حاظر هستند سالانه میلیون ها دلار خرج کنند تا چنین اتفاقی بیافتد، حتی رشته ای با عنوان Search Engine Optimization یا SEO در همین راستا شکل گرفته است. حالا به این مطلب فکر کنید که اگر الگوریتم رتبه بندی در گوگل و موتور های جستجوی دیگر طوری بود که به آسانی می شد آن را تحت تاثیر قرار داد، چه اتفاقی می افتاد. هر کلمه ای را که توی گوگل جستجو می کردید، چند صفحه چرت و پرت که بیشتر آنها سایت شرکت ها بود برای شما برگردانده می شد!

یکی از نکات جالب دیگر این است که الگوریتم رتبه بندی صفحات در گوگل طوری هست که اگر n صفحه توی گوگل ایندکس شود، برای بدست آوردن رتبه هر صفحه باید یک n معادله n مجهول حل شود، و به این نکته هم توجه کنید که این n حداقل چیزی حدود 6 یا 7 میلیارد هست!

البته الگوریتم Page Ranking فعلی گوگل ترکیبی از چند الگوریتم هست که تقریبا سرّی هستند ولی یکی از مهمترین آنها همین الگوریتمی هست که در این مقاله توضیح داده شده.

راستش را بخواهید می خواستم به چند چیز دیگر هم اشاره بکنم ولی مثل اینکه دوباره دارم زیاد می نویسم. برای همین هم بقیه مطالب را می گذارم برای دفعه ی بعد.

پانویس:

*** این را هم بگویم برای اینکه کمی بخندید، چند روز پیش یکی از دوستان می گفت در رسم الخط جدید فرهنگستان گفته اند به جای "محتوی" بنویسید "محتوا"، خیلی خوشحال شدم چون من تا کلاس سوم راهنمایی محتوی را می خواندم mahtooy.

Saturday, May 12, 2007

volatile

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

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

1. تمام پردازنده ها از یک حافظه پنهان مشترک استفاده کنند، در این حالت هنگامی که یک پردازنده مقدار یک متغیر را تغییر می دهد و بلافاصله پردازنده دیگر مقدار آن را می خواند، مقدار خوانده شده با مقدار نوشته شده یکسان است.

2. هر یک از پردازنده ها حافظه پنهان خودشان را داشته باشند، در این حالت فرض کنید قرار است دو پردازنده مختلف به متغیر مشترک X دسترسی داشته باشند و این متغیر در حافظه پنهان هر دو پردازنده قرار دارد(دو مکان متفاوت). حال فرض کنید پردازنده اول مقدار X را در حافظه پنهان خود تغییر دهد و پردازنده دوم آن را از حافظه پنهان خود بخواند. از آنجایی که خواندن و نوشتن در دو مکان مختلف انجام شده ممکن است این مقدار خوانده شده با مقدار نوشته شده متفاوت باشد.

استفاده از حافظه پنهان مشترک در کامپیوترهایی که تعداد زیادی پردازنده دارند امکان پذیر نیست، چرا که در اینصورت به دلیل تعداد زیاد مراجعات به حافظه پنهان، خود حافظه پنهان به گلوگاه کارایی تبدیل شده و عملا خاصیت خود را از دست می دهد. از این رو اغلب در معماری SMP ها از شکل دوم و یا ترکیبی از شکل اول و دوم استفاده می شود.

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

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

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

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

البته دقت کنید که بجای استفاده از volatile در بسیاری از موارد می توانید از کلمه کلیدی synchronized هم استفاده کنید. همچنین دوباره بر این نکته تاکید می کنم که مشکلی که در اینجا مطرح شد حتی در ماشین های تک پردازنده هم ممکن است اتفاق بیفتد(اینجا را ببینید).

در هر حال نوشتن برنامه های Multithreaded توجه و مطالعه زیادی را می طلبد. مشکل اصلی در این برنامه ها این است که اشکالات موجود تنها در بعضی موارد خاص خود را نشان می دهد، به همین دلیل رفع اشکال آنها به سختی انجام می شود. آشنایی کامل بر مفاهیم Multithreading و تعاریف زبانی که با آن برنامه می نویسید می تواند باعث کاهش این مشکلات شود.