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 від принципу єдиної відповідальності

Принцип єдиної відповідальності (SRP) з SOLID стверджує, що у класу повинна бути одна причина для зміни. DRY ширший: він охоплює не тільки класи, але й дані, конфігурацію, документацію і навіть бізнес-правила. SRP — про межі відповідальності, DRY — про недопустимість копіювання.

У мобільній розробці ця відмінність особливо помітна. Якщо одне і те ж бізнес-правило (розрахунок податку, форматування дати) повторюється в Android та iOS частинах проекту — це порушення DRY, хоча SRP формально дотримано всередині кожної платформи. Рішення — виносити загальну логіку в shared-модуль (KMM, C++).

Згідно зі звітом Google Android Architecture Guidelines (2023), команди, які використовують спільні модулі для бізнес-логіки, скорочують кількість багів при зміні вимог на 37% порівняно з проектами з дублюванням логіки по платформах.

Чому дублювання коду небезпечне?

Дублювання — головне джерело технічного боргу в мобільних проектах. Кожна копія коду створює приховану залежність: щоб змінити поведінку, потрібно знайти і оновити всі копії. Пропуск хоча б однієї означає баг.

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

Дослідження Google Research (2020) показало: 68% критичних багів у мобільних додатках пов'язані з несинхронною зміною дубльованого коду. При цьому вартість виправлення такого багу в production в 4,5 рази вища, ніж якби код був єдиним спочатку.

Використовуйте статичний аналізатор (Detekt, SwiftLint) з правилами, що забороняють copy-paste. Налаштуйте CI, щоб пул-реквести з дублюванням більше N рядків не проходили рев'ю без обґрунтування.

DRY у мобільній розробці: практичні приклади

Дублювання UI-логіки в Android

Типовий anti-pattern — копіювання адаптера 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) — найпростіший спосіб уникнути дублювання. Типові кандидати: форматування дат, валідація email, конвертація одиниць, робота з 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. Рекомендується виносити бізнес-логіку в shared-модулі (KMM) і використовувати View Binding для усунення дублювання findViewById.

Як застосовувати DRY в iOS-проектах?

В iOS DRY досягається через протоколи з default implementation, спільні мережеві конфігурації (NetworkConfig), фабрики комірок UICollectionView та SPM-пакети зі спільною бізнес-логікою. Розширення стандартних типів (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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також