SOLID - Erken Soyutlamanın Önlenmesi


27

Ben ne olduğunu anlamak KATI başarmak ve modülerlik önemlidir ve onun hedefleri açıkça faydalıdır durumlarda düzenli kullanmak gerekiyordu. Ancak, iki şey benim kod tabanımda tutarlı bir şekilde uygulamamı engelliyor:

  • Erken soyutlamadan kaçınmak istiyorum. Tecrübelerime göre somut kullanım senaryoları olmadan soyutlama çizgileri çizmek (şimdiki veya öngörülebilir gelecekte var olan türler ) yanlış yerlere çekilmelerine neden olmaktadır. Bu tür bir kodu değiştirmeye çalıştığımda, soyutlama çizgileri yardım etmekten çok yol alıyor. Bu nedenle, nerede yararlı olacağına dair iyi bir fikrim olana kadar soyutlama çizgileri çizmemeye yanlıyorum.

  • Eğer kodumu daha ayrıntılı, anlaşılması zor, vb. Yaparsa ve herhangi bir kopyalamayı ortadan kaldırmazsa, kendi iyiliği için artan modülerliği haklı çıkarmakta zorlanıyorum. Akış basit ve doğrusal olduğundan basit, sıkı bir şekilde birleştirilmiş prosedür veya Tanrı nesne kodunun anlaşılması bazen çok iyi faktörlü mantı kodundan daha kolaydır. Ayrıca yazmak çok daha kolay.

Öte yandan, bu zihniyet genellikle Tanrı'nın nesnelerine yol açar. Genelde bunları muhafazakar bir şekilde yeniden yansıtıyorum, yalnızca net desenler ortaya çıktığında net soyutlama çizgileri ekliyorum. Eğer herhangi bir şey varsa, Tanrı'nın nesnelerinde yanlış olan ve açıkça daha fazla modülerliğe ihtiyacınız yoksa sıkıca birleştirilmiş kod nedir, önemli bir çoğaltmaya sahip değilsiniz ve kod okunabilir mi?

EDIT: Bireysel SOLID ilkelerine gelince, Liskov Sübstitüsyonunun IMHO'nun sağduyuyu biçimlendirdiğini ve soyutlamalar yapılmadığı için her yerde uygulanması gerektiğini vurgulamak istedim. Ayrıca, her sınıfın belirli bir soyutlama düzeyinde tek bir sorumluluğu bulunmalıdır, ancak uygulama ayrıntılarının tümü büyük bir 2.000 satır sınıfında toplanmasıyla çok yüksek olabilir. Temel olarak, soyutlamalarınız, soyutlamayı seçtiğiniz yeri anlamalıdır. Modülerliğin açıkça yararlı olmadığı durumlarda sorduğum ilkeler açık-kapalı, arayüz ayrımı ve özellikle bağımlılık inversiyonu çünkü bunlar sadece soyutlamalar anlamında değil, modülerlikle ilgili.


10
@ S.Lott: Anahtar kelime "daha" dır. Bu tam olarak YAGNI'nin icat ettiği türden bir şey. Modülerliği artırmak veya sadece kendi iyiliği için kuplajı azaltmak sadece kargo kültü programlamasıdır.
Mason Wheeler,

3
@ S.Lott: Bu bağlamdan açıkça anlaşılmalıdır. Okuduğum gibi, en azından, "söz konusu kodda şu anda olduğundan daha fazlası var."
Mason Wheeler

3
@ S.Lott: Pedantik olmakta ısrar ediyorsanız, "daha fazlası" şu anda var olandan daha fazlasını ifade eder. Bunun anlamı, kod veya kaba bir tasarım olsun, zaten var olan bir şeydir ve siz onu nasıl yeniden yapılandırmayı düşündüğünüzdür.
dsimcha

5
@ back2dos: Doğru, ama nasıl genişletilebileceği konusunda net bir fikir olmadan, genişletilebilirlik için bir şeyler tasarlamaya şüpheleniyorum. Bu bilgi olmadan, soyutlama çizgileriniz muhtemelen tüm yanlış yerlerde olacaktır. Soyutlama çizgilerinin nerede yararlı olabileceğini bilmiyorsanız, orada atılan birkaç Tanrı nesnesine sahip olsanız bile, çalışacak ve okunabilir en özlü kodu yazmanız gerektiğini öneriyorum.
dsimcha

