همه چیز درباره annotation ها

استاندارد

at-symbol-1113fg-v1-65

قطعا هممون تو روند کد نویسیمون بارها و بارها از annotation ها استفاده کردیم ، گاهی از annotaion های پیش فرضی که خود جاوا در اختیارمون گذاشته مثل override@ یا depricate@ یا از annotation هایی که فریمورک یا کتابخونه‌ای که باهاش کار میکنیم در اختیارمون قرار میده .

از بحث اینکه چه جاهایی از اونا استفاده کردیم و میکنیم بگذریم، میرسیم به اینکه اصن annotation ها چی هستن و چجوری میتونیم یه annotation دلخواه برای استفاده خودمون بنویسیم ؟

annotation  توی داکیمونت oracle به عنوان یک فرم از meta data معرفی شده که اطلاعاتی درباره برنامه رو وارد کدهامون میکنه ولی خودش جزیی از برنامه نیست . از annotation ها میشه در زمان اجرای برنامه یا در زمان توسعه استفاده کرد همینطور compiler از annotation ها برای تشخیص مواردی مثل متدهای override شده ، خطا ها و هشتارها استفاده میکنه . ولی نکته مهم اینکه annotation ها چطور کار میکنن ؟ در ادامه با یه مثال و ساختن یه annotation دلخواه سعی میکنم جواب این سوال رو توضیح بدم .

سناریویی که پیش رو داریم  :

فرض کنید میخوایم به وسیله annotation ها در کلاس‌های entity  فیلدهایی که باید در دیتابیس ذخیره بشن ، کلید اصلی و فیلدهای not null رو مشخص کنیم  و با توجه به این اطلاعات جداول مورد نیازمون رو بسازیم .

روند انجام :

در مرحله اول لازمه با توجه به نیازهایی که گفته شد یه annotation دلخواه برای خودمون بسازیم .

برای ساخت یک annotation باید اسم کلاس ( اسم annotation ) رو بعد از interface@ قرار بدیم و مواردی مثل جایی که قراره این annotation مورد استفاده قرار بگیره ( متد ، فیلد ، کلاس ) ، زمانی که annotation مورد استفاده قرار میگیره و … رو مشخص کنیم .

در کد بالا به وسیله (Target(ElementType.FIELD مشخص میشه که هدف این annotation قرار گرفتن در سطح فیلدها هست و (Retention(RetentionPolicy.RUNTIME@ نشون میده که این annotation در زمان اجرای کدها مورد استفاده قرار میگیره .

isPrimary این امکان رو به ما میده که بتونیم فیلد مورد نظرمون رو برای قرارگرفتن به عنوان کلید اصلی مشخص کنیم . همینطور با قرار دادن dbColumn برابر false میتونیم مشخص کنیم که نمیخوایم این فیلد رو به عنوان ستون در دیتابیسمون ذخیره کنیم .

در مرحله بعد میرسیم به استفاده از این annotation هامون تو کلاس Users که در ادامه خواهیم ساخت .

با توجه به کد بالا فیلد id قراره به عنوان primary key ما مورد استفاده قرار بگیره . و فیلد email توی جدول ذخیره نشه .

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

کلاس بالا از SQLiteOpenHelper ارث برده و توی اون متد createTable کار پردازش annotation ها و ساخت query مناسب برای ساختن جداول رو بر عهده داره . توی این متد ابتدا فیلدهایی که نباید در جدول ذخیره شوند مورد برسی قرار میگیرند سپس با توجه به کلید اصلی بود یا not null بودن هر فیلد query مورد نظر تغییر میکند و در اخر هم query ساخته شده به وسیله کد (sqLiteDatabase.execSQL(script اجرا خواهد شد و جدول مورد نظر ساخته میشه. همنطور باید بگم توی این متد به وسیله کد  (field.isAnnotationPresent(DbColumn.class مشخص میکنیم که آیا برای فیلد مورد نظر annotation دلخواه ما وجود داره یا نه و به وسیله (field.getAnnotation(DbColumn.class میتونیم annotation قرار گرفته برای فیلد مورد نظر رو بگیریم .

مثال بالا جهت نمایش نحوه کارکرد annotation ها نوشته شده ، اگه شما هم کاربردها و ایده‌های جالبی برای استفاده ازشون پیدا کردید خوشحال میشم به منم بگید .

چگونه توی جاوا کلاس‌های ترتمیز‌تری داشته باشیم

استاندارد

من هم مثل خیلیا سعی میکنم توی کدهایی که میزنم از اصول و مفاهیم شی گرایی استفاده کنم و تنها نکته‌ای که این وسط تاحدی واسم آزار دهنده بوده (البته تا دیروز) این بود که وقتی برای یه کلاس با تعداد متغیرهای زیاد میخواستم توابع getter و setter  بنویسم کد کلاسهام خیلی شلوغ و بهم ریخته میشد! اوضاع وقتی وخیمتر میشد که چندتا constractor و toString و equal و  … هم به کلاس اضافه میشد . تا این که دیروز همکارم یه کتابخونه خیلی خوب بهم معرفی کرد که بوسیله annotation ها تمام کارای که تو بالا بهشون اشاره کردم رو بدون شلوغ کاریهای روش معمول انجام میده، البته بجز کارهایی که گفته شد خیلی کارای باحال دیگه هم انجام میده . مثل cleanup@ که با استفاده از اون برای کلاس‌هایی که متد close توی اونها پیاده سازی شده (کلاس‌های cloasable مثل InputStream  و OutputStream ‌و یا کلاس‌های مربوط به دیتابیس )،به شما این اطمینان رو میده که قبل از خارج شدن از scope کنونی که شما توی اون هستید، این متد(close ) رو به وسیله try/finally فراخوانی کنه . به خواندن ادامه دهید