Uygulama mimarisi kılavuzu

Bu kılavuz, sağlam ve yüksek kaliteli uygulamalar oluşturmak için en iyi uygulamaları ve önerilen mimariyi kapsar.

Mobil uygulama kullanıcı deneyimleri

Tipik bir Android uygulaması, etkinlikler, parçalar, hizmetler, içerik sağlayıcılar ve yayın alıcılar dahil olmak üzere birden fazla uygulama bileşeni içerir. Bu uygulama bileşenlerinin çoğunu uygulama manifestinizde beyan edersiniz. Android işletim sistemi daha sonra bu dosyayı kullanarak uygulamanızı cihazın genel kullanıcı deneyimine nasıl entegre edeceğine karar verir. Tipik bir Android uygulamasının birden fazla bileşen içerebileceği ve kullanıcıların kısa bir süre içinde birden fazla uygulamayla etkileşim kurduğu göz önüne alındığında, uygulamaların farklı kullanıcı odaklı iş akışlarına ve görevlere uyum sağlaması gerekir.

Birden fazla form faktörü

Uygulamalar yalnızca telefonlarda değil, tabletlerde, katlanabilir cihazlarda, ChromeOS cihazlarda ve daha birçok form faktöründe çalışabilir. Bir uygulama dikey veya yatay yönü varsayamaz. Tek bir oturumda her ikisinde de çalışabilir. Kullanıcının katlanabilir cihazı masa veya kitap duruşuna getirmesi gibi yapılandırma değişiklikleri, uygulamanızın kullanıcı arayüzünü yeniden oluşturmasına neden olabilir. Bu durum, uygulama verilerini ve durumunu etkileyebilir.

Kaynak kısıtlamaları

Mobil cihazların da kaynak açısından sınırlı olduğunu unutmayın. Bu nedenle, işletim sistemi yeni uygulamalara yer açmak için bazı uygulama işlemlerini durdurabilir.

Değişken başlatma koşulları

Bu ortamın koşulları göz önüne alındığında, uygulama bileşenlerinizin ayrı ayrı ve sırasız olarak başlatılması ve işletim sistemi ya da kullanıcı tarafından herhangi bir zamanda yok edilmesi mümkündür. Bu etkinlikler sizin kontrolünüzde olmadığından, uygulama bileşenlerinizde herhangi bir uygulama verisi veya durumu saklamamalı ya da bellekte tutmamalı ve uygulama bileşenleriniz birbirine bağlı olmamalıdır.

Sık karşılaşılan mimari ilkeler

Uygulama verilerini ve durumunu depolamak için uygulama bileşenlerini kullanmamanız gerekiyorsa uygulamanızı nasıl tasarlamalısınız?

Android uygulamalarının boyutu büyüdükçe uygulamanın ölçeklenmesine, farklı şekil ve boyutlara uyum sağlamasına, uygulamanın sağlamlığını artırmasına ve uygulamanın test edilmesini kolaylaştırmasına olanak tanıyan bir mimari tanımlamak önemlidir.

Uygulama mimarisi, uygulamanın bölümleri arasındaki sınırları ve her bölümün sorumluluklarını tanımlar. Tüm kurallara uymak için uygulama mimarinizi belirli birkaç ilkeye göre tasarlamanız gerekir.

İlgi alanlarının ayrılması

Uyulması gereken en önemli ilke, ilgi alanlarının ayrılmasıdır. Tüm kodunuzu bir Activity veya Fragment içine yazmak yaygın bir hatadır. Bu kullanıcı arayüzü tabanlı sınıflar yalnızca kullanıcı arayüzü ve işletim sistemi etkileşimlerini işleyen mantığı içermelidir. Bu sınıfları mümkün olduğunca yalın tutarak bileşen yaşam döngüsüyle ilgili birçok sorunu önleyebilir ve bu sınıfların test edilebilirliğini artırabilirsiniz.

Activity ve Fragment uygulamalarının sahibi olmadığınızı unutmayın. Bunlar, Android işletim sistemi ile uygulamanız arasındaki sözleşmeyi temsil eden yapıştırıcı sınıflardır. İşletim sistemi, kullanıcı etkileşimlerine veya düşük bellek gibi sistem koşullarına bağlı olarak bunları istediği zaman yok edebilir. Tatmin edici bir kullanıcı deneyimi ve daha kolay yönetilebilen bir uygulama bakımı deneyimi sunmak için bu kitaplıklara olan bağımlılığınızı en aza indirmeniz önerilir.

Uyarlanabilir düzenler

Uygulamanız, kullanıcının dikey ve yatay cihaz yönleri arasında geçiş yapması ve uygulamanın büyük ekranlarda çalışması gibi yapılandırma değişikliklerini sorunsuz bir şekilde işlemelidir. Standart uyarlanabilir düzenleri uygulayan bir uygulama, çeşitli form faktörlerinde optimum kullanıcı deneyimi sağlar.

Veri modellerinden Drive kullanıcı arayüzü

Bir diğer önemli ilke de kullanıcı arayüzünüzü veri modellerinden (tercihen kalıcı modellerden) yönlendirmeniz gerektiğidir. Veri modelleri, bir uygulamanın verilerini temsil eder. Bunlar, uygulamanızdaki kullanıcı arayüzü öğelerinden ve diğer bileşenlerden bağımsızdır. Bu nedenle, kullanıcı arayüzü ve uygulama bileşeni yaşam döngüsüne bağlı değildirler ancak işletim sistemi, uygulamanın sürecini bellekten kaldırmaya karar verdiğinde yine de yok edilirler.

Kalıcı modeller şu nedenlerle idealdir:

  • Android işletim sistemi, kaynakları boşaltmak için uygulamanızı yok ederse kullanıcılarınız veri kaybetmez.

  • Uygulamanız, ağ bağlantısının kesintili olduğu veya kullanılamadığı durumlarda çalışmaya devam eder.

Uygulama mimarinizi veri modeli sınıflarına dayandırırsanız uygulamanız daha test edilebilir ve sağlam hale gelir.

Tek ve doğru kaynak

Uygulamanızda yeni bir veri türü tanımlandığında bu türe tek bir doğru kaynak (SSOT) atamanız gerekir. SSOT, bu verilerin sahibidir ve yalnızca SSOT bu verileri değiştirebilir veya dönüştürebilir. SSOT, bunu sağlamak için verileri değişmez bir tür kullanarak kullanıma sunar. Verileri değiştirmek için ise SSOT, diğer türlerin çağırabileceği işlevleri veya olayları kullanıma sunar.

Bu kalıp birden fazla avantaj sunar:

  • Belirli bir veri türündeki tüm değişiklikleri tek bir yerde toplar.
  • Bu tür, verileri diğer türlerin kurcalayamayacağı şekilde korur.
  • Verilerde yapılan değişikliklerin daha kolay izlenmesini sağlar. Bu sayede hataları daha kolay tespit edebilirsiniz.

Öncelikle çevrimdışı uygulamalarda, uygulama verilerinin doğruluk kaynağı genellikle bir veritabanıdır. Bazı durumlarda ise doğruluk kaynağı bir ViewModel veya kullanıcı arayüzü olabilir.

Tek Yönlü Veri Akışı

Tek ve doğru kaynak ilkesi, tek yönlü veri akışı (UDF) modeliyle ilgili kılavuzlarımızda sıklıkla kullanılır. UDF'de durum yalnızca tek bir yönde akar. Veri akışını ters yönde değiştiren etkinlikler.

Android'de durum veya veriler genellikle hiyerarşinin daha yüksek kapsamlı türlerinden daha düşük kapsamlı türlerine akar. Etkinlikler genellikle daha düşük kapsamlı türlerden tetiklenerek ilgili veri türü için SSOT'a ulaşır. Örneğin, uygulama verileri genellikle veri kaynaklarından kullanıcı arayüzüne akar. Düğmeye basma gibi kullanıcı etkinlikleri, uygulama verilerinin değiştirildiği ve sabit bir türde kullanıma sunulduğu SSOT'ye kullanıcı arayüzünden aktarılır.

Bu model, veri tutarlılığını daha iyi korur, hata yapmaya daha az eğilimlidir, hata ayıklaması daha kolaydır ve SSOT modelinin tüm avantajlarını sunar.

Bu bölümde, uygulamanızı önerilen en iyi uygulamalara uygun şekilde nasıl yapılandıracağınız gösterilmektedir.

Önceki bölümde bahsedilen ortak mimari ilkeler göz önünde bulundurulduğunda, her uygulamada en az iki katman olmalıdır:

  • Uygulama verilerini ekranda gösteren kullanıcı arayüzü katmanı.
  • Uygulamanızın iş mantığını içeren ve uygulama verilerini kullanıma sunan veri katmanı.