2
@dsimcha: Bir kod yazdıktan sonra gereksinimler değişirse şanslısınız , çünkü bunu yaparken genellikle değişiyorlar . Bu nedenle anlık görüntü uygulamaları gerçek bir yazılım ömrü boyunca hayatta kalmak için uygun değildir. Ayrıca, SOLID sizden sadece kör olarak soyut yapmanızı talep etmiyor. Bir soyutlamanın bağlamı bağımlılık inversiyonu ile tanımlanır. Her modülün bağımlılığını, dayandığı diğer hizmetlerin en basit ve net soyutlamasına indirgiyorsunuz. Keyfi, yapay veya karmaşık değil, iyi tanımlanmış, makul ve basit.
back2dos

Yanıtlar:


8

Sistem tasarımınızı nasıl dengeleyeceğinizi anlamanıza yardımcı olmak için uygulayabileceğiniz basit ilkeler şunlardır:

  • Tek Sorumluluk İlkesi: SKATI içinde. Yöntem sayısı veya veri miktarı açısından çok büyük bir nesneye sahip olabilirsiniz ve bu prensibi hala koruyorsunuz. Örneğin Ruby String nesnesini alın. Bu nesnenin bir çubuğu sallayabileceğinizden çok daha fazla yöntemi var, ancak yine de yalnızca bir sorumluluğu var: uygulama için bir metin dizesi tutun. Hedefiniz yeni bir sorumluluk üstlenmeye başlar başlamaz, bunun hakkında çok düşünmeye başlayın. Bakım sorunu kendinize soruyor "daha sonra sorun yaşarsam bu kodu nerede bulabilirim?"
  • Sadelik sayar: Albert Einstein "Her şeyi mümkün olduğunca basitleştirin, ancak basitleştirmeyin" dedi. Bu yeni yönteme gerçekten ihtiyacın var mı? Mevcut işlevsellik ile ihtiyacınız olanı başarabilir misiniz? Gerçekten yeni bir yöntem olması gerektiğini düşünüyorsanız, ihtiyacınız olan her şeyi karşılamak için mevcut bir yöntemi değiştirebilir misiniz? Özünde, yeni şeyler inşa ederken refactor.

Temel olarak, yazılımı koruma zamanı geldiğinde ayağınıza ateş etmemeniz için elinizden geleni yapmaya çalışıyorsunuz. Büyük nesneleriniz makul soyutlamalar ise, o zaman birisini bir sınıfın X satırından / yöntem / özellik / vb. Bir şey varsa, bunlar kurallardır ve zor ve hızlı kurallar değildir.


3
İyi yorum. Diğer cevaplarda tartışıldığı gibi, "tek sorumluluk" ile ilgili bir sorun, bir sınıfın sorumluluğunun çeşitli soyutlama seviyelerinde tanımlanabilmesidir.
dsimcha

5

Bence çoğu zaman kendi soruna cevap verdin. SOLID, kavramların soyutlama seviyelerini artırması gerektiğinde kodunuzu nasıl yeniden yapılandırmanız gerektiğine dair bir dizi kuraldan oluşur.

Diğer tüm yaratıcı disiplinlerde olduğu gibi mutlaklık yoktur - sadece tradeofflar Ne kadar çok yaparsanız, "sorun" ne kadar kolaysa o anki sorun alanınız veya gereksinimleriniz için ne zaman yeterli olacağına karar verin.

Bunu söylemek - soyutlamak yazılım geliştirmenin kalbidir - bu yüzden yapmamak için iyi bir neden yoksa, uygulama sizi daha iyi hale getirecek ve takaslar için içgüdüsel bir his duyacaksınız. Öyleyse, zararlı olmadıkça tercih edin.


5
I want to avoid premature abstraction.In my experience drawing abstraction lines without concrete use cases... 

Bu kısmen doğru ve kısmen yanlış.

Yanlış
Bu, bir OO ilkesi / SOLID uygulamamasının bir nedeni değildir. Sadece çok erken uygulanmasını önler .

Hangisi...

Doğru
, yeniden birleştirilinceye kadar yeniden kodlama yapmayın; ihtiyaçlar tamamlandığında. Veya, "kullanım davaları" dediğiniz gibi hepsi orada olduğunda.

I find simple, tightly coupled procedural or God object code is sometimes easier to understand than very well-factored...

