Saturday, February 23, 2008

Using Aspectj and Java Annotations to Try Again

We are working on a program that interacts with a hardware device using a com port for some months. After implementing many parts of software, we found that the communication channel is not as reliable as we expected, so we decided to add some "Try Again" functionality to our code. You have seen the "Try Again" dialog many times, but have you ever taught of how to implement one?

All you need is to invoke a method, if an exception occurs ask the user "Try Again?" and if the answer is "Yes" reinvoke the method. At first it seems so simple to me but after playing with some of OO design patterns I realized that many lines of code should be modified to implement the functionality in OO, so I decided to play a little AOP.

Here is the solution I found:

The first thing we need is to specify what methods must be tried again, Thanks to Java 5 annotations, this is very easy to tag some methods, so the first thing we need is a TryAgain Java annotation:

 
 

package com.blogspot.zoftware.aspects;

 
 

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 
 

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface TryAgain {

int count() default 2;

boolean interactive() default true;

}

 
 

The count parameter specifies how many times the method should be reinvoked and the interactive parameter specifies if the user should be asked to try again or not. The second thing we need is an aspect which reinvokes the annotated methods, there are many AOP implementations in the java world but I like the annotation based aspectj the most, as it is very simple and supports standard java syntax, here is the code for the aspect:

 
 

package com.blogspot.zoftware.aspects;

 
 

import java.lang.reflect.Method;

 
 

import javax.swing.JOptionPane;

 
 

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.reflect.MethodSignature;

 
 

@Aspect

public class TryAgainAspect {

 
 

@Around("call(@TryAgain * *..*(..))")

public Object retry(ProceedingJoinPoint jp) throws Throwable{

Method method = ((MethodSignature)jp.getSignature()).getMethod();

TryAgain annotation = method.getAnnotation(TryAgain.class);

Throwable err = null;

 
 

for (int i = 0; i < annotation.count(); i++) {

try {

return jp.proceed();

} catch (Throwable e) {

err = e;

if(annotation.interactive() && !askRetry(e)) {

break;

}

}

}

 
 

throw err;

}

 
 

private boolean askRetry(Throwable e) {

String msg = "The following error occured:\n" + e + "\nRetry?";

return JOptionPane.showConfirmDialog(null, msg) == JOptionPane.YES_OPTION;

}

}


 

 
 

The retry advice, reinvokes every method which is tagged with @TryAgain annotation if an exception occurs (at most count times), so all you need to use this mechanism is to tag the methods that should be reinvoked on failures. Here is a sample usage:

 
 

package com.blogspot.zoftware.demo;

 
 

import com.blogspot.zoftware.aspects.TryAgain;

 
 

public class Foo {

 
 

@TryAgain(count = 3)

public void oftenFails() {

if(Math.random() < 0.6) {

throw new RuntimeException("Sorry, Failed!");

}

}

 
 

public static void main(String[] args) {

new Foo().oftenFails();

System.out.println("Passed");

}

}


 

 
 

The oftenFails method is the method that should be reinvoked, so I annotated it using @TryAgain. To run the code you need aspectj libraries (download here); you can use either dynamic (load time) or static weaving. To use load time weaving, place the following piece of XML into aop.xml under META-INF folder, then run the Foo class with -javaagent:aspectjweaver.jar command line argument.

 
 

<aspects>

<aspect name="com.blogspot.zoftware.aspects.TryAgainAspect" />

</aspects>


 

The mixture of Annotations and AspectJ is a powerful tool to solve many common software engineering problems.

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.