Tentang diriku
Salam untuk semua. Nama saya Vyacheslav, saya telah bekerja di IT selama 11 tahun di bidang Android. Saya menyentuh dan membelai dinosaurus di depan Android 1.5 dan 1.6, melewati semua tahapan pembentukan MVP MVVM Retrofit dan banyak perpustakaan lainnya. Melihat kode lama saya sebagai sekumpulan ... berkali-kali dan masih terus belajar dan berkembang. Saya berhasil belajar lebih dari selusin, saya tidak takut dengan kata "kuat" ini, dengan potensi baik dan kepala di pundak mereka, dalam proses pelatihan, aturan dan rekomendasi dibentuk, yang ingin saya bagikan .
Tentang artikel
Baru-baru ini, saya telah menemukan banyak proyek dengan kompleksitas yang berbeda-beda dan saya melihat masalah yang wajar. Pemrogram pemula tidak melihat nilai konsep seperti Clean Code, KISS dan SOLID. Kami setuju bahwa Kode Bersih masih jauh dari sekedar pemula, tapi saya pikir secara umum, pengetahuan tentang pendekatan ini diperlukan. Pemrogram menengah tidak sepenuhnya menerapkan pendekatan ini. Pemrogram berpengalaman sering kali terlalu mendalami detail dan melupakan hal-hal terpenting. Untuk pemula: Artikel ini akan membantu Anda mengumpulkan aturan untuk diri sendiri yang perlu diperhatikan.
Untuk yang Berpengalaman: Definisikan ulang pandangan Anda atau pelajari detail pendekatan pengkodean modern.
Untuk profesional: lihat pendekatan modern dari sudut yang berbeda (semoga). Terkadang membantu untuk mengambil langkah mundur dan memastikan Anda berada di jalur yang benar.
, , . . Clean Code.
Clean Code
, , .
“Clean Code”. , . . - , ( ). - , . : “ ”. - 2 , - - ”. , - . . , 100 . . 2 ? - , - , . .. - , . “transformDateToString” “transDTS”. “ ” - “”, “ ” - . “” “”, “” . . , . : - .
KISS
KISS (keep it simple, stupid). , . - , , , . . SOLID, , , , - , . .
interface Factory<out T> {
fun create(): T
}
typealias PrinterFun = (String) -> Unit
interface PrinterFactory : Factory<PrinterFun>
interface MessageFactory : Factory<String>
interface MessagePrinter {
fun print(pf: PrinterFactory, mf: MessageFactory)
}
class PrinterFactoryImpl : PrinterFactory {
override fun create(): PrinterFun = ::print
}
class MessageFactoryImpl : MessageFactory {
companion object {
const val DEFAULT_MESSAGE = "Hello World"
}
override fun create(): String = DEFAULT_MESSAGE
class MessagePrinterImpl : MessagePrinter {
override fun print(pf: PrinterFactory, mf: MessageFactory) {
pf.create().invoke(mf.create())
}
}
class ImplProvider {
private val impls = HashMap<KClass<out Any>, Any>()
fun <T : Any> setImpl(clazz: KClass<T>, t: T) {
impls[clazz] = t
}
fun <T : Any> getImpl(clazz: KClass<T>): T {
return (impls[clazz] as? T) ?: throw Exception("No impl")
}
}
fun main(args: Array<String>) {
val implProvider = ImplProvider()
implProvider.setImpl(PrinterFactory::class, PrinterFactoryImpl())
implProvider.setImpl(MessageFactory::class, MessageFactoryImpl())
implProvider.setImpl(MessagePrinter::class, MessagePrinterImpl())
implProvider.getImpl(MessagePrinter::class)
.print(implProvider.getImpl(PrinterFactory::class),
implProvider.getImpl(MessageFactory::class))
}
“Hello world”? “” - .
class TimeFormatter {
private val timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
fun formatTime() = timeFormat.format(Date())
}
. (UNIT ) . , . .
SOLID
“” : SOLID! , , - . . , - , - , , . - , . “ ”, “ ”, .
S - single responsibility
[WIKI] (single responsibility principle). . , , .
: “ ”.
“ ”, - , , . 20 1-2 (TextEditUtils, TextTransformUtils, TextConcatUtils ) - TextUtils . , , . GOD-CLASS . , , . . - . , - . , - ( , ).
O - open–closed
[WIKI] /. « … , ».
“ ( )”. , , .
. “ ?”. - , ? , - , . . - - , . :
open class UiComponent() {
var mode : Int = 0
fun showTextAndImage(text:String, image: Image){
mode = 0
...
}
fun showButton(text:String, action: Runnable){
mode = 1
...
}
...
}
, -:
class MyUiComponent(): UiComponent(){
fun doMagic(){mode = 3}
}
- “ ”, “? , ?” . , , , , , . “mode” , - . , ( ), .
, , , , .
L - Liskov substitution
[WIKI] . « ». .
, . , . . “ ”. , , , . .
. . “Downloader” “downloadFile(url)”. , , . “Downloader” , . ( ) Downloadable:
class DownloadManager() {
fun download(downloadable: Downloadable) {
val stream = downloadable.openStream()
val file = File(downloadable.getFileName())
//
}
}
interface Downloadable {
fun openStream(): InputStream
fun getFileName(): String
}
class SimpleDownloadableFile(val name: String,
val url: String) : Downloadable {
override fun openStream() = URL(url).openStream()
override fun getFileName() = name
}
class HeaderFile(val name: String,
val url: String,
val headers: Map<String, String>) : Downloadable {
override fun openStream(): InputStream {
/* */
}
override fun getFileName() = name
}
( ) ( , + )
- , . . - :
interface Something
interface SomethingSpecific : Something
interface WritableSomething : SomethingSpecific {
fun writeToFile()
}
interface GetableWritable<T> : WritableSomething {
fun obtain(): T
}
abstract class ObtainableFile(val name: String) : GetableWritable<File> {
override fun obtain() = File(name)
override fun writeToFile() = obtain().write(getStream())
abstract fun getStream(): InputStream
}
class UrlFile(url: String, name: String) : ObtainableFile(name) {
override fun getStream(): InputStream = URL(url).openStream()
}
, . , KISS. PS: …
I - interface segregation
[WIKI] . « , , , ».
. - “ ” . - “”, “interface / abstract class”.
“” “ ” . 1000 , , java interface, .
“” - , . ( Utils) . . “ ”, .
. “” “”, S (Single responsibility). Open-close . Liskov substitution .
D - dependency inversion
[WIKI] . « . - ».
, , . . . , . : single responsibility, ( , , , ). : . , Liskov substitution “”, , .
: . :
open class ServerManager {
open fun getData(): String = " "
}
open class CacheManager {
open fun saveData(data: String) {/* / */}
}
class DataManager{
fun getDataAndCache(){
val data = ServerManager().getData()
CacheManager().saveData(data)
}
}
, / “”, .
- . DataManager :
class DataManager(private val serverManager: ServerManager,
private val cacheManager: CacheManager) {
fun getDataAndCache() {
val data = serverManager.getData()
cacheManager.saveData(data)
}
}
. , ( , - ).
Clean Architecture , . “” :
interface ServerManager {
fun getData(): String
}
open class ServerManagerImpl : ServerManager {
override fun getData(): String = " "
}
interface CacheManager {
fun saveData(data: String)
}
open class CacheManagerImpl : CacheManager {
override fun saveData(data: String) {
/* / */
}
}
interface DataManager {
fun getDataAndCache()
}
class DataManagerImpl(
private val serverManager: ServerManager,
private val cacheManager: CacheManager,
) : DataManager {
override fun getDataAndCache() {
val data = serverManager.getData()
cacheManager.saveData(data)
}
}
fun foo(){
val dataManager: DataManager = DataManagerImpl(
ServerManagerImpl(),
CacheManagerImpl()
)
dataManager.getDataAndCache()
}
( ) , ( ).
(Dagger, Koin, ServiceLocator ), . , , :
interface TextProvider {
fun getText(): String
}
class SimpleTextProvider(private val text: String) : TextProvider {
override fun getText(): String = text
}
class Printer(private val textProvider: TextProvider) {
fun printText() {
println(textProvider.getText())
}
}
fun main() {
Printer(SimpleTextProvider("text")).printText()
}
, , SOLID , Dependency injection. . . , - KISS.
“”, , . - . “ ” , , . ( - Adapter-, , ).
, “ ”, , . . , . - . - . , , - : . (MVP, MVVM ) , ( -, - …). , . , . .
“Clean architecture”. . , - . “Clean architecture ”, , , . - . Hello World , ?
, , ( , ). “”. - , .
“ ”
“ ?”, . , , : . , , . . . , , ? - 2 , .. … . - . ? , , “” . .
. .
- . “ ”, “ ”. “ ” . “ ” - . : - , , .
- . ( ) . , . “” ( /).
Sebagai kesimpulan, saya ingin mengingat nasihat yang sangat berguna yang ditemukan di Internet: “Tulis kode seolah-olah akan dibaca oleh seorang maniak yang tahu di mana Anda tinggal”. Tulis kode yang baik, dan semoga kopi dan cookie ikut serta bersama Anda.