Kullanıcı arayüzü ile veri katmanları arasındaki etkileşimleri basitleştirmek ve yeniden kullanmak için alan katmanı adlı ek bir katman ekleyebilirsiniz.

Tipik bir uygulama mimarisinde, kullanıcı arayüzü katmanı uygulama verilerini veri katmanından veya kullanıcı arayüzü katmanı ile veri katmanı arasında yer alan isteğe bağlı alan katmanından alır.
1.şekil Tipik bir uygulama mimarisinin şeması.

Modern Uygulama Mimarisi

Bu Modern Uygulama Mimarisi, diğerlerinin yanı sıra aşağıdaki tekniklerin kullanılmasını teşvik eder:

  • Uyarlanabilir ve katmanlı bir mimari.
  • Uygulamanın tüm katmanlarında tek yönlü veri akışı (UDF).
  • Kullanıcı arayüzünün karmaşıklığını yönetmek için durum koruyucular içeren bir kullanıcı arayüzü katmanı.
  • Eş yordamlar ve akışlar.
  • Bağımlılık ekleme ile ilgili en iyi uygulamalar.

Daha fazla bilgi için aşağıdaki bölümlere, içerik tablosundaki diğer Mimari sayfalarına ve en önemli en iyi uygulamaların özetini içeren öneriler sayfasına bakın.

Kullanıcı arayüzü katmanı

Kullanıcı arayüzü katmanının (veya sunum katmanı) görevi, uygulama verilerini ekranda göstermektir. Veriler, kullanıcı etkileşimi (ör. düğmeye basma) veya harici giriş (ör. ağ yanıtı) nedeniyle her değiştiğinde kullanıcı arayüzü, değişiklikleri yansıtacak şekilde güncellenmelidir.

Kullanıcı arayüzü katmanı iki şeyden oluşur:

  • Ekrandaki verileri işleyen kullanıcı arayüzü öğeleri. Bu öğeleri View'ları veya Jetpack Compose işlevlerini kullanarak oluşturursunuz. Hem Görünümler hem de Jetpack Compose, uyarlanabilir düzenleri destekler.
  • Verileri tutan, kullanıcı arayüzüne sunan ve mantığı işleyen durum tutucular (ör. ViewModel sınıfları).
Tipik bir mimaride, kullanıcı arayüzü katmanının kullanıcı arayüzü öğeleri durum tutuculara, durum tutucular ise veri katmanındaki veya isteğe bağlı alan katmanındaki sınıflara bağlıdır.
Şekil 2. Uygulama mimarisinde kullanıcı arayüzü katmanının rolü.

Bu katman hakkında daha fazla bilgi edinmek için Kullanıcı arayüzü katmanı sayfasını inceleyin.

Veri katmanı

Bir uygulamanın veri katmanı iş mantığını içerir. İş mantığı, uygulamanıza değer katan şeydir. Uygulamanızın verileri nasıl oluşturduğunu, depoladığını ve değiştirdiğini belirleyen kurallardan oluşur.

Veri katmanı, her biri sıfır ila çok sayıda veri kaynağı içerebilen depolardan oluşur. Uygulamanızda işlediğiniz her farklı veri türü için bir depo sınıfı oluşturmanız gerekir. Örneğin, filmlerle ilgili veriler için bir MoviesRepository sınıfı veya ödemelerle ilgili veriler için bir PaymentsRepository sınıfı oluşturabilirsiniz.

Tipik bir mimaride, veri katmanının depoları uygulamanın geri kalanına veri sağlar ve veri kaynaklarına bağlıdır.
3.şekil Uygulama mimarisinde veri katmanının rolü.

Depo sınıfları aşağıdaki görevlerden sorumludur:

  • Verileri uygulamanın geri kalanına sunma
  • Verilerde yapılan değişiklikleri merkezileştirme.
  • Birden fazla veri kaynağı arasındaki çakışmaları çözme
  • Veri kaynaklarını uygulamanın geri kalanından ayırma
  • İş mantığı içerir.

Her veri kaynağı sınıfı, yalnızca bir veri kaynağıyla (dosya, ağ kaynağı veya yerel veritabanı olabilir) çalışma sorumluluğuna sahip olmalıdır. Veri kaynağı sınıfları, veri işlemleri için uygulama ile sistem arasında köprü görevi görür.

Bu katman hakkında daha fazla bilgi edinmek için veri katmanı sayfasına bakın.

Alan katmanı

Alan katmanı, kullanıcı arayüzü ve veri katmanları arasında yer alan isteğe bağlı bir katmandır.

Alan katmanı, karmaşık iş mantığını veya birden fazla ViewModel tarafından yeniden kullanılan daha basit iş mantığını kapsüllemekten sorumludur. Bu katman, tüm uygulamalar bu koşulları karşılamadığından isteğe bağlıdır. Bu özelliği yalnızca gerektiğinde (ör. karmaşıklığı yönetmek veya yeniden kullanılabilirliği tercih etmek için) kullanmalısınız.

İsteğe bağlı alan katmanı, dahil edildiğinde kullanıcı arayüzü katmanına bağımlılıklar sağlar ve veri katmanına bağlıdır.
4.şekil Alan katmanının uygulama mimarisindeki rolü.

Bu katmandaki sınıflara genellikle kullanım alanları veya etkileşimciler adı verilir. Her kullanım alanının tek bir işlevden sorumlu olması gerekir. Örneğin, birden fazla ViewModel ekranda doğru mesajı göstermek için saat dilimlerine bağlıysa uygulamanızda GetTimeZoneUseCase sınıfı olabilir.

Bu katman hakkında daha fazla bilgi edinmek için alan katmanı sayfasını inceleyin.

Bileşenler arasındaki bağımlılıkları yönetme

Uygulamanızdaki sınıfların düzgün çalışması için diğer sınıflara bağlı olması. Belirli bir sınıfın bağımlılıklarını toplamak için aşağıdaki tasarım kalıplarından birini kullanabilirsiniz:

  • Bağımlılık ekleme (DI): Bağımlılık ekleme, sınıfların bağımlılıklarını oluşturmadan tanımlamasına olanak tanır. Çalışma zamanında, bu bağımlılıkları sağlamak başka bir sınıfın sorumluluğundadır.
  • Hizmet bulucu: Hizmet bulucu kalıbı, sınıfların bağımlılıklarını oluşturmak yerine elde edebilecekleri bir kayıt defteri sağlar.

Bu kalıplar, kodu kopyalamadan veya karmaşıklık eklemeden bağımlılıkları yönetmek için net kalıplar sağladığından kodunuzu ölçeklendirmenize olanak tanır. Ayrıca bu kalıplar, test ve üretim uygulamaları arasında hızlıca geçiş yapmanıza olanak tanır.

Genel en iyi uygulamalar

Programlama, yaratıcılık gerektiren bir alandır ve Android uygulamaları geliştirmek de bu kapsamdadır. Bir sorunu çözmenin birçok yolu vardır. Örneğin, verileri birden fazla etkinlik veya parça arasında iletebilir, uzaktan verileri alıp çevrimdışı mod için yerel olarak kalıcı hale getirebilir ya da önemsiz olmayan uygulamaların karşılaştığı diğer yaygın senaryoları işleyebilirsiniz.

Aşağıdaki öneriler zorunlu olmasa da çoğu durumda bu önerilere uyarak kod tabanınızı daha sağlam, test edilebilir ve uzun vadede bakımı daha kolay hale getirebilirsiniz:

Verileri uygulama bileşenlerinde depolamayın.

Uygulamanızın giriş noktalarını (ör. etkinlikler, hizmetler ve yayın alıcılar) veri kaynağı olarak belirlemekten kaçının. Bunun yerine, yalnızca diğer bileşenlerle koordineli çalışarak bu giriş noktasıyla alakalı veri alt kümesini almalıdırlar. Her uygulama bileşeni, kullanıcının cihazıyla etkileşimine ve sistemin genel mevcut durumuna bağlı olarak kısa ömürlüdür.

Android sınıflarına olan bağımlılıkları azaltın.

Uygulama bileşenleriniz, Context veya Toast gibi Android Framework SDK API'lerini kullanan tek sınıflar olmalıdır. Uygulamanızdaki diğer sınıfları bunlardan soyutlamak, test edilebilirliğe yardımcı olur ve uygulamanızdaki bağlantıyı azaltır.

Uygulamanızdaki modüller arasında net sorumluluk sınırları tanımlayın.

Örneğin, ağdan veri yükleyen kodu kod tabanınızdaki birden fazla sınıf veya pakete yaymayın. Benzer şekilde, aynı sınıfta veri önbelleğe alma ve veri bağlama gibi birbiriyle alakasız birden fazla sorumluluk tanımlamayın. Önerilen uygulama mimarisini kullanmak bu konuda size yardımcı olacaktır.

