JavaRush /جاوا بلاگ /Random-SD /SOLID اصول جيڪي توهان جي ڪوڊ کي صاف ڪري ڇڏيندا
Paul Soia
سطح
Kiyv

SOLID اصول جيڪي توهان جي ڪوڊ کي صاف ڪري ڇڏيندا

گروپ ۾ شايع ٿيل
SOLID ڇا آهي؟ ھتي اھو آھي جيڪو SOLID مخفف جو مطلب آھي: - S: اڪيلو  ذميواري اصول. - O: کليل-بند اصول  . - ايل: لسڪوف متبادل اصول  . - I: انٽرفيس سيگريگيشن اصول  . - ڊي: انحصار جي ڦيرڦار جو اصول  . SOLID اصول صلاح ڏين ٿا ته ماڊل ڪيئن ٺاهجن، يعني سرون جن مان ايپليڪيشن ٺاهي وئي آهي. اصولن جو مقصد ماڊلز کي ڊزائين ڪرڻ آهي جيڪي: - تبديلي کي فروغ ڏين ٿا - سمجھڻ ۾ آسان آهن - ٻيهر استعمال جي قابل آهن، سو اچو ته ڏسو ته اهي ڪهڙا آهن مثالن سان.
class MainRepository(
    private val auth: FirebaseAuth
) {
    suspend fun loginUser(email: String, password: String) {
        try {
            auth.signInWithEmailAndPassword(email, password)
        } catch (e: Exception) {
            val file = File("errors.txt")
            file.appendText(text = e.message.toString())
        }
    }
}
اسان هن مثال ۾ ڇا ٿا ڏسو؟ FirebaseAuth تعمير ڪندڙ ۾ گذريو ويو آهي، ۽ اسان لاگ ان ڪرڻ جي ڪوشش ڪرڻ لاء استعمال ڪندا آهيون. جيڪڏهن اسان کي جواب ۾ هڪ غلطي ملي ٿي، اسان هڪ فائل ڏانهن پيغام لکندا آهيون. هاڻي اچو ته ڏسو ته هن ڪوڊ سان ڇا غلط آهي. 1. S: اڪيلو ذميواري اصول  : هڪ طبقي (يا فنڪشن/طريقي) صرف هڪ شيء لاء ذميوار هجڻ گهرجي. جيڪڏهن هڪ طبقو ڪيترن ئي مسئلن کي حل ڪرڻ جو ذميوار آهي، ان جا ذيلي نظام جيڪي انهن مسئلن جي حل کي لاڳو ڪن ٿا، هڪ ٻئي سان ڳنڍيل آهن. هڪ اهڙي سب سسٽم ۾ تبديليون ٻئي ۾ تبديليون آڻيندي. اسان جي مثال ۾، loginUser فنڪشن ٻن شين لاء ذميوار آهي - لاگ ان ۽ فائل ۾ غلطي لکڻ. ھڪڙي ذميواري ٿيڻ لاء، ھڪڙي غلطي کي رڪارڊ ڪرڻ لاء منطق ھڪڙي الڳ طبقي ۾ رکيل آھي.
class FileLogger{
    fun logError(error: String) {
        val file = File("errors.txt")
        file.appendText(text = error)
    }
}
class MainRepository(
    private val auth: FirebaseAuth,
    private val fileLogger: FileLogger,
) {
    suspend fun loginUser(email: String, password: String) {
        try{
            auth.signInWithEmailAndPassword(email, password)
        } catch (e: Exception) {
            fileLogger.logError(e.message.toString())
        }
    }
}
غلطي جي رڪارڊنگ منطق کي الڳ ڪلاس ۾ منتقل ڪيو ويو آهي ۽ هاڻي لاگ ان يوزر جي طريقي جي صرف هڪ ذميواري آهي - اختيار ڏيڻ. جيڪڏهن غلطي جي لاگنگ منطق کي تبديل ڪرڻ جي ضرورت آهي، ته پوء اسين اهو ڪنداسين FileLogger ڪلاس ۾، ۽ loginUser 2 فنڪشن ۾ نه. O: کليل-بند ٿيل  اصول: سافٽ ويئر ادارن (ڪلاس، ماڊل، فنڪشن) کي وڌائڻ لاء کليل هجڻ گهرجي، پر تبديليءَ لاءِ نه. ان حوالي سان، توسيع لاءِ کُليل هڪ ڪلاس، ماڊل، يا فنڪشن ۾ نئين رويي کي شامل ڪرڻ جي صلاحيت آهي جيڪڏهن ضرورت هجي، ۽ تبديلي جي بندش آهي سافٽ ويئر ادارن جي سورس ڪوڊ کي تبديل ڪرڻ تي پابندي. پهرين نظر ۾، اهو آواز پيچيده ۽ متضاد آهي. پر جيڪڏهن توهان ان تي نظر وجهو ته اهو اصول بلڪل منطقي آهي. او سي پي جي اصول تي عمل ڪندي اهو آهي ته سافٽ ويئر تبديل ٿيل آهي موجوده ڪوڊ کي تبديل ڪرڻ سان نه، پر نئون ڪوڊ شامل ڪرڻ سان. اهو آهي، اصل ۾ ٺهيل ڪوڊ "برقرار" ۽ مستحڪم رهي ٿو، ۽ نئين ڪارڪردگي متعارف ڪرايو ويو آهي يا ته عمل درآمد جي ورثي جي ذريعي يا تجريدي انٽرفيس ۽ پوليمورفزم جي استعمال ذريعي. پوء اچو ته ڏسو FileLogger ڪلاس. جيڪڏهن اسان کي ڪنهن ٻئي فائل ۾ لاگ لکڻ جي ضرورت آهي، اسان نالو تبديل ڪري سگهون ٿا:
class FileLogger{
    fun logError(error: String) {
        val file = File("errors2.txt")
        file.appendText(text = error)
    }
}
پر پوءِ سڀئي لاگ نئين فائل ۾ لکيا ويندا، جنهن جي، گهڻو ڪري، اسان کي ضرورت ناهي. پر اسان پنهنجي لاگر کي ڪيئن بدلائي سگهون ٿا بغير طبقن کي تبديل ڪرڻ کان سواء؟
open class FileLogger{

    open fun logError(error: String) {
        val file = File("error.txt")
        file.appendText(text = error)
    }

}

class CustomErrorFileLogger : FileLogger() {

    override fun logError(error: String) {
        val file = File("my_custom_error_file.txt")
        file.appendText(text = error)
    }

}
اسان FileLogger ڪلاس ۽ logError فنڪشن کي کليل طور نشان لڳايو، ھڪڙو نئون CustomErrorFileLogger ڪلاس ٺاھيو ۽ نئون لاگنگ عمل لکو. نتيجي طور، اسان جو ڪلاس ڪارڪردگي وڌائڻ لاءِ موجود آھي، پر ترميم لاءِ بند آھي. 3. ايل: لسڪوف متبادل اصول  . اهو ضروري آهي ته ذيلي ڪلاس انهن جي سپر ڪلاس جي متبادل طور ڪم ڪري سگهن. هن اصول جو مقصد اهو آهي ته نسلي طبقن کي والدين طبقن جي جاء تي استعمال ڪري سگهجي ٿو جن مان اهي پروگرام کي ٽوڙڻ کان سواء نڪتل آهن. جيڪڏهن اهو ظاهر ٿئي ٿو ته ڪوڊ هڪ طبقي جي قسم جي جانچ ڪري رهيو آهي، پوء متبادل اصول جي ڀڃڪڙي آهي. جيڪڏهن اسان جانشين ڪلاس هن طرح لکيو آهي:
class CustomErrorFileLogger : FileLogger() {

    fun customErrorLog(error: String) {
        val file = File("my_custom_error_file.txt")
        file.appendText(text = error)
    }

}
۽ ھاڻي اچو ته FileLogger ڪلاس کي ريپوزٽري ۾ CustomErrorFileLogger سان تبديل ڪريون
class MainRepository(
    private val auth: FirebaseAuth,
    private val fileLogger: CustomErrorFileLogger,
) {

    suspend fun loginUser(email: String, password: String) {
        try{
            auth.signInWithEmailAndPassword(email, password)
        }catch(e: Exception) {
            fileLogger.logError(e.message.toString())
        }
    }

}
انهي صورت ۾، logError کي والدين طبقي مان سڏيو ويندو، يا توهان کي ڪال کي تبديل ڪرڻو پوندو fileLogger.logError(e.message.toString()) to fileLogger.customErrorLog(e.message.toString()) 4. I :  انٽرفيس سيگريگيشن اصول هڪ خاص ڪلائنٽ لاءِ ٺهيل انتهائي خاص انٽرفيس ٺاهيو. ڪلائنٽ کي انٽرفيس تي انحصار نه ڪرڻ گهرجي جيڪي اهي استعمال نٿا ڪن. اهو پيچيده آواز آهي، پر اهو اصل ۾ بلڪل سادو آهي. مثال طور، اچو ته FileLogger ڪلاس کي هڪ انٽرفيس ٺاهيو، پر ان ۾ هڪ وڌيڪ فنڪشن شامل ڪريو:
interface FileLogger{

    fun printLogs()

    fun logError(error: String) {
        val file = File("errors.txt")
        file.appendText(text = error)
    }

}
ھاڻي سڀني اولادن کي پرنٽ لاگز فنڪشن کي لاڳو ڪرڻ جي ضرورت پوندي، جيتوڻيڪ اسان کي ان جي سڀني نسلن جي طبقن ۾ ضرورت نه آھي.
class CustomErrorFileLogger : FileLogger{

    override fun printLog() {

    }

    override fun logError(error: String) {
        val file = File("my_custom_error_file.txt")
        file.appendText(text = error)
    }

}
۽ ھاڻي اسان وٽ خالي ڪم ھوندا، جيڪو ڪوڊ جي صفائي لاءِ خراب آھي. ان جي بدران، اسان انٽرفيس ۾ ڊفالٽ قيمت ٺاهي سگھون ٿا ۽ پوء فنڪشن کي صرف انهن طبقن ۾ ختم ڪري سگهون ٿا جن ۾ ان جي ضرورت آهي:
interface FileLogger{

    fun printLogs() {
        //Howая-то дефолтная реализация
    }

    fun logError(error: String) {
        val file = File("errors.txt")
        file.appendText(text = error)
    }

}
class CustomErrorFileLogger : FileLogger{

    override fun logError(error: String) {
        val file = File("my_custom_error_file.txt")
        file.appendText(text = error)
    }

}
ھاڻي ڪلاس جيڪي لاڳو ڪندا FileLogger انٽرفيس صاف ٿي ويندا. 5. ڊي: انحصار جي ڦيرڦار جو اصول  . انحصار جو اعتراض هڪ تجريد هجڻ گهرجي، نه ڪجهه ڪنڪريٽ. اچو ته اسان جي مکيه طبقي ڏانهن واپس وڃو:
class MainRepository(
    private val auth: FirebaseAuth,
    private val fileLogger: FileLogger,
) {

    suspend fun loginUser(email: String, password: String) {
        try{
            auth.signInWithEmailAndPassword(email, password)
        } catch (e: Exception) {
            fileLogger.logError(e.message.toString())
        }
    }

}
اهو لڳي ٿو ته اسان اڳ ۾ ئي ترتيب ڏني آهي ۽ هر شي کي هتي مقرر ڪيو آهي. پر اڃا به هڪ وڌيڪ نقطو آهي جنهن کي تبديل ڪرڻ جي ضرورت آهي. هي استعمال ڪري رهيو آهي FirebaseAuth ڪلاس. ڇا ٿيندو جيڪڏهن ڪنهن نقطي تي اسان کي اجازت تبديل ڪرڻ جي ضرورت آهي ۽ فائر بيس ذريعي لاگ ان نه ڪرڻ جي ضرورت آهي، پر، مثال طور، ڪنهن قسم جي API درخواست استعمال ڪندي؟ پوءِ اسان کي تمام گھڻيون شيون تبديل ڪرڻيون پونديون، ۽ اسان اھو نه چاھينداسين. ائين ڪرڻ لاءِ، فنڪشن سان هڪ انٽرفيس ٺاهيو signInWithEmailAndPassword(email: String, password: String):
interface Authenticator{
    fun signInWithEmailAndPassword(email: String, password: String)
}
هي انٽرفيس اسان جو خلاصو آهي. ۽ ھاڻي اسان لاگ اِن جا مخصوص عمل ٺاھيون ٿا
class FirebaseAuthenticator : Authenticator{

    override fun signInWithEmailAndPassword(email: String, password: String) {
        FirebaseAuth.getInstance().signInWithEmailAndPassword(email, password)
    }

}
class CustomApiAuthenticator : Authenticator{

    override fun signInWithEmailAndPassword(email: String, password: String) {
        //другой способ логина
    }

}
۽ 'MainRepository' ڪلاس ۾ هاڻي ڪو به انحصار نه آهي مخصوص عمل درآمد تي، پر صرف خلاصي تي
class MainRepository (
    private val auth: Authenticator,
    private val fileLogger: FileLogger,
) {

    suspend fun loginUser(email: String, password: String) {
        try{
            auth.signInWithEmailAndPassword(email, password)
        }catch(e: Exception) {
            fileLogger.logError(e.message.toString())
        }
    }

}
۽ ھاڻي، اختيار ڪرڻ واري طريقي کي تبديل ڪرڻ لاء، اسان کي ماڊل ڪلاس ۾ صرف ھڪڙي لائن تبديل ڪرڻ جي ضرورت آھي.
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION