0x7E5 Raisonnement sur l'essentiel

À propos de moi

Salutations Ă  tous. Je m'appelle Vyacheslav, je travaille dans l'informatique depuis 11 ans sous la direction d'Android. J'ai touchĂ© et caressĂ© des dinosaures face Ă  Android 1.5 et 1.6, j'ai traversĂ© toutes les Ă©tapes de la formation de MVP MVVM Retrofit et de nombreuses autres bibliothĂšques. J'ai regardĂ© mon ancien code comme un tas de g ... plusieurs fois et continue Ă  apprendre et Ă  se dĂ©velopper. J'ai rĂ©ussi Ă  en apprendre plus d'une dizaine, je n'ai pas peur de ce mot, des mecs «forts», avec un bon potentiel et une tĂȘte sur les Ă©paules, en cours de formation, des rĂšgles et recommandations se sont formĂ©es, que je souhaite partager . 





À propos de l'article

RĂ©cemment, je suis tombĂ© sur de nombreux projets de complexitĂ© variable et je vois un problĂšme naturel. Les programmeurs novices ne voient pas la valeur de concepts tels que Clean Code, KISS et SOLID. Nous pouvons convenir que Clean Code est loin d'ĂȘtre pour les dĂ©butants, mais je pense que d'une maniĂšre gĂ©nĂ©rale, la connaissance de cette approche est nĂ©cessaire. Les programmeurs intermĂ©diaires n'appliquent pas pleinement ces approches. Les programmeurs expĂ©rimentĂ©s vont souvent trop loin dans les dĂ©tails et oublient les choses les plus importantes. Pour les dĂ©butants: cet article vous aidera Ă  collecter des rĂšgles qui mĂ©ritent d'ĂȘtre Ă©tudiĂ©es. 





Pour les expérimentés: redéfinissez vos points de vue ou plongez dans les détails des approches de codage modernes.





Pour les professionnels: regardez les approches modernes sous un angle diffĂ©rent (espĂ©rons-le). Parfois, il est utile de prendre du recul et de s'assurer que vous ĂȘtes sur la bonne voie.





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





. .





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





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





En conclusion, je voudrais rappeler un conseil trĂšs utile trouvĂ© sur Internet: «Écrivez le code comme s'il devait ĂȘtre lu par un maniaque qui sait oĂč vous habitez». Écrivez un bon code et que le cafĂ© et les biscuits vous accompagnent. 








All Articles