Her modülden mümkün olduğunca az bilgi gösterin.

Örneğin, bir modüldeki dahili uygulama ayrıntısını ortaya çıkaran bir kısayol oluşturmayın. Kısa vadede biraz zaman kazanabilirsiniz ancak kod tabanınız geliştikçe büyük olasılıkla teknik borçlarınız kat kat artar.

Uygulamanızın benzersiz özüne odaklanarak diğer uygulamalardan öne çıkmasını sağlayın.

Aynı standart kodu tekrar tekrar yazarak zaman kaybetmeyin. Bunun yerine, zamanınızı ve enerjinizi uygulamanızı benzersiz kılan özelliklere odaklanarak geçirin. Tekrarlanan standart kodları ise Jetpack kitaplıkları ve diğer önerilen kitaplıklar halletsin.

Standart düzenler ve uygulama tasarım kalıpları kullanın.

Jetpack Compose kitaplıkları, uyarlanabilir kullanıcı arayüzleri oluşturmak için güçlü API'ler sağlar. Uygulamanızda standart düzenleri kullanarak birden fazla form faktöründe ve ekran boyutunda kullanıcı deneyimini iyileştirin. Kullanım alanlarınıza en uygun düzenleri seçmek için uygulama tasarım kalıpları galerisini inceleyin.

Uygulamanızın her bölümünü ayrı ayrı nasıl test edebileceğinizi düşünün.

Örneğin, ağdan veri getirmek için iyi tanımlanmış bir API'ye sahip olmak, bu verileri yerel bir veritabanında kalıcı hale getiren modülün test edilmesini kolaylaştırır. Bunun yerine bu iki modüldeki mantığı tek bir yerde karıştırırsanız veya ağ kodunuzu tüm kod tabanınıza dağıtırsanız etkili bir şekilde test etmek imkansız olmasa da çok daha zor hale gelir.

Türler, eşzamanlılık politikalarından sorumludur.

Bir tür uzun süreli engelleme işi yapıyorsa bu hesaplamayı doğru iş parçacığına taşımaktan sorumlu olmalıdır. Bu tür, yaptığı hesaplamanın türünü ve hangi iş parçacığında yürütülmesi gerektiğini bilir. Türler ana ileti dizisinde güvenli olmalıdır. Yani ana ileti dizisini engellemeden bu türleri ana ileti dizisinden çağırmak güvenlidir.

Mümkün olduğunca çok sayıda alakalı ve yeni veriyi saklayın.

Bu sayede kullanıcılar, cihazları çevrimdışı moddayken bile uygulamanızın işlevselliğinden yararlanabilir. Kullanıcılarınızın tamamının sürekli ve yüksek hızlı bağlantıdan hoşlanmadığını, hatta hoşlansalar bile kalabalık yerlerde kötü sinyal alabileceklerini unutmayın.

Mimari yapının avantajları

Uygulamanızda iyi bir mimarinin uygulanması projeye ve mühendislik ekiplerine birçok avantaj sağlar:

  • Bu, uygulamanın genel olarak sürdürülebilirliğini, kalitesini ve sağlamlığını artırır.
  • Uygulamanın ölçeklenmesine olanak tanır. Daha fazla kişi ve daha fazla ekip, aynı kod tabanına minimum kod çakışmasıyla katkıda bulunabilir.
  • İlk katılım sürecine yardımcı olur. Mimari, projenize tutarlılık kazandırdığı için ekibin yeni üyeleri kısa sürede uyum sağlayabilir ve daha az zamanda daha verimli olabilir.
  • Test etmek daha kolaydır. İyi bir mimari, genellikle test edilmesi daha kolay olan basit türleri teşvik eder.
  • Hatalar, iyi tanımlanmış süreçlerle metodik olarak incelenebilir.

Mimarideki yatırımlar, kullanıcılarınızı da doğrudan etkiler. Daha üretken bir mühendislik ekibi sayesinde daha kararlı bir uygulamadan ve daha fazla özellikten yararlanırlar. Ancak mimari için önceden zaman ayırmak da gerekir. Bu süreyi şirketinizin geri kalanına açıklamanıza yardımcı olması için diğer şirketlerin uygulamalarında iyi bir mimari kullanırken başarı hikayelerini paylaştığı örnek olaylara göz atın.

Örnekler

Aşağıdaki Google örnekleri, iyi bir uygulama mimarisini gösterir. Bu rehberliğin nasıl uygulandığını görmek için bu kaynakları inceleyin: