قيود القيمة [فحص الكود 2]

الإعلانات

التعليقات التوضيحية لقيود القيمة

 

 

قيود القيمة

 

التعليقات التوضيحية لـ قيود القيمة


إستخدم التعليقات التوضيحية IntRange@FloatRange@ و Size@ للتحقق من صحة قيم الباراميترات التي تم تمريرها.

كلٍ من IntRange@ و FloatRange@ تكونان أكثر فائدة عند تطبيقهما على الباراميترات التي من المحتمل أن يتلقى المستخدمون المجال الخاطئ بها.

التعليق التوضيحي IntRange@ يتحقق من كون قيمة العدد الصحيح أو الباراميتر الطويل، تقع ضمن مجال معين.

المثال التالي يضمن إحتواء الباراميتر المسيطر “alpha” على قيمة عدد صحيح من 0 إلى 255:

KOTLIN

fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }

JAVA

public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }

التعليق التوضيحي FloatRange@ يتحقق من أن قيمة الباراميتر عائم float أو مزدوج double، تقع ضمن مجال محدد، من قيم النقاط العائمة.

المثال التالي يضمن إحتواء الباراميتر المسيطر “alpha” على قيم عائمة من 0.0 إلى 1.0:

KOTLIN

fun setAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) {...}

JAVA

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}

