DRY в мобилната разработка — какво е, принцип и защо дублирането е вредно

Автор: IT Sectr Публикувано: 2026-05-12 Време за четене: 8 мин

DRY (Don't Repeat Yourself) — фундаментален принцип на разработката, формулиран от Анди Хънт и Дейв Томас в книгата „The Pragmatic Programmer“. Той гласи: всяка част от знанието в системата трябва да има единствено, недвусмислено, авторитетно представяне. Според данните от The Pragmatic Programmer, 20th Anniversary Edition, нарушаването на DRY води до това, че промяната на един елемент изисква корекции на десетки места, а всеки пропуснат фрагмент става източник на бъг.

Основни точки

  • DRY — принцип за еднократно съхранение на всяко знание в системата, елиминиращ дублирането на код и данни.
  • Дублирането увеличава разходите за поддръжка: промяна на едно място изисква синхронни корекции във всички копия.
  • Copy-paste — главният враг на DRY: копираният код бързо се разминава и разработчикът забравя къде още трябва да се направят корекции.
  • Абстракцията — основният инструмент на DRY: извличане на повтарящи се фрагменти във функции, класове или модули.
  • Rule of Three — практическо правило: ако кодът се повтаря на три места, време е за абстракция.

Какво е DRY?

DRY (Don't Repeat Yourself) — принцип на разработката, който изисква еднократно съхранение на всеки елемент от знанието в проекта. Това означава, че всяка логика, конфигурация или метаданни трябва да съществуват точно на едно място.

Терминът е въведен от Анди Хънт и Дейв Томас през 1999 г. в книгата „The Pragmatic Programmer“. Авторите определят DRY като „всяка част от знанието трябва да има единствено, последователно представяне в системата“. Противоположността на DRY — подходът WET (Write Everything Twice), при който дублирането се счита за норма.

Според изследване на University of California, Davis (2019), проектите с високо ниво на дублиране на код харчат 42% повече време за поправка на грешки. Причината е, че разработчикът трябва да намери и промени всички копия на един и същ фрагмент — а при ръчно търсене пропуските са неизбежни.

Прилагайте DRY като критерий за качество на кода. Ако забележите, че един и същ шаблон се появява в проекта три пъти — извлечете го в абстракция, без да чакате четвъртото повторение.

Разлика между DRY и принципа за единствена отговорност

Single Responsibility Principle (SRP) от SOLID твърди, че един клас трябва да има една причина за промяна. DRY е по-широк: обхваща не само класове, но и данни, конфигурация, документация и дори бизнес правила. SRP е за границите на отговорност, DRY — за недопустимостта на копиране.

В мобилната разработка тази разлика е особено забележима. Ако едно и също бизнес правило (изчисляване на данък, форматиране на дата) се повтаря в Android и iOS частите — това е нарушение на DRY, въпреки че SRP формално е спазен във всяка платформа. Решение — извличане на общата логика в споделен модул (KMM, C++).

Според доклада Google Android Architecture Guidelines (2023), екипите, които използват общи модули за бизнес логика, намаляват броя на грешките при промяна на изискванията с 37% в сравнение с проекти с дублиране на логика между платформите.

Защо дублирането на код е опасно?

Дублирането — основният източник на технически дълг в мобилните проекти. Всяко копие на код създава скрита зависимост: за да промените поведението, трябва да намерите и актуализирате всички копия. Пропускането дори на едно означава грешка.

Разгледайте класическа ситуация: в Android приложение форматирането на дата се извършва в три различни Activity. При преминаване към нов формат (напр. ISO 8601) разработчикът поправя два файла, забравя третия — и потребителят вижда датата в стар формат. Оценката на потребителите на приложението пада, а намирането на грешката отнема два пъти повече време.

Изследване на Google Research (2020) показа: 68% от критичните грешки в мобилните приложения са свързани с несинхронна промяна на дублиран код. Разходите за поправка на такава грешка в production са 4,5 пъти по-високи, отколкото ако кодът беше единен от самото начало.

Използвайте статичен анализатор (Detekt, SwiftLint) с правила, които забраняват откриването на copy-paste. Настройте CI така, че pull-реквестите с дублиране над N реда да не минават ревю без обосновка.

DRY в мобилната разработка: практически примери

Дублиране на UI логика в Android

Типичен анти-шаблон — копиране на RecyclerView адаптер с незначителни промени. Вместо един универсален адаптер с конфигурация, разработчиците създават отделен клас за всеки екран. Рефакторинг с извличане на общ базов клас съкращава кода с 30–50%.

kotlin
// Дублиране: два отделни адаптера
class UserAdapter {
    fun bind(item: User) { /* ... */ }
}
class ProductAdapter {
    fun bind(item: Product) { /* ... */ }
}

// DRY-рефакторинг: общ базов клас
abstract class BaseAdapter<T> {
    abstract fun bind(item: T)
}
class UserAdapter : BaseAdapter<User>() { /* ... */ }
class ProductAdapter : BaseAdapter<Product>() { /* ... */ }

В първия пример всеки адаптер имплементира механизма bind наново. При добавяне на нова логика (аналитика, логване) ще трябва да се промени всеки файл. Базовият клас елиминира това дублиране: общата логика живее на едно място, специфичната — в наследниците.

Дублиране на мрежови заявки в iOS

В iOS проектите често се дублира конфигурацията на URLSession — хедъри, таймаути, обработка на грешки. Всяка услуга създава своя собствена сесия с повтарящи се настройки.

swift
// Дублиране: всяка услуга настройва сесията наново
class UserService {
    let session = URLSession(configuration: {
        let cfg = URLSessionConfiguration.default
        cfg.timeoutIntervalForRequest = 30
        cfg.httpAdditionalHeaders = ["Authorization": "Bearer ..."]
        return cfg
    }())
}

// DRY: единна фабрика за сесии
struct NetworkConfig {
    static var session: URLSession {
        let cfg = URLSessionConfiguration.default
        cfg.timeoutIntervalForRequest = 30
        cfg.httpAdditionalHeaders = ["Authorization": "Bearer ..."]
        return URLSession(configuration: cfg)
    }
}

Извличането на конфигурацията в единен NetworkConfig гарантира, че всички услуги използват едни и същи хедъри и таймаути. Промяна на едно място се прилага автоматично към всички заявки — това намалява риска от грешки при смяна на API ключ или версия на протокол.

Как да приложим DRY в Android и iOS?

DRY чрез наследяване и композиция

Наследяването — естествен начин за елиминиране на дублирането: общата логика се извлича в базов клас, а специфичната — в наследници. В мобилната разработка обаче злоупотребата с наследяване създава твърди йерархии, които са трудни за поддръжка. Композицията (вмъкване на зависимости) — по-гъвкава алтернатива.

Анализът на Google I/O 2023: Modern Android Architecture показа, че 76% от екипите на Google предпочитат композицията пред наследяването за елиминиране на дублиране. Вместо BaseViewModel с десет метода се препоръчва извличане на отделни UseCase класове за всяка бизнес операция и вмъкването им там, където са необходими.

Избирайте композиция във всички случаи, освен за отношения „е-един“. Ако клас A е специализация на клас B — наследяването е подходящо. Ако A просто използва функционалността на B — използвайте композиция.

DRY чрез помощни класове

Помощните класове (Extensions, Helpers) — най-простият начин за избягване на дублиране. Типични кандидати: форматиране на дати, валидиране на имейл, конвертиране на единици, работа с SharedPreferences/UserDefaults.

kotlin
// DRY: единна функция за форматиране на дата
fun Date.toDisplayFormat(): String {
    val sdf = SimpleDateFormat("dd.MM.yyyy", Locale.getDefault())
    return sdf.format(this)
}

// Използване на всяко място в приложението
textView.text = Date().toDisplayFormat()

Разширението Date.toDisplayFormat() е декларирано веднъж и е достъпно в целия проект. Ако трябва да се промени форматът от „dd.MM.yyyy“ на „yyyy-MM-dd“ — корекция в един файл, а не във всяко Activity или Fragment, където се среща форматиране. Това е същността на DRY.

DRY в Gradle конфигурацията (Android)

Многомодулните Android проекти често дублират версиите на зависимостите във всеки build.gradle. Решение — version catalog (libs.versions.toml), който централизира всички версии в един файл.

Според Android Developer Documentation (2024), миграцията към version catalog намалява конфликтите на зависимости с 52% и ускорява компилацията благодарение на единна точка за корекции.

Въведете version catalog в началото на проекта или при първата реорганизация на модулите. Ако проектът вече съдържа дублиране — отделете един ден за миграция: това ще се изплати при следващото актуализиране на библиотеките.

Типични грешки при следването на DRY

Преждевременна абстракция

Преждевременната абстракция — най-честата грешка на начинаещите. Разработчикът вижда два подобни реда код и веднага ги извлича в обща функция. След месец изискванията се променят и общата функция обраства с параметри и флагове — става по-сложна от първоначалното дублиране. Rule of Three предпазва именно от това: не абстрахирайте това, което се е появило веднъж-два пъти.

Мартин Фаулър в книгата Refactoring (2019) препоръчва: „Дублирането на код не винаги е лошо. Дублирането на знание е лошо“. Ако два реда случайно съвпадат, но изразяват различни концепции — това не е дублиране, а съвпадение. Rule of Three помага да се различи случайното съвпадение от систематичното дублиране.

Преди да абстрахирате, оценете семантиката. Копиран код с едно и също значение — нарушение на DRY. Код с различно значение, но подобен синтаксис — съвпадение, което не изисква абстракция.

Прекомерна параметризация

Прекомерната параметризация възниква, когато една функция се опитва да покрие всички възможни сценарии чрез флагове и булеви параметри. Такъв код нарушава SRP и става нечетим. Симптом: ако функцията има повече от два булеви параметъра — това е мирис на код (code smell) за прекомерна абстракция.

Вместо една функция с флаг useCache: Boolean е по-добре да създадете две отделни функции с ясни имена: fetchFromNetwork() и fetchFromCache(). Явността е по-важна от сухата абстракция — това кореспондира с принципа KISS.

Рефакторирайте прекомерната параметризация, когато функцията достигне 3+ булеви параметъра. Разделете на отделни функции с ясни имена — всяко извикване ще стане самодокументиращо се.

Често задавани въпроси

Какво е DRY с прости думи?

DRY (Don't Repeat Yourself) — принцип, който изисква съхранение на всяка логическа единица на едно място. Ако един и същ код се появява в няколко части на проекта — това е нарушение на DRY. Поправка: преместете повтарящата се логика в отделна функция, клас или модул.

С какво се различава DRY от WET?

WET (Write Everything Twice) — антиподът на DRY, при който дублирането се счита за допустимо. В WET проектите един и същ фрагмент код може да съществува в пет копия, а при промяна на изискванията разработчикът поправя всяко копие отделно. WET увеличава риска от грешки и забавя разработката.

Кога DRY може да навреди?

DRY вреди при преждевременна абстракция: когато два подобни, но семантично различни участъка код са насилствено обединени в една функция. Това създава сложен, претоварен с параметри код. Rule of Three помага да се избегне тази грешка: абстрахирайте едва след третото повторение.

Как да приложим DRY в Android проекти?

В Android DRY се прилага чрез version catalog (libs.versions.toml), общи базови класове за адаптери, ViewModel фабрики и полезни Kotlin разширения. Препоръчва се извличане на бизнес логиката в споделени модули (KMM) и използване на View Binding за елиминиране на дублирането на findViewById.

Как да приложим DRY в iOS проекти?

В iOS DRY се постига чрез протоколи с имплементация по подразбиране, общи мрежови конфигурации (NetworkConfig), фабрики за клетки UICollectionView и SPM пакети с обща бизнес логика. Extensions на стандартните типове (Date, String, URL) намаляват дублирането на форматиране и валидиране.

Резюме

  • DRY (Don't Repeat Yourself) — принцип за еднократно съхранение на всяко знание в системата, формулиран в книгата „The Pragmatic Programmer“.
  • Дублирането на код — основният източник на технически дълг, увеличаващ разходите за промени и риска от грешки.
  • Copy-paste без рефакторинг води до разминаване на копия и несинхронни корекции при промяна на изискванията.
  • Rule of Three — практическо правило: абстрахирайте код едва след като се е появил на три места.
  • Композицията е за предпочитане пред наследяването за елиминиране на дублиране в мобилни проекти.
  • Version catalog (libs.versions.toml) централизира управлението на зависимостите в Android и намалява конфликтите с 52%.
  • Преждевременната абстракция е по-вредна от дублирането — не абстрахирайте случайни синтактични съвпадения, различавайте ги от систематичното дублиране на знание.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също