Dijital ortam geliştikçe modern web sitelerinin karmaşıklığı da artıyor. Daha iyi kullanıcı deneyimi ve gelişmiş özelliklere olan talebin artmasıyla birlikte ön uç geliştiriciler ölçeklenebilir, bakımı yapılabilir ve verimli mimariler oluşturma zorluğuyla karşı karşıya kalıyor.
Ön uç mimarisiyle ilgili mevcut çok sayıda makale ve kaynak arasında önemli bir kısmı Temiz Mimari ve onun uyarlanmasına odaklanmıştır. Aslında, ankete katılan yaklaşık 70 makalenin %50'sinden fazlası, ön uç geliştirme bağlamında Temiz Mimariyi tartışıyor.
Bilgi zenginliğine rağmen göze çarpan bir sorun varlığını sürdürüyor: Önerilen mimari fikirlerin birçoğu gerçek dünyadaki üretim ortamlarında hiçbir zaman uygulanmamış olabilir. Bu durum bunların etkililiği ve pratik senaryolarda uygulanabilirliği konusunda şüphelere yol açmaktadır.
Bu endişeden yola çıkarak, Temiz Mimariyi ön uçta uygulamak için altı aylık bir yolculuğa çıktım; bu, bu fikirlerin gerçekleriyle yüzleşmemi ve buğdayı samandan ayırmamı sağladı.
Bu makalede, Temiz Mimarinin ön uçta nasıl başarılı bir şekilde uygulanacağına dair kapsamlı bir rehber sunarak bu yolculuktan edindiğim deneyimleri ve içgörüleri paylaşacağım.
Zorluklara, en iyi uygulamalara ve gerçek dünya çözümlerine ışık tutan bu makale, ön uç geliştiricilere, sürekli gelişen web sitesi geliştirme dünyasında gezinmek için ihtiyaç duydukları araçları sağlamayı amaçlamaktadır.
Günümüzün hızla gelişen dijital ekosisteminde geliştiriciler, ön uç çerçeveler konusunda seçim yapmakta zorlanıyor. Bu seçenek bolluğu birçok sorunu giderir ve geliştirme sürecini basitleştirir.
Ancak bu aynı zamanda geliştiriciler arasında bitmek bilmeyen tartışmalara da yol açıyor; her biri kendi tercih ettiği çerçevenin diğerlerinden daha üstün olduğunu iddia ediyor. Gerçek şu ki, hızlı tempolu dünyamızda her gün yeni JavaScript kitaplıkları ortaya çıkıyor ve çerçeveler neredeyse her ay tanıtılıyor.
Böylesine dinamik bir ortamda esnekliği ve uyarlanabilirliği korumak için belirli çerçeveleri ve teknolojileri aşan bir mimariye ihtiyacımız var.
Bu, değişen trendlere ve teknolojik gelişmelere uyum sağlanması gereken ürün şirketleri veya bakım içeren uzun vadeli sözleşmeler için özellikle önemlidir.
Çerçeveler gibi detaylardan bağımsız olmak, üzerinde çalıştığımız ürüne odaklanmamızı ve ürünün yaşam döngüsü boyunca ortaya çıkabilecek değişikliklere hazırlıklı olmamızı sağlar.
Korkma; Bu makale bu ikileme cevap vermeyi amaçlamaktadır.
Temiz Mimariyi ön uçta uygulama arayışımda, mimarinin minimum ön uç deneyimine sahip olanlar için bile anlaşılır ve sürdürülebilir olmasını sağlamak amacıyla birkaç fullstack ve arka uç geliştiriciyle yakın işbirliği içinde çalıştım.
Dolayısıyla, mimarimizin temel gereksinimlerinden biri, ön uç karmaşıklıkları konusunda bilgili olmayan arka uç geliştiricilerin yanı sıra, kapsamlı ön uç uzmanlığına sahip olmayan tam yığın geliştiriciler için erişilebilir olmasıdır.
Mimari, ön uç ve arka uç ekipleri arasında kusursuz işbirliğini teşvik ederek aradaki boşluğu doldurmayı ve birleşik bir geliştirme deneyimi yaratmayı amaçlıyor.
Ne yazık ki harika şeyler inşa etmek için biraz arka plan bilgisi edinmemiz gerekiyor. Temel ilkelerin net bir şekilde anlaşılması yalnızca uygulama sürecini kolaylaştırmakla kalmayacak, aynı zamanda mimarinin yazılım geliştirmedeki en iyi uygulamalara bağlı kalmasını da sağlayacaktır.
Bu bölümde mimari yaklaşımımızın temelini oluşturan üç temel kavramı tanıtacağız: SOLID ilkeleri , Temiz Mimari (aslında SOLID ilkelerinden gelir) ve Atomik Tasarım . Eğer bu alanlar hakkında güçlü hisleriniz varsa bu bölümü atlayabilirsiniz.
SOLID, geliştiricilere ölçeklenebilir, bakımı yapılabilir ve modüler yazılım oluşturma konusunda rehberlik eden beş tasarım ilkesini temsil eden bir kısaltmadır:
Bu konuyu daha derinlemesine araştırmak istiyorsanız, ki bunu yapmanızı şiddetle tavsiye ediyorum, o zaman sorun değil. Ancak şimdilik sunduklarım daha ileri gitmek için yeterli.
Peki SOLID bu makale açısından bize ne veriyor?
Robert C. Martin, SOLID ilkelerine ve çeşitli uygulamalar geliştirmedeki kapsamlı deneyimine dayanarak Temiz Mimari konseptini önerdi. Bu kavramı tartışırken, yapısını görsel olarak temsil etmek için genellikle aşağıdaki şemaya başvurulur:
Yani Temiz Mimarlık yeni bir kavram değil; işlevsel programlama ve arka uç geliştirme dahil olmak üzere çeşitli programlama paradigmalarında yaygın olarak kullanılmaktadır.
Lodash gibi kütüphaneler ve çok sayıda arka uç çerçevesi, SOLID ilkelerine dayanan bu mimari yaklaşımı benimsemiştir.
Temiz Mimari, sistemin anlaşılmasını, bakımını ve değiştirilmesini kolaylaştırmak amacıyla kaygıların ayrılmasını ve bir uygulama içinde bağımsız, test edilebilir katmanların oluşturulmasını vurgular.
Mimari, eşmerkezli daireler veya katmanlar halinde düzenlenmiştir; her birinin net sınırları, bağımlılıkları ve sorumlulukları vardır:
Temiz Mimari, bağımlılıkların dış katmanlardan iç katmanlara akışını teşvik ederek temel iş mantığının, kullanılan belirli teknolojilerden veya çerçevelerden bağımsız kalmasını sağlar.
Bu, değişen gereksinimlere veya teknoloji yığınlarına kolayca uyum sağlayabilen esnek, bakımı yapılabilir ve test edilebilir bir kod tabanıyla sonuçlanır.
Atomik Tasarım, arayüzleri en temel öğelerine ayırıp daha sonra bunları daha karmaşık yapılar halinde yeniden birleştirerek kullanıcı arayüzü bileşenlerini düzenleyen bir metodolojidir. Brad Frost, bu konsepti ilk kez 2008 yılında "Atomik Tasarım Metodolojisi" başlıklı makalesinde tanıttı.
İşte Atomik Tasarım kavramını gösteren bir grafik:
Beş farklı seviyeden oluşur:
Geliştiriciler Atomik Tasarımı benimseyerek modülerlik, yeniden kullanılabilirlik ve kullanıcı arayüzü bileşenleri için net bir yapı gibi çeşitli avantajlardan yararlanabilirler çünkü bu, Tasarım Sistemi yaklaşımını takip etmemizi gerektirir, ancak bu makalenin konusu değil, o yüzden devam edin.
Ön uç geliştirme için Temiz Mimari konusunda bilgili bir bakış açısı geliştirmek amacıyla bir uygulama oluşturma yolculuğuna çıktım. Altı aylık bir süre boyunca bu proje üzerinde çalışırken değerli bilgiler ve deneyimler kazandım.
Sonuç olarak, bu makale boyunca verilen örnekler uygulamayla ilgili uygulamalı deneyimimden alınmıştır. Şeffaflığı korumak için tüm örnekler kamuya açık kodlardan alınmıştır.
Nihai sonucu şu adresteki depoyu ziyaret ederek keşfedebilirsiniz:
Daha önce de belirtildiği gibi, çevrimiçi ortamda Temiz Mimarinin çok sayıda uygulaması mevcuttur. Ancak bu uygulamalarda birkaç ortak unsur tespit edilebilir:
Bu ortak noktaları anlayarak Temiz Mimarinin temel yapısını takdir edebilir ve onu özel ihtiyaçlarımıza uyarlayabiliriz.
Uygulamamızın temel kısmı şunları içerir:
Kullanım senaryoları : Kullanım senaryoları, verileri kaydetme, güncelleme ve getirme gibi çeşitli işlemlere yönelik iş kurallarını tanımlar. Örneğin, bir kullanım durumu, Notion'dan bir kelime listesi almayı veya kullanıcının öğrenilen kelimeler için günlük serisini artırmayı içerebilir.
Temel olarak kullanım senaryoları, uygulamanın görev ve süreçlerini iş perspektifinden ele alarak sistemin istenen hedeflere uygun çalışmasını sağlar.
Modeller : Modeller, uygulama içindeki ticari varlıkları temsil eder. Bunlar TypeScript arayüzleri kullanılarak tanımlanabilir ve ihtiyaçlara ve iş gerekliliklerine uygun olmaları sağlanır.
Örneğin, bir kullanım senaryosu Notion'dan bir kelime listesi almayı içeriyorsa, uygun iş kurallarına ve kısıtlamalara bağlı kalarak bu listenin veri yapısını doğru bir şekilde tanımlayacak bir modele ihtiyacınız olacaktır.
Operasyonlar : Bazen belirli görevleri kullanım senaryoları olarak tanımlamak mümkün olmayabilir veya alanınızın birden fazla bölümünde kullanılabilecek yeniden kullanılabilir işlevler oluşturmak isteyebilirsiniz. Örneğin, bir Notion sözcüğünü ada göre aramak için bir işlev yazmanız gerekiyorsa, bu tür işlemlerin bulunması gereken yer burasıdır.
İşlemler, uygulama içindeki çeşitli bağlamlarda paylaşılabilen ve kullanılabilen, alana özgü mantığın kapsüllenmesi için kullanışlıdır.
Depo arayüzleri : Kullanım senaryoları verilere erişim için bir araç gerektirir. Bağımlılığı Tersine Çevirme Prensibi uyarınca, etki alanı katmanının başka bir katmana bağımlı olmaması gerekir (diğer katmanlar ona bağlıyken); bu nedenle bu katman depolar için arayüzleri tanımlar.
Uygulama ayrıntılarını değil, arayüzleri belirttiğine dikkat etmek önemlidir. Depoların kendisi, gerçek veri kaynağından bağımsız olan ve bu kaynaklardan veri alma veya bu kaynaklardan veri gönderme mantığını vurgulayan Depo Desenini kullanır.
Tek bir havuzun birden fazla API uygulayabileceğini ve tek bir Kullanım Senaryosunun birden fazla havuzu kullanabileceğini belirtmek çok önemlidir.
Bu katman veri erişiminden sorumludur ve gerektiğinde çeşitli kaynaklarla iletişim kurabilir. Bir frontend uygulaması geliştirdiğimizi düşünürsek bu katman öncelikle tarayıcı API’leri için sarmalayıcı görevi görecek.
Buna REST, yerel depolama, IndexedDB, konuşma sentezi ve daha fazlası için API'ler dahildir.
OpenAPI türleri ve HTTP istemcileri oluşturmak istiyorsanız API katmanının bunları yerleştirmek için ideal yer olduğunu unutmamak önemlidir. Bu katmanın içinde şunlara sahibiz:
API bağdaştırıcısı : API Bağdaştırıcısı, uygulamamızda kullanılan tarayıcı API'leri için özel bir bağdaştırıcıdır. Bu bileşen, REST çağrılarını ve uygulamanın belleğiyle veya kullanmak istediğiniz diğer herhangi bir veri kaynağıyla iletişimi yönetir.
İsterseniz kendi nesne depolama sisteminizi bile oluşturabilir ve uygulayabilirsiniz. Özel bir API Bağdaştırıcısına sahip olarak, çeşitli veri kaynaklarıyla etkileşimde bulunmak için tutarlı bir arayüz sağlayabilir ve gerektiğinde bunları güncellemeyi veya değiştirmeyi kolaylaştırabilirsiniz.
Depo katmanı, birden fazla API'nin entegrasyonunu yöneterek, API'ye özgü türleri etki alanı türleriyle eşleyerek ve verileri dönüştürmeye yönelik işlemleri birleştirerek uygulamanın mimarisinde önemli bir rol oynar.
Örneğin, konuşma sentezi API'sini yerel depolamayla birleştirmek istiyorsanız burası bunu yapmak için mükemmel bir yerdir. Bu katman şunları içerir:
Bağdaştırıcı katman, bu katmanlar arasındaki etkileşimleri düzenlemekten ve bunları birbirine bağlamaktan sorumludur. Bu katman yalnızca aşağıdakilerden sorumlu modülleri içerir:
Sunum katmanı, kullanıcı arayüzünü (UI) oluşturmaktan ve uygulamayla kullanıcı etkileşimlerini yönetmekten sorumludur. İşlevsel ve etkileşimli bir kullanıcı arayüzü oluşturmak için bağdaştırıcıdan, etki alanından ve paylaşılan katmanlardan yararlanır.
Sunum katmanı, bileşenlerini düzenlemek için Atomik Tasarım metodolojisini kullanır ve sonuçta ölçeklenebilir ve bakımı yapılabilir bir uygulama ortaya çıkar. Ancak bu katman, Temiz Mimari uygulaması açısından ana konu olmadığından bu makalenin ana odağı olmayacaktır.
Merkezi yardımcı programlar, konfigürasyonlar ve paylaşılan mantık gibi tüm ortak öğeler için belirlenmiş bir yer gereklidir. Ancak bu yazıda bu katmana çok fazla değinmeyeceğiz.
Uygulama genelinde ortak bileşenlerin nasıl yönetildiğini ve paylaşıldığını anlamak için bahsetmeye değer.
Şimdi, kodlamaya dalmadan önce testi tartışmak önemlidir. Uygulamanızın güvenilirliğini ve doğruluğunu sağlamak hayati öneme sahiptir ve mimarinin her katmanı için sağlam bir test stratejisi uygulamak çok önemlidir.
Mimarinin her katmanı için kapsamlı bir test stratejisi uygulayarak uygulamanızın güvenilirliğini, doğruluğunu ve sürdürülebilirliğini sağlarken geliştirme sırasında hata oluşma olasılığını da azaltabilirsiniz.
Ancak küçük bir uygulama geliştiriyorsanız adaptör katmanındaki entegrasyon testleri yeterli olacaktır.
Tamam, artık Temiz Mimari konusunda sağlam bir anlayışa sahip olduğunuza ve hatta bu konuda kendi fikrinizi oluşturduğunuza göre, biraz daha derine inelim ve bazı gerçek kodları inceleyelim.
Burada sadece basit bir örnek sunacağımı unutmayın; ancak daha ayrıntılı örneklerle ilgileniyorsanız, bu makalenin başında bahsedilen GitHub depomu incelemekten çekinmeyin.
"Gerçek hayatta" Temiz Mimari, büyük, kurumsal düzeydeki uygulamalarda gerçekten parlıyor, oysa daha küçük projeler için aşırıya kaçabilir. Bunu söyledikten sonra asıl meseleye geçelim.
Örnek olarak uygulamamı kullanarak, belirli bir kelime için sözlük önerilerini getirmek üzere bir API çağrısının nasıl gerçekleştirileceğini göstereceğim. Bu özel API uç noktası, iki web sitesini web kazıyarak anlamların ve örneklerin bir listesini alır.
İş açısından bakıldığında bu uç nokta, kullanıcıların belirli bir kelimeyi aramasına olanak tanıyan "Kelime Bul" görünümü için çok önemlidir. Kullanıcı sözcüğü bulup oturum açtığında, web'den alınan bilgileri Notion Veritabanına ekleyebilir.
Başlamak için daha önce tartıştığımız katmanları doğru şekilde yansıtan bir klasör yapısı oluşturmalıyız. Yapı aşağıdakine benzemelidir:
client ├── adapter ├── api ├── domain ├── presentation ├── repository └── shared
İstemci dizini birçok projedeki "src" klasörüne benzer bir amaca hizmet eder. Bu özel Next.js projesinde, ön uç klasörünü "istemci" ve arka uç klasörünü "sunucu" olarak adlandırma kuralını benimsedim.
Bu yaklaşım, uygulamanın iki ana bileşeni arasında net bir ayrım yapılmasını sağlar.
Projeniz için doğru klasör yapısını seçmek gerçekten de geliştirme sürecinin başlarında verilmesi gereken çok önemli bir karardır. Kaynakların düzenlenmesi söz konusu olduğunda farklı geliştiricilerin kendi tercihleri ve yaklaşımları vardır.
Bazıları kaynakları sayfa adlarına göre gruplandırabilir, diğerleri OpenAPI tarafından oluşturulan alt dizin adlandırma kurallarını takip edebilir ve yine de diğerleri uygulamalarının bu çözümlerden herhangi birini garanti edemeyecek kadar küçük olduğuna inanabilir.
Önemli olan, kaynakların açık ve sürdürülebilir bir organizasyonunu korurken, projenizin özel ihtiyaçlarına ve ölçeğine en iyi uyan yapıyı seçmektir.
Ben üçüncü gruptayım, dolayısıyla yapım şöyle görünüyor:
client ├── adapter │ ├── local-storage │ ├── rest │ ├── speech-synthesis │ └── supabase ├── api │ ├── local-storage │ ├── rest │ ├── speech-synthesis │ └── supabase ├── domain │ ├── local-storage │ ├── rest │ ├── speech-synthesis │ ├── supabase └── repository ├── local-storage ├── rest ├── speech-synthesis └── supabase
Daha derine inmek isteyenlerin daha fazla bilgi için arşivime başvurabileceğine inandığım için bu makaledeki paylaşım ve sunum katmanlarını atlamaya karar verdim. Şimdi Temiz Mimarinin bir ön uç uygulamada nasıl uygulanabileceğini göstermek için bazı kod örnekleriyle ilerleyelim.
İhtiyaçlarımızı göz önünde bulunduralım. Bir kullanıcı olarak anlamları ve örnekleriyle birlikte bir öneri listesi almak istiyorum. Bu nedenle tek bir sözlük önerisi şu şekilde modellenebilir:
interface DictionarySuggestion { example: string; meaning: string; }
Artık tek bir sözlük önerisini tanımladığımıza göre, bazen web kazıma yoluyla elde edilen kelimenin kullanıcının yazdığı kelimeyle karşılaştırıldığında farklı olduğunu veya düzeltildiğini belirtmek önemlidir. Buna uyum sağlamak için düzeltilmiş sürümü daha sonra uygulamamızda kullanacağız.
Sonuç olarak sözlük önerileri ve kelime düzeltmelerinin listesini içeren bir arayüz tanımlamamız gerekiyor. Son arayüz şuna benzer:
export interface DictionarySuggestions { suggestions: DictionarySuggestion[]; word: string; }
Bu arayüzü dışa aktarıyoruz, bu nedenle export
anahtar sözcüğü eklenmiştir.
Modelimiz elimizde, şimdi onu kullanma zamanı.
import { DictionarySuggestions } from './rest.models'; export interface RestRepository { getDictionarySuggestions: (word: string) => Promise<DictionarySuggestions | null>; }
Bu noktada her şeyin açık olması gerekiyor. Burada API'yi hiç tartışmadığımızı unutmamak önemlidir! Deponun yapısı oldukça basittir: her yöntemin belirli bir türdeki verileri eşzamansız olarak döndürdüğü bazı yöntemleri içeren bir nesne.
Lütfen havuzun verileri her zaman etki alanı modeli biçiminde döndürdüğünü unutmayın.
Şimdi iş kuralımızı bir kullanım durumu olarak tanımlayalım. Kod şuna benzer:
export type GetDictionarySuggestionsUseCaseUseCase = UseCaseWithSingleParamAndPromiseResult< string, DictionarySuggestions | null >; export const getDictionarySuggestionsUseCase = ( restRepository: RestRepository, ): GetDictionarySuggestionsUseCaseUseCase => ({ execute: (word) => restRepository.getDictionarySuggestions(word), });
Dikkat edilmesi gereken ilk şey, kullanım durumlarını tanımlamak için kullanılan yaygın türlerin listesidir. Bunu başarmak için etki alanı dizininde bir use-cases.types.ts
dosyası oluşturdum:
domain ├── local-storage ├── rest ├── speech-synthesis ├── supabase └── use-cases.types.ts
Bu, alt dizinlerim arasında kullanım senaryolarına yönelik türleri kolayca paylaşmamı sağlıyor. UseCaseWithSingleParamAndPromiseResult
tanımı şuna benzer:
export interface UseCaseWithSingleParamAndPromiseResult<TParam, TResult> { execute: (param: TParam) => Promise<TResult>; }
Bu yaklaşım, etki alanı katmanı genelinde kullanım senaryosu türlerinin tutarlılığının ve yeniden kullanılabilirliğinin korunmasına yardımcı olur.
execute
işlevine neden ihtiyacımız olduğunu merak ediyor olabilirsiniz. Burada gerçek kullanım durumunu döndüren bir fabrikamız var.
Bu tasarım seçimi, kullanım senaryosu kodunda depo uygulamasına doğrudan referans vermek istemememizden veya deponun bir içe aktarma tarafından kullanılmasını istemememizden kaynaklanmaktadır. Bu yaklaşım daha sonra bağımlılık enjeksiyonunu kolayca uygulamamıza olanak tanır.
Fabrika modelini ve execute
işlevini kullanarak, havuzun uygulama ayrıntılarını kullanım senaryosu kodundan ayrı tutabiliriz, bu da uygulamanın modülerliğini ve sürdürülebilirliğini artırır.
Bu yaklaşım, etki alanı katmanının başka herhangi bir katmana bağlı olmadığı Bağımlılığı Tersine Çevirme İlkesini takip eder ve farklı depo uygulamalarının değiştirilmesi veya uygulamanın mimarisinin değiştirilmesi söz konusu olduğunda daha fazla esneklik sağlar.
Öncelikle arayüzümüzü tanımlayalım:
export interface RestApi { getDictionarySuggestions: (word: string) => Promise<AxiosResponse<DictionarySuggestions>>; }
Gördüğünüz gibi, bu fonksiyonun arayüzdeki tanımı depodakine çok benzer. Etki alanı türü yanıtı zaten tanımladığından aynı türü yeniden oluşturmaya gerek yoktur.
API'mızın ham verileri döndürdüğünü unutmamak önemlidir; bu nedenle AxiosResponse<DictionarySuggestions>
öğesinin tamamını döndürüyoruz. Bunu yaparak, API ve etki alanı katmanları arasında net bir ayrım sağlayarak veri işleme ve dönüştürmede daha fazla esneklik sağlıyoruz.
Bu API'nin uygulanması şuna benzer:
export const getRestApi = (axiosInstance: AxiosInstance): RestApi => ({ getDictionarySuggestions: async (word: string) => { const encodedCurrentDate = encodeURIComponent(word); const response = await axiosInstance.get( `${RestEndpoints.GET_DICTIONARY_SUGGESTIONS}?word=${encodedCurrentDate}`, ); return response; } });
Bu noktada işler daha da ilginçleşiyor. Tartışılacak ilk önemli husus, axiosInstance
enjeksiyonudur. Bu, kodumuzu çok esnek hale getirir ve kolayca sağlam testler oluşturmamızı sağlar. Burası aynı zamanda sorgu parametrelerinin kodlanmasını veya ayrıştırılmasını da gerçekleştirdiğimiz yerdir.
Ancak burada giriş dizesini kırpmak gibi başka eylemleri de gerçekleştirebilirsiniz. axiosInstance
enjekte ederek endişelerin net bir şekilde ayrılmasını sağlıyoruz ve API uygulamasının farklı senaryolara veya harici hizmetlerdeki değişikliklere uyarlanabilir olmasını sağlıyoruz.
Arayüzümüz zaten alan adı tarafından tanımlandığından tek yapmamız gereken depomuzu uygulamaktır. Yani son uygulama şöyle görünür:
export const getRestRepository = (restApi: RestApi): RestRepository => ({ getDictionarySuggestions: async (word) => { const { data } = await restApi.getDictionarySuggestions(word); if (!data?.suggestions?.length) { return null; } return formatDictionarySuggestions(data); } });
Bahsedilmesi gereken önemli bir husus API'lerle ilgilidir. getRestRepository
önceden tanımlanmış bir restApi
aktarmamıza olanak tanır. Bu avantajlıdır çünkü daha önce de belirtildiği gibi testlerin daha kolay yapılmasını sağlar. formatDictionarySuggestions
kısaca inceleyebiliriz:
export const formatDictionarySuggestions = ({ suggestions, word, }: DictionarySuggestions): DictionarySuggestions => { const cleanedWord = cleanUpString(word); const cleanedSuggestions = suggestions.map((_suggestion) => { const cleanedMeaning = cleanUpString(_suggestion.meaning); const cleanedExample = cleanUpString(_suggestion.example); return { meaning: cleanedMeaning, example: cleanedExample, }; }); return { word: cleanedWord, suggestions: cleanedSuggestions, }; };
Bu işlem, etki alanı DictionarySuggestions
modelimizi bağımsız değişken olarak alır ve bir dize temizliği gerçekleştirir; bu, gereksiz boşlukların, satır sonlarının, sekmelerin ve büyük harflerin kaldırılması anlamına gelir. Hiçbir gizli karmaşıklık olmadan oldukça basittir.
Unutulmaması gereken önemli bir nokta, bu noktada API uygulamanız konusunda endişelenmenize gerek olmamasıdır. Bir hatırlatma olarak, depo her zaman etki alanı modelindeki verileri döndürür! Aksi olamaz çünkü bunu yapmak bağımlılığın tersine çevrilmesi ilkesini ihlal eder.
Ve şimdilik etki alanı katmanımız onun dışında tanımlanan hiçbir şeye bağlı değil.
Bu noktada her şeyin uygulanması ve bağımlılık enjeksiyonuna hazır olması gerekir. İşte dinlenme modülünün son uygulaması:
import { getRestRepository } from '@repository/rest/rest.repository'; import { getRestApi } from '@api/rest/rest.api'; import { getDictionarySuggestionsUseCase } from '@domain/rest/rest.use-cases'; import { axiosInstance } from '@shared/axios.instance'; const restApi = getRestApi(axiosInstance); const restRepository = getRestRepository(restApi); export const restModule = { getDictionarySuggestions: getDictionarySuggestionsUseCase(restRepository).execute, };
Bu doğru! Temiz Mimari ilkelerini belirli bir çerçeveye bağlı kalmadan hayata geçirme sürecini yaşadık. Bu yaklaşım, kodumuzun uyarlanabilir olmasını sağlar ve gerektiğinde çerçeveler veya kitaplıklar arasında geçiş yapmayı kolaylaştırır.
Test söz konusu olduğunda, depoyu kontrol etmek, testlerin bu mimaride nasıl uygulandığını ve organize edildiğini anlamanın harika bir yoludur.
Temiz Mimari'de sağlam bir temele sahip olduğunuzda, çeşitli senaryoları kapsayan kapsamlı testler yazabilir, uygulamanızı daha sağlam ve güvenilir hale getirebilirsiniz.
Gösterildiği gibi, Temiz Mimari ilkelerini takip etmek ve endişeleri ayırmak, sürdürülebilir, ölçeklenebilir ve test edilebilir bir uygulama yapısına yol açar.
Bu yaklaşım sonuçta yeni özellikler eklemeyi, kodu yeniden düzenlemeyi ve bir proje üzerinde bir ekiple çalışmayı kolaylaştırarak uygulamanızın uzun vadeli başarısını garanti eder.
Örnek uygulamada sunum katmanı için React kullanılmıştır. Bağdaştırıcı dizininde dinlenme modülüyle etkileşimi yöneten hooks.ts
adında ek bir dosya vardır. Bu dosyanın içeriği aşağıdaki gibidir:
import { restModule } from '@adapter/rest/rest.module'; import { useAxios } from '@shared/hooks'; export const useDictionarySuggestions = () => { const { data, error, isLoading, mutate } = useAxios(restModule.getDictionarySuggestions); return { dictionarySuggestions: data, getDictionarySuggestions: mutate, dictionarySuggestionsError: error, isDictionarySuggestionsLoading: isLoading, }; };
Bu uygulama sunum katmanıyla çalışmayı inanılmaz derecede kolaylaştırır. useDictionarySuggestions
kancasını kullanarak sunum katmanının, veri eşlemelerini veya birincil işleviyle ilgisi olmayan diğer sorumlulukları yönetme konusunda endişelenmesine gerek kalmaz.
Bu endişelerin ayrılması, Temiz Mimari ilkelerinin korunmasına yardımcı olarak daha yönetilebilir ve bakımı kolay kodlara yol açar.
Öncelikle ve en önemlisi, sağlanan GitHub deposundaki koda dalmanızı ve yapısını keşfetmenizi öneririm.
Başka ne yapabilirim? Sınır gökyüzü! Her şey özel tasarım ihtiyaçlarınıza bağlıdır. Örneğin, bir veri deposu (Redux, MobX veya hatta özel bir şey - fark etmez) ekleyerek veri katmanını uygulamayı düşünebilirsiniz.
Alternatif olarak, yoklama, anlık bildirimler veya soketleri (esasen herhangi bir veri kaynağı için hazırlanmayı) içerebilen arka uçla eşzamansız iletişimi yönetmek için RxJS kullanmak gibi katmanlar arasında farklı iletişim yöntemlerini deneyebilirsiniz.
Temel olarak, katmanlı mimariyi koruduğunuz ve ters bağımlılık ilkesine bağlı kaldığınız sürece dilediğiniz gibi keşfetmekten ve denemekten çekinmeyin. Her zaman alan adının tasarımınızın merkezinde olduğundan emin olun.
Bunu yaparak, çeşitli senaryolara ve gereksinimlere uyum sağlayabilecek esnek ve sürdürülebilir bir uygulama yapısı oluşturacaksınız.
Bu makalede, React kullanılarak oluşturulan bir dil öğrenme uygulaması bağlamında Temiz Mimari kavramını derinlemesine inceledik.
Katmanlı bir mimariyi korumanın ve ters bağımlılık ilkesine bağlı kalmanın öneminin yanı sıra endişeleri ayırmanın faydalarını vurguladık.
Temiz Mimarinin önemli bir avantajı, belirli bir çerçeveye bağlı kalmadan uygulamanızın mühendislik yönüne odaklanmanıza izin vermesidir. Bu esneklik, uygulamanızı çeşitli senaryolara ve gereksinimlere uyarlamanıza olanak tanır.
Ancak bu yaklaşımın bazı dezavantajları vardır. Bazı durumlarda katı bir mimari modeli takip etmek, standart kodun artmasına veya proje yapısında ilave karmaşıklığa yol açabilir.
Ek olarak, belgelere daha az güvenmek hem olumlu hem de olumsuz olabilir; daha fazla özgürlük ve yaratıcılığa izin verirken aynı zamanda ekip üyeleri arasında kafa karışıklığına veya yanlış iletişimle de sonuçlanabilir.
Bu potansiyel zorluklara rağmen Temiz Mimarinin uygulanması, özellikle evrensel olarak kabul edilmiş bir mimari modelin bulunmadığı React bağlamında son derece faydalı olabilir.
Mimarinizi, yıllarca uğraştıktan sonra ele almak yerine, bir projenin başlangıcında düşünmek önemlidir.
Temiz Mimarinin gerçek hayattaki bir örneğini uygulamalı olarak keşfetmek için şu adresteki depoma göz atmaktan çekinmeyin:
Vay, bu muhtemelen şimdiye kadar yazdığım en uzun makale. İnanılmaz hissettiriyor!