JavaRush /Blog Jawa /Random-JV /Prinsip SOLID sing bakal nggawe kode sampeyan luwih resik...
Paul Soia
tingkat
Kiyv

Prinsip SOLID sing bakal nggawe kode sampeyan luwih resik

Diterbitake ing grup
Apa iku SOLID? Iki tegese singkatan SOLID: - S: Prinsip Tanggung Jawab Tunggal  . - O: Prinsip Open-Closed  . - L: Prinsip Substitusi Liskov  . - I: Prinsip Segregasi Antarmuka  . - D: Prinsip Inversi Dependensi  . Prinsip SOLID menehi saran carane ngrancang modul, i.e. bata saka kang aplikasi dibangun. Tujuan saka prinsip yaiku kanggo ngrancang modul sing: - ningkatake owah-owahan - gampang dimangerteni - bisa digunakake maneh Dadi, ayo dideleng nganggo conto.
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())
        }
    }
}
Apa sing kita deleng ing conto iki? FirebaseAuth diterusake ing konstruktor, lan digunakake kanggo nyoba mlebu. Yen kita nampa kesalahan kanggo nanggepi, kita nulis pesen menyang file. Saiki ayo ndeleng apa sing salah karo kode iki. 1. S: Tanggung Jawab Tunggal Prinsip  : Kelas (utawa fungsi / metode) kudu tanggung jawab mung siji. Yen kelas tanggung jawab kanggo ngrampungake sawetara masalah, subsistem sing ngetrapake solusi kanggo masalah kasebut disambungake. Owah-owahan ing siji subsistem kasebut nyebabake owah-owahan ing subsistem liyane. Ing conto kita, fungsi loginUser tanggung jawab kanggo rong perkara - login lan nulis kesalahan menyang file. Supaya ana siji tanggung jawab, logika kanggo ngrekam kesalahan kudu diselehake ing kelas kapisah.
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())
        }
    }
}
Logika rekaman kesalahan wis dipindhah menyang kelas sing kapisah lan saiki cara loginUser mung duwe tanggung jawab siji - wewenang. Yen logika logging kesalahan kudu diganti, banjur kita bakal nindakake iki ing kelas FileLogger, lan ora ing fungsi loginUser 2. O: Open-Closed  Principle: Entitas piranti lunak (kelas, modul, fungsi) kudu mbukak kanggo extension , nanging ora kanggo modifikasi. Ing konteks iki, keterbukaan kanggo ekstensi yaiku kemampuan kanggo nambah prilaku anyar menyang kelas, modul, utawa fungsi yen perlu, lan ketertutupan kanggo ngganti minangka larangan kanggo ngganti kode sumber entitas piranti lunak. Ing kawitan marketing, iki muni rumit lan mbantah. Nanging yen sampeyan ndeleng, prinsip kasebut cukup logis. Miturut prinsip OCP yaiku piranti lunak diganti ora kanthi ngganti kode sing wis ana, nanging kanthi nambah kode anyar. Tegese, kode asline digawe tetep "utuh" lan stabil, lan fungsi anyar dikenalaké liwat warisan implementasine utawa liwat nggunakake antarmuka abstrak lan polimorfisme. Dadi ayo goleki kelas FileLogger. Yen kita kudu nulis log menyang file liyane, kita bisa ngganti jeneng:
class FileLogger{
    fun logError(error: String) {
        val file = File("errors2.txt")
        file.appendText(text = error)
    }
}
Nanging banjur kabeh log bakal ditulis menyang file anyar, kang, paling kamungkinan, kita ora perlu. Nanging kepiye carane bisa ngganti logger tanpa ngganti kelas kasebut?
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)
    }

}
Kita menehi tandha kelas FileLogger lan fungsi logError minangka mbukak, nggawe kelas CustomErrorFileLogger anyar lan nulis implementasi logging anyar. Akibaté, kelas kita kasedhiya kanggo nambah fungsi, nanging ditutup kanggo modifikasi. 3. L: Prinsip Substitusi Liskov  . Sampeyan kudu subclass bisa dadi pengganti kanggo superclasses. Tujuan saka prinsip iki yaiku kelas turunan bisa digunakake kanggo ngganti kelas induk sing asale tanpa ngilangi program kasebut. Yen ternyata kode kasebut mriksa jinis kelas, mula prinsip substitusi dilanggar. Yen kita nulis kelas penerus kaya iki:
class CustomErrorFileLogger : FileLogger() {

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

}
Lan saiki ayo ngganti kelas FileLogger karo CustomErrorFileLogger ing gudang
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())
        }
    }

}
Ing kasus iki, logError bakal disebut saka kelas induk, utawa sampeyan kudu ngganti telpon kanggo fileLogger.logError(e.message.toString()) kanggo fileLogger.customErrorLog(e.message.toString()) 4. Aku : Prinsip Segregasi Antarmuka. Nggawe antarmuka khusus sing dirancang kanggo klien tartamtu. Klien ngirim ora gumantung ing antarmuka sing ora digunakake. Iku muni rumit, nanging nyatane prasaja banget. Contone, ayo nggawe kelas FileLogger minangka antarmuka, nanging tambahake fungsi liyane:
interface FileLogger{

    fun printLogs()

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

}
Saiki kabeh keturunan bakal diwajibake ngleksanakake fungsi printLogs, sanajan kita ora butuh ing kabeh kelas turunan.
class CustomErrorFileLogger : FileLogger{

    override fun printLog() {

    }

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

}
lan saiki kita bakal duwe fungsi kosong, sing ora becik kanggo kebersihan kode. Nanging, kita bisa nggawe nilai standar ing antarmuka lan banjur ngilangi fungsi kasebut mung ing kelas sing dibutuhake:
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)
    }

}
Saiki kelas sing bakal ngetrapake antarmuka FileLogger bakal luwih resik. 5. D: Prinsip Inversi Ketergantungan  . Obyek ketergantungan kudu abstraksi, ora konkrit. Ayo bali menyang kelas utama:
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())
        }
    }

}
Katon yen kita wis ngatur lan ndandani kabeh ing kene. Nanging isih ana siji titik liyane sing kudu diganti. Iki nggunakake kelas FirebaseAuth. Apa sing bakal kedadeyan yen ing sawetara titik kita kudu ngganti wewenang lan mlebu ora liwat Firebase, nanging, contone, nggunakake sawetara jinis panyuwunan API? Banjur kita kudu ngganti akeh perkara, lan kita ora pengin. Kanggo nindakake iki, gawe antarmuka kanthi fungsi signInWithEmailAndPassword(email: String, sandi: String):
interface Authenticator{
    fun signInWithEmailAndPassword(email: String, password: String)
}
Antarmuka iki minangka abstraksi kita. Lan saiki kita nggawe implementasi tartamtu saka login
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) {
        //другой способ логина
    }

}
Lan ing kelas `MainRepository` saiki ora ana katergantungan ing implementasine tartamtu, nanging mung ing abstraksi.
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())
        }
    }

}
Lan saiki, kanggo ngganti cara wewenang, kita kudu ngganti mung siji baris ing kelas modul.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION