0x7E5 Razonamiento sobre lo principal

Sobre mí

Saludos a todos. Mi nombre es Vyacheslav, he trabajado en TI durante 11 años en la dirección de Android. Toqué y acaricié dinosaurios en la cara de Android 1.5 y 1.6, pasé por todas las etapas de la formación de MVP MVVM Retrofit y muchas otras bibliotecas. He visto mi código antiguo como un montón de g ... muchas veces y sigo aprendiendo y desarrollándome. Logré aprender más de una decena, no le tengo miedo a esta palabra, chicos “fuertes”, con buen potencial y la cabeza sobre los hombros, en el proceso de entrenamiento se formaron reglas y recomendaciones, las cuales quiero compartir. . 





Acerca del artículo

Recientemente, me he encontrado con muchos proyectos de diversa complejidad y veo un problema natural. Los programadores novatos no ven el valor de conceptos como Clean Code, KISS y SOLID. Podemos estar de acuerdo en que Clean Code está lejos de ser para principiantes, pero creo que en términos generales, el conocimiento de este enfoque es necesario. Los programadores intermedios no aplican completamente estos enfoques. Los programadores experimentados a menudo profundizan demasiado en los detalles y se olvidan de las cosas más importantes. Para principiantes: este artículo lo ayudará a recopilar reglas para sí mismo a las que vale la pena prestar atención. 





Para los experimentados: redefina sus puntos de vista o profundice en los detalles de los enfoques de codificación modernos.





Para profesionales: mire los enfoques modernos desde un ángulo diferente (con suerte). A veces es útil dar un paso atrás y asegurarse de que está en el camino correcto.





, , . . 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 , .. … . - . ? , , “” . . 





. .





- . “ ”, “ ”. “ ” . “ ” - . : - , , .





- . ( ) . , . “” ( /). 





Para concluir, me gustaría recordar un consejo muy útil que se encuentra en Internet: "Escribe el código como si fuera leído por un maníaco que sabe dónde vives". Escriba un buen código y que el café y las galletas vengan con usted. 








All Articles