التعليق التوضيحي Size@ يتحقق من حجم مجموعة أو مصفوفة، كما يتحقق أيضاً من طول السلسلة. التعليق التوضيحي Size@ يمكن إستخدامه للتحقق من الخواص التالية:

  • الحد الأدنى للحجم (مثل (Size(min=2@)
  • الحد الأعلى للحجم (مثل (Size(max=2@)
  • الحجم الدقيق (مثل (Size(2@)
  • الرقم الذي يجب مضاعفة الحجم به (مثل (Size(multiple=2@)

على سبيل المثال، (Size(min=1@ تتحقق عما إذا كانت المجموعة غير فارغة، و (Size(3@ تتحقق من أن المصفوفة تحتوي على ثلاث قيم بالضبط.

المثال التالي يضمن إحتواء مصفوفة الموقع location على عنصر واحد على الأقل:

KOTLIN

fun getLocation(button: View, @Size(min=1) location: IntArray) {
    button.getLocationOnScreen(location)
}

JAVA

void getLocation(View button, @Size(min=1) int[] location) {
    button.getLocationOnScreen(location);
}

 

قيود القيمة

اذونات التعليق التوضيحي


إستخدم التعليق التوضيحي RequiresPermission@ للتحقق من صحة أذونات مستدعي الدالة. للتحقق من أذونة واحدة من قائمة الأذونات الصحيحة، إستخدم السمة anyOf.

للتحقق من مجموعة من الأذونات، إستخدم السمة allOf. المثال التالي يضع تعليق توضيحي للدالة ()setWallpaper للتأكد من أن مستدعي الدالة يملك الإذن permission.SET_WALLPAPERS:

KOTLIN

@RequiresPermission(Manifest.permission.SET_WALLPAPER)
@Throws(IOException::class)
abstract fun setWallpaper(bitmap: Bitmap)

JAVA

@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;

هذا المثال يتطلب من مستدعي الدالة ()copyFile بأن يكون لديه كلاً من أذونتي القراءة والكتابة لوحدة التخزين الخارجية:

KOTLIN

@RequiresPermission(allOf = [
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE
])
fun copyFile(dest: String, source: String) {
    ...
}

JAVA

@RequiresPermission(allOf = {
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, String source) {
    //...
}

بالنسبة لأذونات الأغراض، قم بوضع متطلبات الإذن في حقل السلسلة، الذي يعرّف، اسم إجراء الغرض:

KOTLIN

@RequiresPermission(android.Manifest.permission.BLUETOOTH)
const val ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE"

JAVA

@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
            "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";

بالنسبة لأذونات موفر المحتوى، والتي تحتاج إلى أذونات منفصلة للوصول، إلى القراءة والكتابة، قم بإحاطة كل متطلب إذن بتعليق

توضيحي RequiresPermission.Read@ أو RequiresPermission.Write@:

KOTLIN

@RequiresPermission.Read(RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(RequiresPermission(WRITE_HISTORY_BOOKMARKS))
val BOOKMARKS_URI = Uri.parse("content://browser/bookmarks")

JAVA

@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");

 

قيود القيمة

الأذونات الغير مباشرة

 

عندما تعتمد الإذن على القيمة المحددة، و المقدمة إلى باراميتر الدالة، إستخدم RequiresPermission@ على الباراميتر نفسه، بدون إدراج الأذونات المحددة.

مثال، تستخدم الدالة (startActivity(Intent أذونة غير مباشرة على الغرض الذي تم تمريره للدالة:

KOTLIN

abstract fun startActivity(@RequiresPermission intent: Intent, bundle: Bundle?)

JAVA

public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle)

عندما تستخدم أذونات غير مباشرة، تقوم أدوات البناء بإجراء تحليل لتدفق البيانات، للتحقق مما إذا كانت المعطيات argument

التي تم تمريرها إلى الدالة، تحتوي على أي تعليقات توضيحية RequiresPermission@.

 

ثم تقوم بفرض أي تعليقات توضيحية موجودة، من الباراميتر على الدالة نفسها. في المثال (startActivity(Intent، التعليقات

التوضيحية في فئة الغرض Intent أدت إلى ظهور تحذيرات عن الإستخدامات الغير صحيحة لـ (startActivity(Intent عندما تم

تمرير غرض لا يحتوي على الأذونات المناسبة إلى الدالة، كما هو موضح في الشكل 1.

الشكل 1. التحذير الذي تم إنشاؤه من خلال التعليق التوضيحي للأذونة الغير مباشرة على الدالة (startActivity(Intent.

 

تقوم أدوات البناء بإنشاء تحذير على (startActivity(Intent من خلال التعليق التوضيحي على “اسم إجراء” الغرض المطابق، في فئة الغرض Intent.

KOTLIN

@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
const val ACTION_CALL = "android.intent.action.CALL"

JAVA

@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";

 

إذا لزم الأمر، يمكنك إستبدال RequiresPermission@ بـ RequiresPermission.Read@ و\أو RequiresPermission.Write@، عند إضافة تعليق توضيحي على باراميتر إحدى الدوال.

مع ذلك، بالنسبة للأذونات الغير مباشرة، لا ينبغي إستخدام RequiresPermission@ بالتزامن مع أي من التعليقات التوضيحية لأذونات القراءة أو الكتابة.

 

 

قيود القيمة

 

التعليقات التوضيحية للقيم المرجعة


إستخدم التعليق التوضيحي CheckResult@ للتحقق من أن النتيجة أو القيمة المرجعة للدالة، مستخدمة بالفعل، بدلاً من وضع

تعليق توضيحي لكل دالة غير خالية، بإستخدام CheckResult@، قم بإضافة تعليق توضيحي لتوضيح النتائج الخاصة بالدوال التي قد تبدو مربكة.

مثال، غالباً ما يُخطئ مطوري الجافا الجدد، في الإعتقاد بأن ()String>.trim> تقوم بإزالة المسافة من السلسلة الأصلية.

إضافة تعليق توضيحي للدالة بإستخدام علامات CheckResult@ تستخدم ()String>.trim> ، حيثما لا يقوم المستدعي بفعل شيء بالقيمة المرجعة للدالة.

يقوم المثال التالي بوضع تعليق توضيحي للدالة ()checkPermissions للتأكد من أن القيمة المرجعة للدالة، تتم الإشارة إليها بالفعل.

كما يقوم أيضاً بتسمية الدالة ()enforcePermission كدالة يتم إقتراحها للمطور كبديل:

KOTLIN

@CheckResult(suggest = "#enforcePermission(String,int,int,String)")
abstract fun checkPermission(permission: String, pid: Int, uid: Int): Int

JAVA

@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);

 

قيود القيمة

 

التعليقات التوضيحية CallSuper


إستخدم التعليق التوضيحي CallSuper@ للتحقق من أن دالة التجاوز، تقوم بإستدعاء التنفيذ الفائق super implementation للدالة.

يقوم المثال التالي بوضع تعليق توضيحي للدالة ()onCreate للتأكد من أن أي تنفيذات للدالة المتجاوزة، تقوم بإستدعاء التنفيذ الفائق ()super.onCreate:

KOTLIN

@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
}

JAVA

@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}

 

قيود القيمة

 

التعليق التوضيحي لتعريف النوع Typedef


إستخدم التعليقات التوضيحية IntDef@ و StringDef@ لكي تتمكن من إنشاء تعليقات توضيحية تعدادية، من مجموعات العدد

الصحيح integer و السلسلة string، للتحقق من صحة الأنواع الأخرى، للإشارات المرجعية للكود.

 

التعليقات التوضيحية Typedef تتأكد بأن “باراميتر، قيمة مرجعة، أو حقل” محدد\ة، يُشير إلى مجموعة معينة من الثوابت.

كما إنها تقوم بتمكين عملية إكمال الكود، لتقديم الثوابت المسموح بها تلقائياً. 

 

التعليقات التوضيحية Typedef تستخدم interface@ للإعلان عن نوع التعليق التعدادي الجديد. التعليقات التوضيحية IntDef@ و

StringDef@ ، بالإضافة إلى Retention@ تضيف تعليق توضيحي جديد و مهم من أجل تحديد النوع التعدادي.

 

التعليق التوضيحي (Retention(RetentionPolicy.SOURCE@ يخبر المحول البرمجي compiler، بعدم تخزين بيانات التعليق التوضيحي التعدادي في الملف class.

 

يوضح المثال التالي خطوات إنشاء تعليق توضيحي، يضمن بأن القيم التي تم تمريرها كباراميتر للدالة، تُشير إلى إحدى الثوابت المحددة:

KOTLIN

import android.support.annotation.IntDef
//...
// Define the list of accepted constants and declare the NavigationMode annotation
@Retention(AnnotationRetention.SOURCE)
@IntDef(NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS)
annotation class NavigationMode

// Declare the constants
const val NAVIGATION_MODE_STANDARD = 0
const val NAVIGATION_MODE_LIST = 1
const val NAVIGATION_MODE_TABS = 2

abstract class ActionBar {

    // Decorate the target methods with the annotation
    // Attach the annotation
    @get:NavigationMode
    @setparam:NavigationMode
    abstract var navigationMode: Int

}

JAVA

import android.support.annotation.IntDef;
//...
public abstract class ActionBar {
    //...
    // Define the list of accepted constants and declare the NavigationMode annotation
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
    public @interface NavigationMode {}

    // Declare the constants
    public static final int NAVIGATION_MODE_STANDARD = 0;
    public static final int NAVIGATION_MODE_LIST = 1;
    public static final int NAVIGATION_MODE_TABS = 2;

    // Decorate the target methods with the annotation
    @NavigationMode
    public abstract int getNavigationMode();

    // Attach the annotation
    public abstract void setNavigationMode(@NavigationMode int mode);
}

عند إنشائك لهذا الكود، يتم إنشاء تحذير إذا كان باراميتر الوضع، لا يشير إلى إحدى الثوابت المحددة (NAVIGATION_MODE_STANDARD

أو NAVIGATION_MODE_LIST أو NAVIGATION_MODE_TABS).

يمكنك أيضاً دمج IntDef@ و IntRange@ للإشارة إلى أن عدد صحيح، يمكنه أن يكون إما مجموعة مُعطاة من الثوابت، أو قيمة ضمن المجال.

 

تمكين دمج الثوابت مع الأعلام

 

إذا أمكن للمستخدمين دمج الثوابت المسموح بها مع الأعلام، (مثل |، &، ^ وما إلى ذلك)، فيمكنك تعيين تعليق توضيحي

بإستخدام سمة الأعلام flag للتحقق مما إذا كان الباراميتر أو القيمة المرجعة يشيران إلى نمط صالح.

يقوم المثال التالي بإنشاء التعليق التوضيحي DisplayOptions مع قائمة بثوابت _DISPLAY الصالحة:

KOTLIN

import android.support.annotation.IntDef
...

@IntDef(flag = true, value = [
    DISPLAY_USE_LOGO,
    DISPLAY_SHOW_HOME,
    DISPLAY_HOME_AS_UP,
    DISPLAY_SHOW_TITLE,
    DISPLAY_SHOW_CUSTOM
])
@Retention(AnnotationRetention.SOURCE)
annotation class DisplayOptions
...

JAVA

import android.support.annotation.IntDef;
...

@IntDef(flag=true, value={
        DISPLAY_USE_LOGO,
        DISPLAY_SHOW_HOME,
        DISPLAY_HOME_AS_UP,
        DISPLAY_SHOW_TITLE,
        DISPLAY_SHOW_CUSTOM
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayOptions {}

...

عندما تُنشئ كود به علامة توضيحية، يتم إنشاء تحذير إذا كان الباراميتر الزخرفي أو القيمة المرجعة لا يُشيران إلى نمط صالح.

 

 

التعليق التوضيحي Keep


التعليق التوضيحي Keep@ يضمن بأن الفئة أو الدالة الذين أُضيف لهما تعليق توضيحي، لا تتم إزالتهما عند تقليص الكود أثناء وقت التشغيل.

عادة يتم إضافة هذا التعليق التوضيحي، إلى الدوال والفئات التي يتم الوصول إليها من خلال الإنعكاس reflection لمنع المحول

البرمجي compiler من التعامل مع الكود كما لو كان غير مستخدم.

 

تحذير: الفئات والدوال التي تقوم بالتعليق عليها بإستخدام Keep@ تظهر دائماً في APK تطبيقك، حتى لو لم تُشير إلى هذه الدوال والفئات  بداخل منطق تطبيقك.

للحفاظ على صغر حجم تطبيقك، ضع في إعتبارك ما إذا كان من الضروري الإحتفاظ بكل تعليق يحمل Keep@ في تطبيقك أم لا.

إذا كنت تستخدم الإنعكاس للوصول إلى الدوال والفئات ذات التعليق التوضيحي، فإستخدم الشرط if- في قواعد ProGuard الخاصة بك، مع تحديد الفئات التي تقوم بإجراء إستدعاءات الإنعكاس.

لمزيد من المعلومات حول كيفية تقليص الكود، وتحديد الأكواد التي يجب ألا تُحذف، راجع تقليص كودك ومصادرك.

 

 

التعليق التوضيحي رؤية الكود


إستخدم التعليقات التوضيحية التالية، للدلالة على إمكانية رؤية أجزاء معينة من الكود، مثل الدوال، الفئات، الحقول، أو الحزم.

إجراء الرؤية للإختبار

 

التعليق التوضيحي VisibleForTesting@ يشير إلى أن كون الدالة ذات التعليق، أكثر وضوحاً من المعتاد، يجعل الدالة قابلة للإختبار.

يحتوي هذا التعليق التوضيحي على وسيط\معطى otherwise إختياري، يتيح لك تحديد ما يجب أن تكون عليه رؤية الدالة، إن لم

يكن لغرض جعلها مرئية من أجل الإختبار. يستخدم فحص Lint الوسيط otherwise لفرض الرؤية المقصودة.

 

في المثال التالي، تكون الدالة ()myMethod عادةً خاصة private، لكنها حزمة خاصة للإختبارات. بإستخدام تعيين VisibleForTesting.PRIVATE التالي

يعرض فحص lint رسالة، إذا تم إستدعاء هذه الدالة من خارج السياق المسموح به، من قبل الوصول الخاص private، كمثال من وحدة برمجة مختلفة compilation.

KOTLIN

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
fun myMethod() {
    ...
}

JAVA

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
void myMethod() { ... }

يمكنك أيضاً تحديد (VisibleForTesting(otherwise =VisibleForTesting.NONE@ للإشارة إلى وجود دالة للإختبار فقط. هذا النموذج

مشابه لإستخدام  (RestrictTo(TESTS@. كلاهما يؤدي فحص لينت نفسه.

 

حصر API

 

التعليق التوضيحي RestrictTo@ يشير إلى أن الوصول إلى API ذو التعليق التوضيحي (الحزمة، الفئة، أو الدالة) محصور كما يلي.

 

الفئات الفرعية

 

إستخدم نموذج التعليق التوضيحي (RestrictTo(RestrictTo.Scope.SUBCLASSES@ لتقييد وصول API إلى الفئات الفرعية فقط.

فقط الفئات التي تقوم بتوسيع الفئة ذات التعليق، يمكنها الوصول إلى الـ API هذه. محول جافا protected ليس مقيداً بما يكفي،

لأنه يسمح بالوصول من الفئات التي ليس لها علاقة والموجودة بداخل نفس الحزمة.

 

أيضاً، هناك حالات حيث تريد فيها ترك الدالة public، من أجل التوافق المستقبلي، لأنه لا يمكنك أبداً إنشاء protected سابق، و تجاوز الدالة public.

ولكنك ترغب في توفير تلميح، بأن الفئة معدة للإستخدام بداخل الفئة، أو من الفئات الفرعية، فقط.

 

 

المكتبات

 

إستخدم نموذج التعليق التوضيحي (RestrictTo(RestrictTo.Scope.GROUP_ID@ لتقييد وصول API إلى مكتباتك فقط.

يمكن فقط للمكتبة الخاصة بكودك، الوصول إلى API ذو التعليق التوضيحي.

 

لا يسمح لك هذا فقط تنظيم الكود الخاص بك، في أي تسلسل هرمي للحزمة التي تريدها، بل أيضاً يسمح بمشاركة الكود بين مجموعة من المكتبات ذات الصلة.

 

هذا الخيار متاح بالفعل لمكتبات الدعم، التي تحتوي على الكثير من أكواد التنفيذ، الغير مُعدة للإستخدام الخارجي، ولكن يجب أن

تكون عامة public لمشاركتها عبر مختلف مكتبات الدعم التكميلية.

 

ملاحظة: يتم الآن وضع تعليق توضيحي على فئات وحزم مكتبة دعم اندرويد بإستخدام (RestrictTo (GROUP_ID@، مما يعني أنه في حالة إستخدامك لفئات التنفيذ هذه بالخطأ، يحذرك فحص لينت من أنه لا يُوصى بفعل هذا .

 

الإختبار

 

إستخدم التعليق التوضيحي (RestrictTo(RestrictTo.Scope.TESTS@ لمنع المطورين الآخرين من الوصول إلى API الإختبار الخاص بك.

يمكن فقط لكود الإختبار الوصول إلى API ذات التعليق التوضيحي. وهذا يمنع المطورين الآخرين من إستخدام API للتطوير، والتي تنوي إستخدامها لأغراض الإختبار فقط.

 


للإطلاع على المقال باللغة الإنجليزية أضغط هنا.

الإعلانات

اترك رد