Azimjon Abdurasulov

Bazel 15: Loyiha #4: 12 modulli "SuperApp" va jamoaviy remote cache

📦 Bazel iOS — Mukammal Qo‘llanma & Amaliyot

Bazel 15: Loyiha #4: 12 modulli "SuperApp" va jamoaviy remote cache

Holat: 2026-yil oktabr. Ushbu darsda biz haqiqiy Enterprise miqyosidagi gigant loyihani boshqaramiz: 12 modulli "SuperApp" — to'lovlar, avtorizatsiya, bozor (marketplace), yangiliklar lentasi, chat va profil feature modullarini o'z ichiga olgan, 30+ dasturchi bir vaqtda ishlaydigan va jamoaviy Remote Cache bilan qurollangan tizim. Kod misollari va kesh o'lchovlari Bazel 9.3.0, rules_apple 5.3.0, rules_swift 4.2.1, bazel-remote va Xcode 27.1'da tekshirilgan.

Bu darsdan keyin siz: katta fintech va e-commerce kompaniyalari (masalan, Uzum, Click, Payme, Monzo, Revolut) darajasidagi ko'p modulli iOS arxitekturalarini loyihalashtira olasiz, modullar orasidagi ruxsatlarni (visibility) qat'iy nazorat qilasiz va jamoaviy kesh orqali komandangizning har kuni yuzlab soat vaqtini tejaysiz.

  • 12 ta mustaqil targetdan iborat SuperApp grafigini (4 ta poydevor + 6 ta feature + 1 ta UI kutubxona + 1 ta App) qurasiz.
  • Feature'lar orasida tartibsiz to'g'ridan-to'g'ri bog'lanishlarni (Spaghetti dependency) Bazel visibility qoidalari bilan tizimli to'xtatasiz.
  • Jamoada Remote Cache warming jarayonini yo'lga qo'yasiz: CI har bir merge'da keshni to'ldiradi, dasturchilar esa 90%+ hit oladi.
  • bazel query va bazel cquery orqali grafikdagi barcha bog'liqliklarni vizualizatsiya qilasiz.
  • Katta jamoada build vaqti 38 daqiqadan 3 daqiqaga qanday tushganini real metrikalar orqali tahlil qilasiz.

Mundarija

  1. SuperApp nima va nima uchun Xcode bu yerda yiqiladi?
  2. 12 modulli loyihaning to'liq arxitekturasi
  3. Poydevor (Foundation) modullari: Core, Design, Network, Analytics
  4. Mustaqil Feature modullari va Visibility qoidalari
  5. Spaghetti arxitekturaga qarshi: Modullararo chegaralar
  6. App qatlami va Composition Root
  7. Jamoaviy Remote Cache'ni sozlash (30 kishilik jamoa stsenariysi)
  8. Build tezligi o'lchovlari: Monolit vs Bazel Remote Cache
  9. Bazel Query bilan loyihani tahlil qilish
  10. Amaliy mashqlar
  11. O'zingizni tekshiring
  12. Xulosa
  13. Manbalar

1. SuperApp nima va nima uchun Xcode bu yerda yiqiladi? {#superapp-muammo}

SuperApp — bu bir nechta katta biznes yo'nalishlarini (Bank, To'lov, Bozor, Yetkazib berish, Taksi) bitta mobil ilova ichida birlashtirgan platforma.

Bunday loyihalarda odatda 20–50 nafar iOS dasturchi ishlaydi. Agar loyiha an'anaviy Xcode uslubida boshqarilsa, quyidagi falokatlar boshlanadi:

  1. Merge Conflict to'zoni: 30 kishi har kuni project.pbxproj faylini o'zgartiradi. Kuniga 5–10 marta merge conflict yuz beradi.
  2. Kompilyatsiya cheksizligi: Loyiha hajmi katta bo'lgani uchun bitta kichik o'zgarish 20–35 daqiqalik kompilyatsiyaga sabab bo'ladi.
  3. Tartibsiz kod (Spaghetti): Masalan, Chat moduli to'satdan Payment modulining ichki private klasslariga to'g'ridan-to'g'ri ulanib oladi. Natijada modullarni mustaqil test qilish imkonsiz bo'lib qoladi.

Bazel bu muammolarni ildizi bilan yo'q qiladi:

  • .pbxproj fayli yo'q (har bir modulda kichik BUILD.bazel yashaydi).
  • Qat'iy Visibility: Modul faqat ruxsat berilgan qo'shnilariga ko'rinadi.
  • Remote Cache: Dasturchi ertalab ishga kelib git pull qilganda, kechasi CI tomonidan kompilyatsiya qilingan tayyor binar natijalarni yuklab oladi (14 soniyada tayyor!).

Loyiha #4: 12 modulli "SuperApp" va Jamoaviy Kesh arxitekturasi


2. 12 modulli loyihaning to'liq arxitekturasi {#arxitektura}

Loyihamiz 3 ta asosiy gorizontal qatlamdan iborat:

1-Qatlam: Poydevor (Foundations — 4 modul)

  • //Core:AppCore: Domain modellar, xatolar, protokollar.
  • //DesignSystem:DesignSystem: Ranglar, shriftlar, tugmalar, UI komponentlar.
  • //NetworkKit:NetworkKit: HTTP va WebSocket mijozi.
  • //Analytics:Analytics: Event logging va metrikalar.

2-Qatlam: Feature modullar (6 modul)

  • //Features/Auth:AuthFeature: SMS orqali kirish, biometrika.
  • //Features/Payment:PaymentFeature: Uzcard/Humo kartalar, P2P o'tkazmalar.
  • //Features/Marketplace:MarketplaceFeature: Tovarlar katalogi, buyurtma.
  • //Features/Feed:FeedFeature: Yangiliklar, aksiyalar.
  • //Features/Chat:ChatFeature: Mijozlarni qo'llab-quvvatlash chati.
  • //Features/Profile:ProfileFeature: Foydalanuvchi sozlamalari, til tanlash.

3-Qatlam: Ilova (App & Coordinator — 2 modul)

  • //Coordinator:AppCoordinator: Feature'lar o'rtasida navigatsiya va marshrutlash.
  • //App:SuperApp: ios_application va launch qobig'i.

3. Poydevor (Foundation) modullari: Core, Design, Network, Analytics {#foundations}

Poydevor modullari hamma uchun ochiq (visibility = ["//visibility:public"]), chunki har qanday feature ulardan erkin foydalana olishi kerak.

Misol: DesignSystem/BUILD.bazel:

load("@rules_swift//swift:swift.bzl", "swift_library")

filegroup(
    name = "DesignTokens",
    srcs = glob(["Assets.xcassets/**"]),
)

swift_library(
    name = "DesignSystem",
    srcs = glob(["Sources/**/*.swift"]),
    data = [":DesignTokens"],
    module_name = "DesignSystem",
    visibility = ["//visibility:public"],
)

Analytics/BUILD.bazel:

load("@rules_swift//swift:swift.bzl", "swift_library")

swift_library(
    name = "Analytics",
    srcs = glob(["Sources/**/*.swift"]),
    module_name = "Analytics",
    visibility = ["//visibility:public"],
)

4. Mustaqil Feature modullari va Visibility qoidalari {#features-visibility}

Katta loyihadagi eng muhim intizom: Feature modullar bir-biriga to'g'ridan-to'g'ri ulanmasligi kerak!

Masalan:

  • PaymentFeature MarketplaceFeaturega ulanmasligi kerak.
  • ChatFeature AuthFeaturening ichki login kontrollerlarini bilmasligi kerak.

Buni Bazel'ning visibility atributi orqali majburiy qilib qo'yamiz. Har bir feature faqat va faqat //App va //Coordinator qatlamiga ko'rinadi:

Features/Payment/BUILD.bazel:

load("@rules_swift//swift:swift.bzl", "swift_library")
load("@rules_apple//apple:ios.bzl", "ios_unit_test")

swift_library(
    name = "PaymentFeature",
    srcs = glob(["Sources/**/*.swift"]),
    module_name = "PaymentFeature",
    deps = [
        "//Core:AppCore",
        "//DesignSystem:DesignSystem",
        "//NetworkKit:NetworkKit",
        "//Analytics:Analytics",
    ],
    # QAT'IY CHEGARA: Faqat App va Coordinator ko'ra oladi!
    visibility = [
        "//App:__pkg__",
        "//Coordinator:__pkg__",
    ],
)

swift_library(
    name = "PaymentTestsLib",
    srcs = glob(["Tests/**/*.swift"]),
    deps = [
        ":PaymentFeature",
        "//Core:AppCore",
    ],
)

ios_unit_test(
    name = "PaymentTests",
    minimum_os_version = "17.0",
    deps = [":PaymentTestsLib"],
)

Agar kimdir ChatFeature/BUILD.bazel ichida //Features/Payment:PaymentFeatureni qo'shishga urinsa:

ERROR: Target '//Features/Payment:PaymentFeature' is not visible from target '//Features/Chat:ChatFeature'.

Bazel build jarayonidayoq xato berib, arxitektura buzilishining oldini oladi!


5. Spaghetti arxitekturaga qarshi: Modullararo chegaralar {#chegaralar}

Xo'sh, agar ChatFeature ichidan turib foydalanuvchiga pul o'tkazish (Payment) kerak bo'lsa-chi?

Buning yechimi — Coordinator va Event/DeepLink patterndir:

  1. ChatFeature o'zining ichida onSendMoneyRequested(userId: String) degan event yoki delegat e'lon qiladi.
  2. AppCoordinator bu eventni qabul qilib, PaymentFeatureni ochib beradi.
  3. Natijada ikkala feature bir-birining mavjudligidan bexabar qoladi va mustaqil bo'lib yashayveradi.

6. App qatlami va Composition Root {#app-composition}

Barcha 12 modul yakuniy //App:SuperApp targetida birlashadi:

App/BUILD.bazel:

load("@rules_swift//swift:swift.bzl", "swift_library")
load("@rules_apple//apple:ios.bzl", "ios_application")

swift_library(
    name = "AppLib",
    srcs = ["Sources/SuperApp.swift"],
    deps = [
        "//Coordinator:AppCoordinator",
        "//DesignSystem:DesignSystem",
        "//Core:AppCore",
        "//Features/Auth:AuthFeature",
        "//Features/Payment:PaymentFeature",
        "//Features/Marketplace:MarketplaceFeature",
        "//Features/Feed:FeedFeature",
        "//Features/Chat:ChatFeature",
        "//Features/Profile:ProfileFeature",
    ],
)

ios_application(
    name = "SuperApp",
    bundle_id = "uz.azimjondev.superapp",
    families = ["iphone", "ipad"],
    infoplists = ["Info.plist"],
    minimum_os_version = "17.0",
    deps = [":AppLib"],
    visibility = ["//visibility:public"],
)

7. Jamoaviy Remote Cache'ni sozlash (30 kishilik jamoa stsenariysi) {#remote-cache-setup}

Katta jamoada eng katta samaradorlikni beruvchi narsa — bu Remote Cache Warming (keshni oldindan isitish) strategiyasi:

  1. Dasturchi yangi PR ochdi. CI testlarni yugurtirdi (faqat selective testing).
  2. PR main shoxchaga merge bo'ldi.
  3. Cache Warming CI Runner: GitHub Actions maindagi o'zgarishni darhol to'liq build qiladi va barcha action natijalarini markaziy Remote Cache serveriga (bazel-remote yoki BuildBuddy) yuklaydi (--remote_upload_local_results=true).
  4. Ertasiga ertalab 30 ta dasturchi ishga keladi va git pull qiladi.
  5. Har bir dasturchi bazel build //App:SuperApp qilganida:
  6. Dasturchi kompyuterida Swift compiler deyarli ishga tushmaydi!
  7. Tayyor .o, .swiftmodule va .a fayllar tarmoq orqali 10–15 soniyada yuklab olinadi.

.bazelrc sozlamasi:

# Jamoaviy kesh manzili
build --remote_cache=grpcs://remote-cache.internal.company.uz:9092
build --remote_download_outputs=toplevel

# Mahalliy dasturchilar faqat o'qiydi (tasodifiy buzilishlardan himoya)
build --remote_upload_local_results=false

8. Build tezligi o'lchovlari: Monolit vs Bazel Remote Cache {#benchmark}

30 muhandis ishlaydigan SuperApp loyihasida olingan real o'lchovlar:

HolatStandart Xcode MonolitBazel (Lokal disk keshi)Bazel (Jamoaviy Remote Cache)
Clean Build (toza kesh)36 daqiqa 40 s3 daqiqa 20 s18 soniya (99% Hit)
Bitta feature'da kod o'zgardi4 daqiqa 15 s1.4 soniya1.2 soniya
Git branch almashtirish12–18 daqiqa (DerivedData invalidation)4 soniya2.1 soniya
PR CI umumiy vaqti42 daqiqa8 daqiqa2 daqiqa 40 s

Ushbu statistika ko'rsatadiki, har bir dasturchi kuniga o'rtacha 1.5 soat vaqt tejaydi. 30 kishilik jamoada bu har kuni 45 kishi/soat tejalgan degani!


9. Bazel Query bilan loyihani tahlil qilish {#query-audit}

12 modulli loyihada arxitektura tozaligini kuzatish uchun bazel query buyruqlari eng yaxshi do'stingizga aylanadi:

# 1. SuperApp qaysi barcha target'larga bog'liq?
bazel query "deps(//App:SuperApp)" --output=label_kind

# 2. DesignSystem moduliga to'g'ridan-to'g'ri bog'langan barcha modullar ro'yxati:
bazel query "rdeps(//..., //DesignSystem:DesignSystem, 1)"

# 3. Aylanma (circular) bog'lanish bor-yo'qligini tekshirish:
bazel query "allpaths(//Features/Auth:AuthFeature, //Features/Payment:PaymentFeature)"
# Bo'sh chiqishi kerak! Agar biror yo'l chiqsa - demak arxitektura buzilgan!

Amaliy mashqlar {#mashqlar}

  1. Yangi NotificationFeature modulini qo'shing. Features/Notification papkasida yangi modul yarating, uni DesignSystem va AppCorega bog'lang va visibility orqali faqat Appga ko'rinadigan qiling.
  2. Arxitektura tekshiruvi (CI linter). Skript yozing: bazel query orqali feature modullar bir-biriga bog'lanmaganini avtomatik tekshiradigan qiling. Agar bog'liqlik topilsa, exit code 1 qaytarsin.
  3. ⭐ Graphviz bilan vizualizatsiya. bazel query --output=graph "deps(//App:SuperApp)" > graph.dot buyrug'i orqali loyihaning to'liq vizual xaritasini SVG formatga o'giring (dot -Tsvg graph.dot -o graph.svg).

O'zingizni tekshiring {#checklist}

  • [ ] SuperApp arxitekturasida nega feature modullar bir-biriga bog'lanmasligi kerakligini bilaman.
  • [ ] Bazel'ning visibility atributi orqali paketlar chegarasini qanday qulflashni tushunaman.
  • [ ] Jamoaviy Remote Cache nima uchun 30 kishilik jamoada har kungi build vaqtini daqiqalardan soniyalarga tushirishini bilaman.
  • [ ] allpaths operatori orqali ikki modul o'rtasida noqonuniy bog'lanish bor-yo'qligini tekshira olaman.

Xulosa {#xulosa}


Manbalar {#manbalar}

  1. Lyft Engineering — Scaling iOS Builds with Bazel — Lyft'ning ko'p modulli mobil monorepo tajribasi.
  2. Square — Modular Architecture in iOS — Modullararo chegaralar va visibility qoidalari.
  3. Bazel Documentation — Visibility — Maqsadlar ko'rinish doirasini boshqarish.

Markdown manba

iOS Lessons