نمایش نتایج 1 تا 10 از 10

نام تاپیک: annotation چیست و چطوری میشه annotation های شخصی نوشت

  1. #1

    annotation چیست و چطوری میشه annotation های شخصی نوشت

    سلام دوستان. در مورد این سوال یه کم اگه میشه توضیح بدید و اینکه چطوری میتونم خودم از اونا بنویسم برای کارای خودم

  2. #2
    کاربر دائمی آواتار ahmad.mo74
    تاریخ عضویت
    مرداد 1393
    محل زندگی
    تهران
    پست
    437

  3. #3
    کاربر دائمی آواتار -سیّد-
    تاریخ عضویت
    فروردین 1393
    محل زندگی
    تهران
    پست
    233

    نقل قول: annotation چیست و چطوری میشه annotation های شخصی نوشت

    من یه توضیح کلی و سریع بدم:
    ‫Annotation در واقع meta-data ای هست که شما روی کد اضافه می‌کنید. مثلاً یه تابع تعریف می‌کنید، می‌تونید annotate اش کنید که این تابع فلان کار رو می‌کنه. مثال بسیار کاربردیش توی کتابخونه‌ی hibernate هست، که شما اونجا متغیرهاتون رو annotate می‌کنید و این کتابخونه به کمک annotation های شما متوجه می‌شه که چطوری باید کلاس‌ها رو به جداول پایگاه داده map کنه.
    نحوه‌ی استفاده ازشون هم به کمک Reflection هست. شما می‌تونید از یه کلاس یا فیلد یا تابع، فهرست annotation هاش رو بگیرید و پردازش کنید.

    اگه annotation نباشه، مجبورید این داده‌ها رو مثلاً توی یه فایل کانفیگ بذارید، یا توی یه Map قرار بدید. خوبی‌ای که annotation داره اینه که داخل کدتون و دقیقاً در کنار متغیر یا تابع یا کلاس مربوطه هست و این هم باعث می‌شه که خوانایی کد به شدت بالا بره، و هم باعث می‌شه چیزی از قلم نیافته (این خیلی معموله که آدم یه چیزی رو یادش بره توی config بذاره، یا توی Map بنویسه).

  4. #4

    نقل قول: annotation چیست و چطوری میشه annotation های شخصی نوشت

    دستتون درد نکنه. یه مثال مفید هم میتونید برای واضح تر شدن قضیه کاربرد اون بزنید؟ ممنون میشم برا اینکه بفهمم واقعا چه کاربرد اساسی و نقش خوبی بازی میکنه

  5. #5
    کاربر دائمی آواتار -سیّد-
    تاریخ عضویت
    فروردین 1393
    محل زندگی
    تهران
    پست
    233

    نقل قول: annotation چیست و چطوری میشه annotation های شخصی نوشت

    خوب جا داره من یه مشق به شما بدم!

    فرض کنید یه سایت دارید، که توش چندین کار (action) مختلف می‌شه انجام داد. مثلاً ساده‌اش می‌شه این که می‌شه توش یه کاربر اضافه کرد، فهرست کاربرا رو دید، یه کاربر رو ویرایش کرد، و یه کاربر رو حذف کرد (عملیات CRUD).
    پس تا اینجا یه کلاس داریم مثلاً به نام MyController که توش ۴ تا تابع بالا هست (برای سادگی کار، توابع رو static گرفتم):

    public class MyController {
    public static void createAction() {
    ...
    }

    public static void listAction() {
    ...
    }

    public static void editAction() {
    ...
    }

    public static void deleteAction() {
    ...
    }
    }


    حالا می‌خوایم یه تابع route داشته باشیم که action رو به عنوان ورودی بگیره، و action مورد نظر رو انجام بده (تابع متناظرش رو فراخوانی کنه). این کار رو توسط Reflection می‌شه اینطوری انجام داد:

    public void route(String action) throws Exception {
    Method m = MyController.class.getDeclaredMethod(action + "Action");
    m.invoke(null);
    }

    (خیلی ساده‌سازی توی کد انجام دادم (و یه سری از best practice ها رو نقض کردم) که بشه مثال رو راحت جلو برد، لطفاً خیلی توجه نکنید!)

    تا اینجای کار همه چیز خوبه!

    حالا فرض کنید توی این سایت می‌خوایم سطوح دسترسی و Access Control تعریف کنیم. نقش‌هامون هم از قبل مشخص هستند:
    • admin: به تمام action هایی که گفتم دسترسی داره.
    • operator: می‌تونه فهرست کاربرا رو ببینه و هر کاربری رو ویرایش کنه.
    • guest: فقط می‌تونه فهرست کاربرا رو ببینه.

    حالا می‌خوایم این سطوح دسترسی رو توی کد تابع route اعمال کنیم و اگه یکی با سطح دسترسی نامناسب اومد سراغ یه تابع، یه Exception خاص (مثلاً AccessDeniedException) پرتاب کنیم. یعنی تعریف تابع route به این صورت تغییر می‌کنه:

    public void route(String action, String role) throws Expection {
    ...
    }


    خوب بسم‌الله! لطفاً این تابع رو پیاده‌سازی کنید و در جواب این پست بنویسید. (لطفاً دوستانی که جواب نهایی رو بلدن دخالت نکنن! پیشاپیش ممنونم!)
    آخرین ویرایش به وسیله -سیّد- : شنبه 24 مرداد 1394 در 23:10 عصر دلیل: فرمت کردن

  6. #6

    نقل قول: annotation چیست و چطوری میشه annotation های شخصی نوشت

    ممنون. درست نفهمیدم. برای تابع آخری یعنی یه annonate تعریف کنم؟ یا بر اساس اون role بگم که روت چطور کار کنه؟

  7. #7
    کاربر دائمی آواتار -سیّد-
    تاریخ عضویت
    فروردین 1393
    محل زندگی
    تهران
    پست
    233

    نقل قول: annotation چیست و چطوری میشه annotation های شخصی نوشت

    نه شما فعلاً annotation رو بی‌خیال شو! معمولی بنویس.

  8. #8

    نقل قول: annotation چیست و چطوری میشه annotation های شخصی نوشت

    خوب راستش تو این موارد جاوا زیاد نیستم. الان چیزی که به ذهنم میرسه این هستش که ما روی role یه سوییچ بندازیم. یا میشه سطوح دسترسی رو بزاریم داخل آرایه و از

    Arrays.asList(array).contains(value)

    استفاده کنیم ببینیم چی هستش ولی این خوب بدترین حالت ممکنی هستش که به این شکل میشه ازش استفاده کرد. از جاوا من تو اندروید استفاده میکنم برای همین دیدی به این قضیه ندارم. سرچ هم کردم ولی چیزی پیدا نکردم. ببخشید

  9. #9
    کاربر دائمی آواتار -سیّد-
    تاریخ عضویت
    فروردین 1393
    محل زندگی
    تهران
    پست
    233

    نقل قول: annotation چیست و چطوری میشه annotation های شخصی نوشت

    بسیار عالی! من دنبال همین بودم (همیشه نباید مشق رو یه جوری طرح کرد که طرف مقابل بتونه کامل حلش کنه! ). البته توی نسخه‌های قبلی جاوا، روی String نمی‌شد switch گذاشت، و مجبور بودیم با یه مشت if-else حلش کنیم.
    ولی روش دومتون خوبه. من یه کم دقیق‌ترش می‌کنم:
    می‌تونیم برای هر action، یه آرایه داشته باشیم از نقش‌هایی که بهش دسترسی دارن، و بعد بررسی کنیم که آیا نقش مورد نظر توی آرایه‌ی مربوط به action مورد نظر موجود هست یا نه (البته به طور کلی برای بررسی کردن موجود بودن یه المان توی یه فهرست، بهتره از HashSet به جای آرایه یا List استفاده کنیم که با سرعت بالا جوابمون رو می‌ده). این Map رو هم به صورت static یه بار می‌سازیم که هر دفعه بتونیم توش نگاه کنیم. پس می‌شه اینطوری:

    ...
    private static final Map<String, Set<String>> ACL = new HashMap<String, Set<String>>();

    static {
    ACL.put("create", new HashSet<String>(Arrays.asList("admin")));
    ACL.put("list", new HashSet<String>(Arrays.asList("admin", "operator", "guest")));
    ACL.put("edit", new HashSet<String>(Arrays.asList("admin", "operator")));
    ACL.put("delete", new HashSet<String>(Arrays.asList("admin")));
    }

    public void route(String action, String role) throws Expection {
    if (!ACL.get(action).contains(role))
    throw new AccessDeniedException();

    Method m = MyController.class.getDeclaredMethod(action + "Action");
    m.invoke(null);
    }

    این روش به خوبی جواب می‌ده و ما خوشحالیم!

    حالا فرض کنید کد شما بزرگ و بزرگ‌تر شد، و از ۴ تا دونه action هی گسترشش دادید، تا این که شد ۱۰۰ تا action! چی کار باید بکنیم؟ باید دونه به دونه هر action ای که اضافه می‌کنیم، حواسمون باشه که بیایم اینجا هم یه مدخل توی map مون اضافه کنیم. این کار چند تا اشکال داره. یکی این که به خاطر این که این ۲ تا کار از هم مجزا هستن، یعنی action رو یه جا تعریف می‌کنیم و یه جای دیگه باید بیایم کنترل دسترسیش رو اضافه کنیم، کاملاً ممکنه که یادمون بره سطح دسترسی رو اضافه کنیم. یه اشکال دیگه‌اش اینه که اینجا یه کدی داریم که هی بزرگ‌تر و بزرگ‌تر می‌شه! شما اگه مطابق MVC کد بزنید، action های مختلف رو توی controller های مختلف می‌نویسید، ولی دسترسی‌ها همه توی این یه کلاس تجمیع می‌شه و کد به شددددددت ناخوانا می‌شه (تصور کنید از بین صد خط کد دسترسی (که همه شبیه هم هستن!)، بخواین یکی رو ویرایش کنید!).

    یه اشکال بزرگ دیگه که این روش داره، اینه که اینطوری نمی‌تونید یه کتابخونه بسازید که عملیات کنترل دسترسی رو انجام بده. یعنی فرض کنید می‌خواین این روش route کردن رو به صورت کتابخونه در بیارید، و بشه ازش توی جاهای دیگه هم استفاده کرد. یعنی من نفر دوم بتونم با وابستگی به کتابخونه‌ی شما، یه controller جدید با action های custom خودم رو بنویسم و روش بتونم سطوح دسترسی رو کنترل کنم. برای این کار باید به متغیر ACL که اینجا تعریف کردید دسترسی داشته باشم. اگه این متغیر رو public کنید که من بهش دسترسی داشته باشم (یا یه متد add به صورت public static تعریف کنید که بتونم به کمک اون دسترسی‌های مورد نظر خودم رو اضافه کنم)، مشکلی که پیش میاد اینه که می‌تونم بقیه‌ی سطوح دسترسی رو هم دستکاری کنم. یعنی مثلاً می‌تونم این Map رو clear کنم و همه‌ی دسترسی‌ها بپره!

    برای حل این ۲ مشکل، می‌تونیم از annotation استفاده کنیم. چه جوری؟ یه Annotation تعریف می‌کنیم به نام AccessControl، که توش اسم role مورد نظر هست:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface AccessControl {
    String[] value() default "guest";
    }

    اولین خط (Retention) برای این هست که به JVM بگیم اطلاعات مربوط به این Annotation رو موقع اجرای برنامه حفظ کنه، که بشه بازیابیشون کرد (اگه این رو نگیم، پیش‌فرضش RetentionPolicy.CLASS هست که یعنی موقع اجرا نمی‌شه اطلاعات مربوط به این Annotation رو بازیابی کرد).
    خط دوم یعنی این Annotation رو می‌شه روی method ها به کار برد، نه کلاس‌ها و پارامترها و غیره.
    بعد هم که تعریف خود Annotation هست، که یه المان به صورت آرایه‌ای از String داره (که نقش‌ها توشن).

    خوب حالا بیایم ازش استفاده کنیم. روی هر کدوم از action هایی که تعریف کردیم، یه دونه از این Annotation ها می‌ذاریم:

    public class MyController {
    @AccessControl("admin")
    public static void createAction() {
    ...
    }

    @AccessControl({"admin", "operator", "guest"})
    public static void listAction() {
    ...
    }

    @AccessControl({"admin", "operator"})
    public static void editAction() {
    ...
    }

    @AccessControl("admin")
    public static void deleteAction() {
    ...
    }
    }

    می‌بینید چقدر قشنگ و تمیز شد؟ هر کسی action تعریف می‌کنه، همونجا هم کنارش دسترسی‌هاش رو می‌گه (و کسی نمی‌تونه دسترسی‌های کس دیگه رو عوض کنه).
    دقت کنید که وقتی نوع رو آرایه تعریف می‌کنید، می‌تونید مقدار رو یه دونه بدید، یا آرایه بدید.

    حالا بیاین توی تابع route مون بخونیمش و ازش استفاده کنیم:

    public void route(String action, String role) throws Expection {
    Method m = MyController.class.getDeclaredMethod(action + "Action")
    AccessControl ac = m.getDeclaredAnnotation(AccessControl.class);
    if (ac == null)
    throw new ActionNotAnnotatedException();

    if (!Arrays.asList(ac.value()).contains(role))
    throw new AccessDeniedException();

    m.invoke(null);
    }

    اینجا چند تا نکته هست:
    یکی این که وقتی می‌گیم m.getDeclaredAnnotation و نوع مورد نظر رو بهش می‌دیم، در صورتی که روی تابع annotation ای از نوع مورد نظر ما تعریف نشده باشه، null برمی‌گردونه، که در این صورت داریم یه exception از نوع ActionNotAnnotatedException پرتاب می‌کنیم. پس باز هم ممکنه یه نفر یادش بره روی action اش annotation ما رو بزنه، ولی احتمالش کمتره.
    دوم این که مقدار annotation مورد نظر رو که می‌خونیم، یه آرایه هست از نقش‌ها. بنابراین باید توش بگردیم ببینیم نقش مورد نظرمون توش هست یا نه. البته این کار یه مقدار هزینه داره (چون دونه به دونه توی خونه‌های آرایه رو می‌گرده)، ولی برای مثال ما کافیه.

    در نهایت هم بگم که برای پیاده‌سازی Access Control معمولاً از این روش استفاده نمی‌کنن. اگه بخواین کنترل دسترسی کاملاً پویا داشته باشید، بهترین راه اینه که از پایگاه داده استفاده کنید. ما برای مثال از Annotation این کارو کردیم.
    نکته‌ی دیگه این که معمولاً توی یه پروژه، زیاد با تعریف کردن Annotation سر و کار نداریم و بیشتر ازشون استفاده می‌کنیم. یعنی Annotation رو برای کاربردهای یه مقدار خاص تعریف می‌کنن و بعیده توی یه پروژه‌ی معمولی نیاز بشه که شما برای خودتون یه Annotation تعریف کنید. به عنوان مثال، توی کل بخش‌های جاوایی موتور جستجوی یوز (که خیلی هم زیاد هستند)، من یک جا رو یادم میاد که دوستان برای یه کار خاص Annotation تعریف کرده بودن (دقت کنید! از Annotation زیاد استفاده می‌شه! ولی Annotation جدید زیاد تعریف نمی‌شه).

    نکته در مورد Annotation ها زیاده (مثلاً این که اسم المان رو بذاریم value، یا مقدار پیش‌فرضشون، یا این که توی جاوا ۸ مفهوم Repeated Annotation اضافه شده، ...)، نکات بیشتر رو به منابعی که دوستان معرفی کردن مراجعه کنید.
    آخرین ویرایش به وسیله -سیّد- : دوشنبه 26 مرداد 1394 در 06:58 صبح دلیل: ویرایش املایی

  10. #10

    نقل قول: annotation چیست و چطوری میشه annotation های شخصی نوشت

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

تاپیک های مشابه

  1. سوال: چطوری میشه برنامه های وی بی6 رو تمام صفحه کرد
    نوشته شده توسط mkvisual در بخش برنامه نویسی در 6 VB
    پاسخ: 5
    آخرین پست: چهارشنبه 20 آبان 1388, 09:56 صبح
  2. چطوری میشه منو های ویندوز رو فارسی کرد
    نوشته شده توسط esrafilnl در بخش برنامه نویسی در 6 VB
    پاسخ: 7
    آخرین پست: پنج شنبه 02 آبان 1387, 11:35 صبح
  3. چطوری میشه کانکشن های وصل شده به db رو clear کرد؟
    نوشته شده توسط combo_ci در بخش SQL Server
    پاسخ: 1
    آخرین پست: دوشنبه 26 فروردین 1387, 19:12 عصر
  4. چطوری میشه فایل های اصلی ویندوز اکس پی رو عوض کرد؟
    نوشته شده توسط hex161 در بخش برنامه نویسی در 6 VB
    پاسخ: 14
    آخرین پست: شنبه 03 اردیبهشت 1384, 23:01 عصر

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •