bir işlevi kötü uygulama olarak adlandırmanın yolu nedir?


10

Takip koduna sahibim:

public void moveCameraTo(Location location){
    moveCameraTo(location.getLatitude(), location.getLongitude());
}

public void moveCameraTo(double latitude, double longitude){
    LatLng latLng = new LatLng(latitude, longitude);
    moveCameraTo(latLng);
}

public void moveCameraTo(LatLng latLng){
    GoogleMap googleMap =  getGoogleMap();
    cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, INITIAL_MAP_ZOOM_LEVEL);
    googleMap.moveCamera(cameraUpdate);
}

Bu şekilde LatLng, örneğin başka bir sınıfta neyin olduğunu bilmenin sorumluluğunu ortadan kaldırdığımı düşünüyorum .

Ve işlevi çağırmadan önce verileri hazırlamanız gerekmez.

Ne düşünüyorsun?

Bu yaklaşımın bir adı var mı? Gerçekten kötü bir uygulama mı?


2
Bence, dilin yerleşik Yöntem Aşırı Yüklemesi'ni kullanarak Kapsülleme ile uğraşıyorsunuz. İyi / kötü değil. Kodunuza zarar verebilecek bir araç.
bitsoflogic

5
Amacınız LatLngbu Camerasınıfın müşterilerinden gizlemekse , muhtemelen moveCameraTo(LatLng)olmak istemezsiniz public.
bitsoflogic

Cevaplarda verilen tavsiyeye ek olarak, bu YAGNI'den bahsetmek için iyi bir yer gibi geliyor. Buna ihtiyacın olmayacak. İyi bir kullanım örneği olmadan önce API yöntemlerini tanımlamayın çünkü ... İhtiyacınız olmayacak.
Patrick Hughes

moveCameraToLocationVe moveCameraTo/ ile ilgili yanlış bir şey yok moveCameraToCoords. Kesinlikle aynı adlarda Location / lat / long geçmek istemem.
insidesin

Yanıtlar:


9

Arayanlara konum bilgisine bağımlılık yöntemlerini çözmenin alternatif yollarını sunmak için dil yöntemini aşırı yükleme özelliğini kullanıyorsunuz. Daha sonra, kamerayı güncelleme işleminin geri kalanını çözmek için başka bir yönteme geçiyorsunuz.

Buradaki kod kokusu, yöntemleri çağıran yöntem zincirini genişletmeye devam ederseniz olacaktır. Konum alma yöntemi, son olarak kamerayı nasıl güncelleyeceğini bilen bir şeyi çağıran latLng alma yöntemini çağıran çift alma yöntemini çağırır.

Uzun zincirler en zayıf halkaları kadar güçlüdür. Zincirin her bir uzantısı, çalışması gereken kodun kapladığı alanı artırır veya bu şey kırılır.

Her yöntemin kendisine sunulan sorunu çözmek için mümkün olan en kısa yolu seçmesi çok daha iyi bir tasarımdır. Bu, her birinin kamerayı nasıl güncelleyeceğini bilmesi gerektiği anlamına gelmez. Her biri, konum parametresi türünü, bu tek tür sunulduğunda kamerayı nasıl güncelleyeceğini bilen bir şeye geçirilebilen tek tip bir türe çevirmelidir.

Bu şekilde yapın ve her şeyin yarısını kırmadan birini kaldırabilirsiniz.

Düşünmek:

public void moveCameraTo(Location location){
    moveCameraTo( new LatLng(location) );
}

Bu, enlem ve boylam LatLngproblemini ele alır. Maliyet LatLngetrafında bilgi yayılır . Bu pahalı görünebilir, ancak benim tecrübelerime göre, ilkel takıntıya tercih edilen bir alternatiftir, bu da bir parametre nesnesi oluşturmaktan kaçınmanızın size takılı kalmasını sağlar.

Yeniden düzenlenebilir Locationancak LatLngdeğilse, aşağıdakilere bir fabrika ekleyerek bunu çözmeyi düşünün Location:

moveCameraTo( location.ToLatLng() );

Bu aynı zamanda ilkel takıntıyı da güzelce önler.


1
Benim için o kadar da kötü görünmüyor - bu sadece tüketici için kolaylık. Bu 10 kez zincirlenmiş olsaydı ya da tüketici tüm bu seçeneklere gerçekten ihtiyaç duymazsa, o zaman bir kod kokusu diyorum.
mcknz

1
Ancak, her işlevde dönüşüm çiftleri için LagLng veya Location to LagLng için tüm mantık koymanın alternatifi nedir?
Tlaloc-ES

@ Tlaloc-ES daha iyi mi?
candied_orange

@ Tlaloc-ES "Dönüştürme" yalnızca temel öğeler etki alanı mantığına yüklendiğinde gerçekleşmelidir. DTO'nun serileştirmesini kaldırdığınızda meydana gelir. Ardından, tüm etki alanı mantığınız LatLngveya Locationnesnelerin etrafından geçer . İkisi arasındaki ilişkiyi New LatLng(Location)veya Location.toLatLng()birinden diğerine gitmeniz gerekiyorsa gösterebilirsiniz .
bitsoflogic

1
@ Tlaloc-ES İlgili okumalar: Martin Fowler tarafından FlagArgument . "Karışık Uygulama" bölümünü okuyun.
Marc.2377

8

Çözümünüzde özellikle yanlış bir şey yok.

Ama kişisel tercihim, bu yöntemlerin o kadar kullanışlı olmamasıdır. Ve parçası oldukları nesnelerin arayüzünü karmaşık hale getirin.

void moveCameraTo(double latitude, double longitude)Ben hiçbir sorun basitçe çağıran gördüğünüz gibi gerçekten kodu basitleştirmek gelmez moveCameraTo(new LatLng(latitude, longitude));'s yerinde. Bu yöntem aynı zamanda ilkel saplantı kokuyor.

Bu yöntem ve void moveCameraTo(Location location)ispat Location.ToLatLng()yöntemi ile daha iyi çözülebilir moveCameraTo(location.ToLatLng()).

Bu C # olsaydı ve böyle bir yöntem gerçekten gerekli olsaydı, onları örnek yöntemleri yerine genişletme yöntemleri olarak tercih ederdim. Bu örneği soyutlayıp denemeden önce uzantı yöntemlerinin kullanımı çok açık hale gelecektir. Çünkü basit dönüşümlerle çoklu aşırı yükler yerine tek bir yöntemi taklit etmek çok daha kolay olurdu.

Bu şekilde, örneğin başka bir sınıfta LatLng'in ne olduğunu bilmenin sorumluluğunu ortadan kaldırdığımı düşünüyorum.

Bunun bir sorun olması için hiçbir neden göremiyorum. Kodunuz içerdiği sınıfı referans aldığı sürece void moveCameraTo(LatLng latLng), dolaylı olarak buna bağlıdır LatLng. Bu sınıf asla doğrudan başlatılmasa bile.

Ve işlevi çağırmadan önce verileri hazırlamanız gerekmez.

Ne demek istediğini anlamıyorum. Yeni örnek oluşturmak veya sınıfları birinden diğerine dönüştürmek demekse, bununla ilgili bir sorun görmüyorum.

Bunu düşünerek, söylediklerimin .NET'in API tasarımıyla da desteklendiğini hissediyorum. Tarihsel olarak, birçok .NET sınıfı, farklı parametreler ve içeride basit dönüşümler içeren birçok aşırı yüke sahip olma yaklaşımınızı izledi. Ancak bu, genişletme yöntemleri bulunmadan önceydi. Daha modern .NET sınıfları kendi API'lerinde daha hafiftir ve parametre aşırı yükleri olan herhangi bir yöntem varsa, uzantı yöntemleri olarak sağlanır. Daha eski bir örnek, günlüğe yazmak için düzinelerce aşırı yüke sahip NLog ILogger'dır . Bunu, toplam 3 yöntemi olan yeni Microsoft.Extensions.Logging.ILogger ile karşılaştırın (ve yalnızca günlüğe kaydetmeyi sayıyorsanız 1). Ancak uzatma yöntemleri olarak birçok yardımcı ve çeşitli parametreler vardır .

Bence bu cevap bazı dillerin tasarımı daha hoş hale getirecek araçlara sahip olacağını gösteriyor. Çok fazla Java bilmiyorum, bu yüzden eşdeğer olup olmayacağından emin değilim. Ancak düz statik yöntemler kullanmak bile bir seçenek olabilir.


Neden olduğundan emin değilim ama kendimi bu cevap için rakip bir cevap olmasına rağmen kök salıyor buluyorum. Bence bu konuyu daha iyi hale getirmeyi başardın. Benim tek geribildirim, bu sorunla ilgilenen herkesin .NET üzerinde olduğunu hatırlamak olacaktır. +1
candied_orange

@candied_orange Doğru. Artık OP'nin sorusuna daha iyi baktığım için, bu C # 'dan daha çok Java'ya benziyor.
Euphoric

Ben gerçekten moveCameraTo(new LatLng(latitude, longitude));projenin herhangi bir yerinde kullanımda bir sorun var , ama ben doğrudan moveCametaTo (latLng) daha açık kullanım olduğunu düşünüyorum, java bir dosya gibi dize gibi yol geçebilir veya bir Path sınıfı gibi
Tlaloc-ES

1

Bunun için doğru ismin ne olduğundan emin değilim, eğer varsa, ama iyi bir uygulamadır. Birden fazla aşırı yüke maruz kalırsınız ve çağrı sınıfının hangi parametre kümesini kullanmak istediğini belirlemesine izin verirsiniz. Dediğiniz gibi, başka bir sınıf bir LatLngnesnenin ne olduğunu bilmeyebilir , ama onun nesnesini bilebilir Location.

Bir yöntem diğerini çağırmak da anahtardır, çünkü bu yöntemlerde yinelenen kod istemezsiniz. Yaptığınız gibi, işi yapan yöntemlerden birini seçin ve diğer yöntemlerin (doğrudan veya dolaylı olarak) çağırmasını sağlayın


1

Bir çeşit yöntem kullanmayı düşünürseniz, sadece yöntem aşırı yükleme özelliğidir.

Ancak LatLng'in ne olduğunu bilmenin sorumluluğunu ortadan kaldırmaz . Çünkü siz başlatıyorsunuz LatLng latLng = new LatLng(latitude, longitude). Bu tamamen bağımlılıktır LatLng. (Başlatma işleminin neden bir bağımlılık sorunu olduğunu anlamak için Bağımlılık Enjeksiyonunu kontrol edebilirsiniz. ) Aşırı yüklenmiş yöntem oluşturmak yalnızca umursamayan müşterilere yardımcı olur LatLng. Eğer bunu kastediyorsanız, bu da iyidir ama bunun bir yaklaşım olduğunu düşünmüyorum. Müşteriler için sadece birçok hizmet yöntemidir.

Yani, mimarinizi tasarlamak için iki seçenek var:

  1. Birçok aşırı yüklenmiş yöntem oluşturun ve bunları istemciye sağlayın.
  2. Arayüz veya beton sınıfı olarak parametre (ler) gerektiren az sayıda aşırı yüklenmiş yöntem oluşturun.

Parametre olarak ilkel tiplere ihtiyaç duyan yöntemler oluşturmaktan mümkün olduğunca kaçıyorum (Seçenek 1). İşletmeniz çok zaman değiştiriyorsa ve yöntem parametrelerini oynatmanız gerekiyorsa, tüm arayan işlevlerini değiştirmek ve uygulamak gerçekten zordur.

Bunun yerine arayüzler kullanın (Bağımlılık Enjeksiyonu). Maliyet olduğunu ve daha fazla zaman aldığını düşünüyorsanız, sınıfları kullanın ve eşleyici uzantı yöntemlerini sağlayın (Seçenek 2).

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.