Tek başına veya siloda çalışırken
OO yapmama sorunu hemen belli değildir. Bir programın ilk sürümünü yazdıktan sonra:

Code is fresh in your head
Code is familiar
Code is easy to mentally compartmentalize
You wrote it

Bu iyi şeylerin 3 / 4'ü kısa sürede kısa sürede ölür.

Sonunda, Tanrı nesnelerine sahip olduğunuzu (birçok işlevi olan nesneler) tanıdığınız için bireysel işlevleri tanıyorsunuz. Kapsüllemek. Onları klasörlere yerleştirin. Arabirimleri arada bir kullanın. Uzun süreli bakım için kendinize bir iyilik yapın. Özellikle yeniden yapılandırılmamış yöntemler sınırsız şişirmek ve Tanrı yöntemi olmak eğilimindedir.

Bir takımda
OO yapmama problemleri hemen fark edilir. İyi OO kodu en azından biraz kendi kendini belgeliyor ve okunuyor. Özellikle iyi yeşil kodla birleştirildiğinde. Ayrıca, yapı eksikliği görevleri ayırmayı ve entegrasyonu çok daha karmaşık hale getirir.


Sağ. Objelerimin birden fazla şey yaptığını belli belirsiz olarak biliyorum, ancak bakım yapılması gerektiğinde soyutlama çizgilerinin doğru yerlerde olması için onları nasıl yararlı bir şekilde parçalayacağını daha somut olarak tanımıyorum . Bakım programcısının soyutlama yollarını doğru şekilde almak için muhtemelen çok daha fazla yeniden düzenleme yapması gerekecekse, yeniden uçurmak için zaman kaybı gibi görünüyor.
dsimcha

Kapsülleme ve soyutlama iki farklı kavramdır. Kapsülleme, temelde sınıfınız olduğu anlamına gelen temel bir OO konseptidir. Sınıflar kendi içinde modülerlik ve okunabilirlik sağlar. Bu faydalı.
P.Brian.Mackey

Soyutlama, doğru uygulandığında bakımı azaltabilir. Yanlış uygulanırsa bakımı artırabilir. Çizgilerin ne zaman ve nerede çizileceğini bilmek, kendi başına “fabrika modelini nasıl uygulayacağız” ın temel teknik yönlerine ek olarak iş, çerçeve ve müşterinin sağlam bir şekilde anlaşılmasını gerektirir.
P.Brian.Mackey

3

Büyük nesnelerde yanlış bir şey yoktur ve uygun olduklarında ve daha iyi bir mühendislik yapılması gerekmediğinde sıkı bir şekilde birleştirilmiş kod vardır . Bu, dogmaya dönüşen bir kuralın bir başka tezahürü .

Gevşek bağlanma ve küçük, basit nesneler birçok genel durumda özel faydalar sağlama eğilimindedir, bu nedenle genel olarak bunları kullanmak iyi bir fikirdir. Sorun, uygulanmayan yerlerde bile, evrensel olarak uygulamaya çalışırken ilkelerin arkasındaki mantığı anlamayan insanlarda yatmaktadır.


1
+1. Yine de "uygun" un ne anlama geldiğinin iyi bir tanımına ihtiyaç var.
jprete

2
@jprete: Neden? Mutlak tanımlamalar yapmaya çalışmak, bunun gibi kavramsal mesajların nedeninin bir parçasıdır . İyi yazılım yapımında çok işçilik var. Gerçekten ihtiyaç duyulan IMO deneyim ve iyi yargılamadır.
Mason Wheeler

4
Evet, ama geniş bir tanım bazı tür hala yararlıdır.
jprete

1
Uygun bir tanımlamaya sahip olmak faydalı olabilir, ama mesele bu. Sesli bir ısırık yerine oturtmak zordur, çünkü yalnızca duruma göre uygulanabilir. Her davada uygun seçimi yapıp yapmamanız büyük ölçüde tecrübedir. Neden yüksek uyumunuz olduğunu açıkça söyleyemiyorsanız, monolitik çözüm düşük bir uyumluluktan, yüksek modüler bir çözümden daha iyidir, düşük olasılıklı ve modüler olmaktan "muhtemelen" daha iyi olurdu. Refaktör yapmak her zaman daha kolaydır.
Ian

1
Kör spagetti kodu yazmak yerine, kör bir şekilde dekuplaj kodu yazmayı tercih ediyorum :)
Boris Yankov

2

Buna daha fazla ihtiyacın olmayacak bir noktadan yaklaşma eğilimindeyim. Bu gönderi özellikle bir maddeye odaklanacak: miras.

İlk tasarımımda, iki veya daha fazla olacağını bildiğim şeyler hiyerarşisini yaratıyorum. Şansları aynı koda çok ihtiyaç duyacakları için, en baştan tasarlamaya değer. İlk kod yapıldıktan sonra ve daha fazla özellik / işlevsellik eklemem gerekiyor, sahip olduğum şeye baktım ve "Zaten aynı veya benzer bir işlevi uyguladı mı?" Eğer öyleyse, bu büyük olasılıkla serbest bırakılmaya dilen yeni bir soyutlama.

Buna iyi bir örnek, bir MVC çerçevesidir. Sıfırdan başlayarak, arkasında kod olan büyük bir sayfa yaratırsınız. Ama sonra başka bir sayfa eklemek istiyorsun. Ancak, arkasındaki kod zaten yeni sayfanın ihtiyaç duyduğu bir çok mantığı uygulamaktadır. Bu nedenle, orijinal "tanrı" kodunun ardında ortak şeyler bırakarak, o sayfaya özelController mantığı uygulayacak bir sınıf / arayüz soyutlarsınız .


1

Bir geliştirici olarak SİZİN kodun geleceği nedeniyle ilkeleri ne zaman UYGULAMAMASI gerektiğini biliyorsanız, o zaman sizin için iyi.

Umarım, SOLID, karmaşıklığı önlemek ve işlerin belirttiğiniz değerlerde bozulmaya başlaması durumunda kodun kalitesini iyileştirmek için ne zaman özetlenmesi gerektiğini bilmek için aklınızın arkasında kalır.

Daha önemlisi, geliştiricilerin çoğunluğunun günlük işi yaptığını ve sizin kadar önemli olmadığını düşünün. Başlangıçta uzun süre çalışan yöntemler belirlediyseniz, koda geldiğinde veya genişlettiğinde ne olacağını düşünecek kodun diğer geliştiricileri nelerdir? ... tanrı nesnelere ve büyüyen kodu yakalayabilmek ve doğru şekilde kaplayabilmek için akılda tutulması gereken ilkelere sahip değiller. "Okunabilir" kodunuz artık çürüyen bir karmaşaya dönüşüyor.

Dolayısıyla, kötü bir geliştiricinin bunu ne olursa olsun yapabileceğini iddia edebilirsiniz, ancak en azından işler basit ve iyi organize edildiğinde daha iyi bir avantaja sahip olursunuz.

Özellikle basit bir "Küresel Kayıt Defteri Haritası" veya "Tanrı Nesnesi" umursamıyorum. Bu gerçekten sistem tasarımına bağlıdır, bazen ondan kurtulabilir ve basit kalabilirsiniz, bazen yapamazsınız.

Ayrıca, büyük işlevlerin ve Tanrı Nesnelerinin test etmenin son derece zor olduğunu kanıtlayamadığını da unutmayın. Kodu yeniden faktoring ederken ve değiştirirken Çevik olmak ve "Güvenli" hissetmek istiyorsanız, testlere ihtiyacınız var. İşlevler veya nesneler çok şey yaptığında testler yazmak zordur.


1
Temelde iyi bir cevap. Benim tek yakınlığım, eğer bir bakım geliştiricisi gelir ve bir karışıklık yaparsa, bu gibi değişiklikler kendileri için planlamayı haklı çıkaracak kadar önceden öngörülemeyecek kadar muhtemel görünmüyorsa ya da kod çok kötü belgelendirilmiş / test edilmiş / vb. . Bu yeniden yapılanmanın bir tür delilik olabileceğini söyledi.
dsimcha

Bu doğru dsimcha. Sadece bir geliştiricinin "RequestHandlers" klasörü oluşturduğu ve o klasörün altındaki her sınıfın bir istek işleyicisi olduğunu düşündüğüm bir sistemde düşündüm, sonra gelen ve "Yeni bir istek işleyicisi eklemem gerek" diye düşünen bir sonraki geliştirici, Mevcut altyapı neredeyse onu sözleşmeyi izlemesi için zorluyor. Sanırım söylemeye çalıştığım şey buydu. Baştan itibaren açık bir kongre kurmak, en deneyimsiz geliştiricilere bile kalıba devam etmeleri için rehberlik edebilir.
Martin Blore

