Sobre mim
SaudaçÔes a todos. Meu nome Ă© Vyacheslav, trabalho na ĂĄrea de TI hĂĄ 11 anos na direção do Android. Toquei e acariciei dinossauros na cara do Android 1.5 e 1.6, passei por todas as etapas da formação do MVP MVVM Retrofit e muitas outras bibliotecas. Olhei para o meu cĂłdigo antigo como um monte de g ... muitas vezes e continuo aprendendo e desenvolvendo. Consegui aprender mais de uma dĂșzia, nĂŁo tenho medo dessa palavra, caras âfortesâ, com bom potencial e cabeça sobre os ombros, no processo de treinamento foram formadas regras e recomendaçÔes que quero compartilhar .
Sobre o artigo
Recentemente, encontrei muitos projetos de complexidade variada e vejo um problema natural. Os programadores iniciantes não veem o valor de conceitos como Clean Code, KISS e SOLID. Podemos concordar que o Clean Code estå longe de ser para iniciantes, mas acho que em termos gerais, o conhecimento dessa abordagem é necessårio. Os programadores intermediårios não aplicam totalmente essas abordagens. Os programadores experientes muitas vezes se aprofundam muito nos detalhes e se esquecem das coisas mais importantes. Para iniciantes: este artigo o ajudarå a coletar regras para si mesmo às quais vale a pena prestar atenção.
Para os experientes: redefina seus pontos de vista ou aprofunde-se nos detalhes das abordagens de codificação modernas.
Para profissionais: olhe para as abordagens modernas de um Ăąngulo diferente (espero). Ăs vezes, Ă© Ăștil dar um passo para trĂĄs e verificar se vocĂȘ estĂĄ no caminho certo.
, , . . 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 finalizar, gostaria de relembrar um conselho muito Ăștil encontrado na Internet: âEscreva o cĂłdigo como se fosse lido por um manĂaco que sabe onde vocĂȘ moraâ. Escreva um bom cĂłdigo e que cafĂ© e biscoitos acompanhem vocĂȘ.