Aynı üyeli fakat farklı isimlendirmeli iki yapı, iyi bir fikir mi?


49

Hem kutupsal hem de Kartezyen koordinatlarıyla çalışmayı içeren bir program yazıyorum.

O anlamda noktaları ile birinin her türlü iki farklı yapılar oluşturmak için yapıyor mu Xve Yüyeleri ve bir ile Rve Thetaüyeler.

Yoksa çok mu fazla ve üyeli firstve tek bir yapıya sahip olmak daha iyi second.

Yazdıklarım basit ve fazla değişmeyecek. Ancak tasarım açısından neyin daha iyi olduğunu merak ediyorum.

İlk seçeneğin daha iyi olduğunu düşünüyorum. Daha okunaklı görünüyor ve tip kontrolünden faydalanacağım.


11
Her zaman amaç için yeni bir yapı / sınıf yaratırım. Bir 3d vektöre ihtiyacınız var, üç tane yüzer içeren bir yapı 3d_vector oluşturun. Bir uvw temsili gerekir, üç yüzer ile bir yapı texture_coords oluşturun. 3B ortamda bir pozisyona ihtiyacınız var, üç yüzer ile bir yapısal pozisyon oluşturun. Sen anladın. Baştan sona aynı şeyi kullanmaktan çok daha iyi okunabilirlik sağlar. Aynı şeyi birden çok kez tanımlayarak rahatsızsanız, 3-float tabanlı bir temel kullanın ve aynı yapı için birden çok ad tanımlayın.
Kevin

Bazı ortak yöntemleri varsa, o zaman belki bir. Hiç ikisinin eşitliğini karşılaştırmanız gerekecek mi?
paparazzo

8
@Sidney Kesinlikle yapmayacağım işlevselliğe ihtiyacınız olmadığı sürece. İki gösterim arasında dönüşüm yapabilmek için bir sin / arcsin işlemi yapmanız gerekir. Bu, dönüşümü her yaptığınızda en az önemli bitlerde bir bit bit ekleyecektir. Hem olayın sıklığını hem de olayların (x ve 1 / x) temsilini temsil eden bir sınıfla uğraşmaya çalıştığım şeylerle benzer bir acı ile karşı karşıya kalacağınızdan neredeyse eminim. Sınıfta hangi gösterimin kuralsız olduğunu izlemek ve tüm baş ağrıları ile başa çıkmak, tekrar yapmak istediğim bir şey değil.
Dan Neely,

3
Birçok şeyi temsil edebilecek bir veri tipine iyi bir örnek, dizedir, ancak "stringy yazılan" bir antipattern'dir. Örneğinle Wrt. Her iki koordinat sistemini destekleyen bir tür için nokta ürünü uygulamaya çalışın.
Nathan Cooper

1
Tip güvenliğinin avantajlarından yararlanmak için, mümkün olduğunda farklı türleri kullanmaya çalışmalısınız - bu, bir fonksiyona yanlış tipi göndermenizi önler (programlama dilinize bağlı olarak derleme zamanı doğruluk kontrolünü kullanarak). Bakımı kolaylaştıracaktır, çünkü bazı tiplerdeki tüm gerçek kullanımları bulabilirsiniz (türler kapalı olduğundan dolayı hatalı kullanım olmadan).
Erik Eidt

Yanıtlar:


17

Her iki çözümü de gördüm, bu kesinlikle içeriğe bağlı.

Okunabilirlik için, önerdiğiniz gibi çok sayıda yapıya sahip olmak çok etkilidir. Bununla birlikte, bazı ortamlarda, bu yapılarda ortak manipülasyonlar yapmak istiyorsunuz ve kendinizi matris * vektör işlemleri gibi yinelenen kod olarak buluyorsunuz. Belirli bir işlem vektörünüzün tadı için uygun olmadığında sinir bozucu hale gelebilir, çünkü kimse oraya taşımıyordu.

(En sonunda verdiğimiz) en uç çözüm, öğelerin genel bir şekilde elde edilmesi için, işlevlerin <0> () işlevinin <1> () ve <2> () işlevlerinin alındığı bir CRTP şablon temel sınıfına sahip olmasıdır. Bu işlevler daha sonra bu temel sınıftan türetilen Kartezyen veya Polar yapısında tanımlanır. Tüm sorunları çözer, ancak oldukça saçma bir bedelle gelir: şablon metaprogramlamasını öğrenmek zorunda. Ancak, şablon metaprogramlaması projeniz için zaten adil bir oyundursa, iyi bir eşleşme olabilir.


1
Cevabınız çok ilginç. örnek vermek mümkün mü?
Yüce deve Moha,

1
Yaptıklarımın bir örneğini sorabilirim: FIR filtreleme kutupları, kartezyenleri ve bunların vektörlerini. Matematik oldukça benzerdi, sans açısı (un) sarma, kod, bazı nedenlerle performans nedenleriyle çoğaltılmış ve aynı olduğu için şablonlar kullandık. Her şey için farklı adlar kullandım. Cort'un "aşırı çözümü" birkaç kopya kurtarabilirdi, ancak neredeyse hepsini değil.
Eugene Ryabtsev

1
İlk tepkim, bunun gibi bir durumun döküm ile çözülmesinin daha iyi çözüleceği, ancak biraz riskli olduğu ortaya çıktı .
200’de

114

Evet, çok mantıklı.

Bir yapının değeri, yalnızca verileri kullanışlı bir ad altında kapsamadığı anlamına gelmez. Buradaki değer, derleyicinizin bir gün onları ihlal etmediğinizi doğrulamanıza yardımcı olabilmesi için niyetlerinizi koordine etmesidir (örneğin, bir kartezyen koordinat kümesi için ayarlanmış bir kutupsal koordinatı yanlışlamak).

İnsanlar bu tür çekici detayları hatırlama konusunda kötü, ama cesur ve yaratıcı planlar oluşturmada iyi. Bilgisayarlar ayrıntılara dalmakta iyi, yaratıcı planlarda da kötü. Bu nedenle, zihninizi ayrıntılı bakımını değiştirerek, zihninizi büyük plan üzerinde çalışmaktan kurtarmaya çalışmak her zaman iyi bir fikirdir.


6
+1 Bilgisayarların yapmanın iyi olduğu şeyleri yapmak için bilgisayarı kullanmanın ve beyninizin kendi işinize odaklanmasını sağlamanın mükemmel bir açıklaması.
BrianH

8
"Programların insanların okuması için yazılması ve sadece tesadüfen makinelerin çalışması için yazılmalıdır." - Abelson ve Sussman'ın "Bilgisayar Programlarının Yapısı ve Yorumlanması" ndan.
hlovdal

18