1

Bir tanrı nesnesindeki sorun, genellikle karlı bir şekilde parçalara ayırmanızdır. Tanım olarak, birden fazla şey yapar. Daha küçük sınıflara ayırmanın amacı, bir şeyi iyi yapan bir sınıfa sahip olmaktır (ve "bir şeyin" tanımını da uzatmamalısınız). Bu, herhangi bir sınıf için yapması gereken bir şeyi öğrendiğinizde, onu kolayca okuyabileceğiniz ve o şeyi doğru yapıp yapmadığını söyleyebileceğiniz anlamına gelir.

Orada düşünüyorum olduğunu çok fazla modülerlik ve çok fazla esnekliğe sahip olarak böyle bir şey, ama bu en fazla aşırı tasarım ve aşırı mühendislik probleminin nerede olduğunu bile müşterinin istediği bilmiyorum gereksinimleri için sen muhasebe. Pek çok tasarım fikri, kodun nasıl yürüdüğüne dair değişiklikleri kontrol etmeyi kolaylaştırmak için yönlendirilir, ancak kimse değişikliği beklemiyorsa, esnekliği eklemek anlamsızdır.


Hangi seviyede soyutlamaya çalıştığınıza bağlı olarak "birden fazla şey yapar" tanımlaması zor olabilir. İki veya daha fazla kod satırı içeren herhangi bir yöntemin birden fazla şey yaptığı söylenebilir. Spektrumun diğer ucunda, bir komut dosyası motoru gibi karmaşık bir şey, hepsinin doğrudan birbiriyle doğrudan ilgili olmayan, ancak her biri “meta "komut dosyalarınızın düzgün çalışmasını sağlayan şey" ve komut dosyası motorunu bozmadan yapılabilecek çok fazla parçalama var.
Mason Wheeler

Orada kavramsal düzeyde bir spektrum kesinlikle, ama biz olabilir üzerinde bir nokta seçmek: "tek şeyi yapar sınıfın" boyutu neredeyse hemen uygulanmasını anlayabileceği şekilde olmalıdır. Yani uygulama detayları kafanıza uyar. Eğer büyürse, o zaman tüm sınıfı bir kerede anlayamazsınız. Daha küçükse, o zaman çok uzağa çekiyorsun Ancak başka bir yorumda dediğiniz gibi, çok fazla yargı ve deneyim var.
jprete

IMHO, düşünülecek en iyi soyutlama seviyesi, tüketicinin kullanmasını beklediğiniz seviyedir. Diyelim ki Queryerveritabanı sorgularını en iyi duruma getiren, RDBMS'yi sorgulayan ve sonuçları geri döndürmek üzere nesnelere ayıran bir nesne olduğunu söyleyin . Bunu uygulamanızda yapmanın tek bir yolu varsa ve Queryerhava geçirmez bir şekilde kapatılmış ve bunu bir şekilde kapsıyorsa, o zaman sadece bir şey yapar. Bunu yapmanın birden fazla yolu varsa ve birisi bir bölümünün ayrıntılarını önemseyebilirse, o zaman birden çok şey yapar ve onu bölmek isteyebilirsiniz.
dsimcha

1

Daha basit bir kılavuz kullanıyorum: bunun için birim sınamaları yazabiliyorsanız ve kod çoğaltması yoksa, yeterince soyut. Ayrıca, daha sonra yeniden düzenleme için iyi bir pozisyondasın.

Bunun ötesinde, SOLID'i aklınızda tutmalısınız, ancak bir kuraldan çok bir rehber olarak.


0

Bir şey varsa, Tanrı'nın nesnelerinde yanlış olan ve açıkça daha fazla modülerliğe ihtiyacınız yoksa sıkıca birleştirilmiş kod nedir, önemli bir çoğaltmaya sahip değilsiniz ve kod okunabilir mi?

Uygulama yeterince küçükse, her şey korunabilir. Daha büyük uygulamalarda, Tanrı nesneleri hızla bir sorun haline gelir. Sonunda yeni bir özellik uygulamak için 17 tanrı nesnesinin değiştirilmesi gerekiyor. 17 adımlık prosedürleri takip eden insanlar pek iyi iş çıkarmıyor. Tanrı objeleri, birçok geliştirici tarafından sürekli olarak değiştirilmektedir ve bu değişikliklerin tekrar tekrar birleştirilmesi gerekmektedir. Oraya gitmek istemiyorsun.


0

Aşırı ve uygunsuz soyutlama hakkındaki endişelerinizi paylaşıyorum, ancak erken soyutlama konusunda mutlaka endişelenmiyorum.

Muhtemelen bir çelişki gibi görünebilir, ancak bir soyutlamayı kullanmak çok erken bir şeyden fazla abartmadığınız sürece bir soruna yol açması muhtemel değildir - yani gerektiğinde yeniden istekli ve istekli olduğunuz sürece.

Bunun anlamı, koddaki bir miktar prototip oluşturma, deneme ve geri izlemedir.

Bununla birlikte, tüm problemleri çözecek basit bir deterministik kural yoktur. Tecrübe çok şey sayar, ancak bu deneyimi hata yaparak kazanmanız gerekir. Ve önceki hataların sizi hazırlamayacağına karar vermek için her zaman daha fazla hata vardır.

Buna rağmen, ders kitabı ilkelerini bir başlangıç ​​noktası olarak ele alın, ardından programlama lotlarını ve bu ilkelerin nasıl işlediğini görmeyi öğrenin. SOLID gibi şeylerden daha iyi, daha kesin ve güvenilir kurallar vermek mümkün olsaydı, muhtemelen birileri şimdi bunu yapardı - ve olsalar bile, bu iyileştirilmiş ilkeler hala kusurlu olurdu ve insanlar bu sınırlamaları soruyorlardı. .

İyi iş de - herhangi biri program tasarlama ve kodlama için açık ve belirleyici bir algoritma sağlayabilirse, insanların yazması için son bir program olurdu - gelecekteki tüm programları insan müdahalesi olmadan otomatik olarak yazacak program.


0

Uygun soyutlama çizgilerini çizmek, kişinin tecrübe edindiği bir şeydir. Bunu yaparken hatalar yaparsınız, bu inkar edilemez.

SOLID, bu deneyimi zor yoldan edinen insanlar tarafından size verilen konsantre bir formdur. Bir ihtiyaç görmeden önce soyutlama yapmaktan kaçınacağınızı söylerken, onu çok fazla çivilenmişsinizdir. Peki, SOLID size sağladığı deneyim, asla var olmadığınız sorunları çözmenize yardımcı olacaktır . Ama güven bana ... çok gerçek var.

SOLID modülerlikle ilgili, modülerlik sürdürülebilirlikle ilgili ve bakım yapılabilirlik, yazılım üretime ulaştığında ve müşteri sizin sahip olmadığınız hataları fark etmeye başladığında insancıl bir çalışma programını sürdürmenize izin vermeyle ilgili.

Modülerliğin en büyük yararı test edilebilirliktir. Sisteminiz ne kadar modüler olursa, test etmesi o kadar kolay olur ve daha hızlı bir şekilde sorununuzu daha da zorlaştıracak sağlam temeller oluşturabilirsiniz. Bu nedenle, probleminiz bu modülerliği gerektirmeyebilir, ancak daha hızlı bir şekilde daha iyi bir test kodu oluşturmanıza izin vermesi gerçeği, modülerlik için çaba sarf etmek akıllıca değildir.

Çevik olmak, hızlı sevkiyat ve iyi kalite sağlama arasındaki hassas dengeyi bozmaya çalışmakla ilgilidir. Çevik, köşeyi kesmemiz gerektiği anlamına gelmiyor, aslında benim birlikte olduğum en başarılı çevik projeler, bu ilkelere çok dikkat eden projeler.


0

Göz ardı edilmiş gibi görünen önemli bir nokta, SOLID'in TDD ile birlikte uygulanıyor olmasıdır. TDD, kendi bağlamınızdaki "neyin" uygun olduğunu vurgulama ve tavsiyede göründüğü gibi bir çok eşleşmenin hafifletilmesine yardımcı olma eğilimindedir.


1
Lütfen cevabınızı genişletmeyi düşünün. Haliyle, iki ortogonal kavramı bir araya getiriyorsunuz ve sonucun OP'nin kaygılarını nasıl ele aldığı belli değil.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.