تعلّم البرمجة بلغة كوتلن (73): التحقق من التعليمات Check Instructions

تعلّم البرمجة بلغة كوتلن (73): التحقق من التعليمات Check Instructions
أستمع الى المقال

تتيح لنا لغة كوتلن، كتابة شفرة نظيفة خالية من الأخطاء بقدر الإمكان. حيث تزخر بالعديد من الطرق والمعالجات التي تمكننا من تجنب هذه الأخطاء، بالتالي، قضاء وقت أقل في عمليات التصحيح Debugging لاحقًا. ومن ضمن هذه المعالجات، استخدام دالتي: ()require و ()check. ومهمة هاتين الدالتين هي، التحقق من أنه تم استيفاء الشروط، أثناء فترة عمل البرنامج Runtime. وتستخدم غالبًا، للتحقق من القيم المُرسلة للدوال ونتائجها.

دالة ()require:

تستخدم هذه الدالة في الغالب، للتحقق من القيم المُرسلة للدوال. لذا يتم استخدامها في أول سطر داخل جسم الدوال. عندما يكون الشرط الذي نُرسله للدالة غير صحيح أي false، سترمي الدالة الاستثناء IllegalArgumentException والذي هو فرع من الاستثناء RuntimeException. 

فمثلًا، إذا كان لدينا دالة مهمتها هي التحقق من تسجيل دخول المستخدم للبرنامج:

fun login(user: User): String {

    require(user.username.isNotBlank() 
            && user.password.isNotBlank())

    return "Welcome ${user.username}"
}

ولدينا صنف User ليُمثل كائن المستخدم:

data class User(val username: String, val password: String)

وفي دالة ()main، نقرأ مُدخلات المستخدم: اسم المستخدم username والرقم السري password، عبر دالة ()readln، ثم نُنشئ كائن User جديد باستخدام المُدخلات، ونرسله لدالة ()login.

fun main() {

    println("Enter username:")
    val username = readln()
    println("Enter password:")
    val password = readln()

    println(login(User(username, password)))
}

مهمة دالة ()require المتواجدة داخل دالة ()login، هي التحقق مما إذا كانت مدخلات المستخدم غير فارغة عبر استخدام دالة ()isNotBlank من مكتبة كوتلن القياسية. عندما يدخل المستخدم قيم فارغة، سيتم رمي الاستثناء وإيقاف البرنامج، كما يظهر في الصورة التالية:

كما نرى في الصورة، ادخل المستخدم الـ username ونسي ادخال الرقم السري، وضغط على Enter. عند حدوث خطأ مثل هذا أثناء فترة الـ Runtime، يجب أن يتوقف البرنامج عن العمل. هذا يعطينا الفرصة أن نعالج هذا الاستثناء، قبل إصدار البرنامج واستخدامه فعليًا من قبل المستخدمين.

تخصيص رسالة دالة ()require:

نلاحظ أن رسالة الاستثناء، بها اسم نوع الاستثناء IllegalArgumentException والنص: “Failed requirement.”. هذا هو النص الذي ستعيده الدالة لكل الاستثناءات إذا لم نعمل على تقديم نص خاص بنا. ولأن لدى الدالة معامل آخر وهو من نوع بيانات الدوال، يمكننا أن نرسل لها تعبير لامبدا. لذا سنذهب إلى دالة ()login ونعدل على دالة ()require كالتالي:

fun login(user: User): String {

    require(user.username.isNotBlank() 
            && user.password.isNotBlank()) {
        "Username or password can't be blank"
    }

    return "Welcome ${user.username}"
}

أرسلنا النص:  “Username or password can’t be blank” كتعبير لامبدا لدالة ()require. وعند تنفيذ الشفرة، إذا كانت كل أو إحدى مُدخلات المستخدم فارغة، ستكون رسالة الاستثناء كالتالي:

أصبحت رسالة الاستثناء أكثر وضوحًا. بالطبع، يمكننا رمي الاستثناء مباشرةً IllegalArgumentException عبر استخدام الكلمة throw. ولكن استخدام دالة ()require، يزيد من وضوح وقابلية قراءة الشفرة.

دالة ()check:

هذه الدالة مطابقة للدالة السابقة. ما عدا أن هذه الدالة تفحص مما إذا كان الكائن الذي تعيده الدالة التي تعمل بداخلها، حالته state مناسبة. لذا، ترمي الدالة الاستثناء IllegalStateException، وهو نوع آخر من أنواع الاستثناءات التي تنتمي للاستثناء RuntimeException. فمثلًا، يمكننا التعديل على دالة ()login كالتالي:

fun login(user: User): String {

    require(user.username.isNotBlank() && user.password.isNotBlank()) {
        "Username or password can't be blank"
    }

    check(user.username != "exvar")

    return "Welcome ${user.username}"
}

ما زلنا نحتفظ بدالة ()require ولكن أضفنا دالة ()check للتحقق من أن اسم المستخدم لا يساوي “exvar”. هكذا نتأكد من أن حالة state الكائن User المسماة username لا تساوي القيمة exvar. فإذا كانت تساوي exvar أثناء عمل البرنامج، فسيتم رمي الاستثناء IllegalStateException:

نلاحظ أن النص المُرفق مع رسالة الاستثناء، هو نص عام. يمكن تخصيص نص كما فعلنا مع دالة ()require. لأن دالة ()check هي الأخرى لديها معامل من نوع بيانات الدوال. لذا يمكننا أن نرسل له تعبير لامبدا:

fun login(user: User): String {


    require(user.username.isNotBlank() 
            && user.password.isNotBlank()) {
        "Username or password can't be blank"
    }

    check(user.username != "exvar") {
        "This user is not allowed to login!"
    }

    return "Welcome ${user.username}"
}

وعند تنفيذ الشفرة بعد إضافة النص لدالة ()check، ستكون نتيجة التنفيذ هي:

الخلاصة:

تعمل دوال التحقق عادةً على رمي الاستثناءات حينما لا توافق المُدخلات شروطها. يفضل استخدام دوال التحقق، كبديل لرمي الاستثناءات عبر الكلمة throw. وهذا لأنها أسهل في كتابتها وتتبعها وقراءتها لاحقًا.

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

هل أعجبك المحتوى وتريد المزيد منه يصل إلى صندوق بريدك الإلكتروني بشكلٍ دوري؟
انضم إلى قائمة من يقدّرون محتوى إكسڤار واشترك بنشرتنا البريدية.