Evet, hem Kartezyen hem de Polar (onların yerinde) oldukça duyarlı bir koordinat gösterme şemaları olsa da, ideal olarak asla karıştırılmamalı (Kartezyen {1,1} puanınız varsa, Polar {1,1'den çok farklı bir noktadır) }).

İhtiyaçlarınıza bağlı olarak, aynı zamanda gibi yöntemlerle, arayüz Koordinat uygulamaya değer olabilir X(), Y(), Displacement()ve Angle()(ya da muhtemelen Radius()ve Theta()bağlı).


OP'nin bu yapılardan ders çıkarması daha da önemlidir, çünkü kartezyen ve kutupsal koordinatlar üzerindeki işlemler farklıdır.
Mindwin

1
Son paragraf için +1, bu ideal çözümdür. Bir nokta uzaydır, bir nesnedir; bu noktanın içsel gösterimi önemli olmamalıdır. Tabii ki, gerçek dünyadaki endişeler (performans, yuvarlama hataları) önemli olabilir. Her şey bunun ne için kullanıldığına bağlı.
BlueRaja - Danny Pflughoeft 10:15

Ve ayrıca, bu örnekte, değişmesi pek mümkün değildir, ancak 2 farklı sınıf olsaydı, hiçbir şey size bazı noktalarda farklılaşabileceklerini söylemez.
dydydy 10:15

8

Sonunda, programlamanın amacı, faydalı işler yapmak için transistör bitlerine geçiş yapmaktır. Ancak bu kadar düşük bir seviyede düşünmek yönetilemez bir çılgınlığa yol açacaktır, bu yüzden karmaşıklığı gizlemenize yardımcı olacak daha yüksek seviyeli programlama dilleri vardır.

Sadece üyeli firstve biriyle bir yapı secondyaparsanız, isimler hiçbir şey ifade etmez; aslında onlara hafıza adresleri gibi davranırsınız. Bu, üst düzey programlama dilinin amacını yendi.

Üstelik, hepsinin temsil edilebileceği doublegerçeği, birbirlerini birbirleriyle değiştirebileceğiniz anlamına gelmez. Örneğin, θ boyutsuz bir açıdır, oysa y'nin uzunluk birimleri vardır. Türler mantıksal olarak ikame edilemediğinden, birbiriyle uyumlu olmayan iki yapı olmalıdır.

Eğer gerçekten tekrar bellek oynamayla ilgili püf noktaları oynamanız gerekiyorsa - ve neredeyse kesinlikle yapmamalısınız - unionniyetinizi netleştirmek için C harfini kullanabilirsiniz.


En iyi cevap, IMHO
Dean Radcliffe

2

İlk olarak, @ Kilian-foth'un tamamen sağlam cevabına göre, her ikisini de açıkça yapın.

Ancak şunu eklemek isterim:

Ask: Gerçekten çiftleri olarak kabul edildiğinde her ikisi için de genel olan işlemleriniz var doublemı? Bunun, her ikisine de kendi koşulları için geçerli olan işlemlerin olduğunu söylemekle aynı olmadığını unutmayın. Örneğin, 'arsa (Koord)' CoordPolar veya Kartezyen olup olmadığını önemser . Öte yandan, dosyaya devam etmek sadece verileri olduğu gibi değerlendirir. Gerçekten genel işlemleriniz varsa, ya bir temel sınıfı tanımlamayı std::pair<double, double>ya tupleda kendi dilinizde ne ya da ne varsa için bir dönüştürücü tanımlamayı düşünün .

Ayrıca, bir yaklaşım, bir Koordinat türünü daha temel, diğerini ise yalnızca kullanıcı veya harici etkileşimi destekleyecek şekilde ele almak olabilir.

Bu nedenle, tüm temel işlemlerin kodlandığından emin olabilirsiniz Cartesianve sonra dönüştürmek Polariçin destek sağlayabilirsiniz Cartesian. Bu, birçok işlemin farklı sürümlerini uygulamaktan kaçınır.


1

Dile bağlı olarak ve her iki sınıfın da benzer yöntem ve işlemlere sahip olacağını biliyorsanız olası bir çözüm, sınıfı bir kez tanımlamak ve türleri farklı bir şekilde adlandırmak için takma ad kullanmaktır.

Bu aynı zamanda, sınıflar tamamen aynı olduğu sürece, sadece bir tanesini tutabildiğiniz sürece, ancak bunları değiştirmeniz gerektiğinde, türler zaten kullanıldığından, bunları kullanarak kodu değiştirmeniz gerekmediği avantajına da sahiptir. distincly.

Sınıfların kullanımına bağlı olarak yine bir başka seçenek (polimorfizme ihtiyacınız varsa) ve her iki yeni türde de ortak miras kullanmaktır, bu nedenle her ikisi de temsil ettikleri ortak türle aynı ortak arabirime sahiptir. Bu aynı zamanda türlerin ayrı ayrı gelişmesine izin verir.


Her iki sınıftaki üyelerin adları aynı değildir. aslında isimler iki sınıf arasındaki tek farktır
Yüce deve Moha

@ Mhd.Tahawi Kullandığınız sınıfın aynı olmasını sağlamak, ancak kullanmak istediğiniz işlemler için uygun adlar vererek alıcıları ve ayarlayıcıları uygun adlarla uygulayabilirsiniz. Biraz daha ayrıntılı hale gelir, ancak daha az kod kopyalamanız gerekir.
Svalorzen

0

Aynı üye isimlerine sahip olmanın bu durumda kötü bir fikir olduğuna inanıyorum, çünkü kodu daha fazla hataya açık hale getiriyor.

Senaryoyu hayal edin: birkaç kartezyen noktanız var: pntA ve pntB. Öyleyse, bir nedenden ötürü, kutupsal koordinatlarda daha iyi temsil edilmeleri gerektiğine karar verirsiniz ve bildirimi ve yapıcıyı değiştirirsiniz.

Şimdi, tüm işlemleriniz sadece yöntem çağrılarıysa:

double distance = pntA.distanceFrom(pntB);

o zaman iyisin. Peki ya üyelere açık bir şekilde kullandıysanız? Karşılaştırmak

double leftMargin = abs(pntA.x - pntB.x);
double leftMargin = abs(pntA.first - pntB.first);

İlk durumda, kod derlenmeyecek. Hemen hatayı göreceksiniz ve düzeltebileceksiniz. Ancak aynı üye adlarına sahipseniz, hata yalnızca mantıksal seviyede olacaktır, tespit edilmesi daha zordur.

Nesne yönelimli olmayan bir dilde yazarsanız, fonksiyona yanlış yapıyı iletmek daha da kolaydır. Aşağıdaki kodu yazmanızı engelleyen nedir?

double distance = calculate_distance_polar(cartesianPointA, polarPointB);

Öte yandan, farklı veri türleri derleme sırasında hatayı bulmanızı sağlar.

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.