2010-08-09 68 views
1

我有一個服務這兩種方法:合併這兩個非常相似的方法

public Offer GetOffer(int id, string languageCode = Website.LanguageSettings.DefaultLanguageCode) 
     { 
      Entities.Offer offerEntity = _db.Offers.FirstOrDefault(offer => offer.Id == id); 

      if (languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode) 
      { 
       using (IDocumentSession session = store.OpenSession()) 
       { 
        Translation.Offer translatedOffer = session.LuceneQuery<Translation.Offer>(Website.RavenDbSettings.Indexes.Offers) 
         .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode)) 
         .OrderByDescending(offer => offer.Id) 
         .FirstOrDefault(); 

        var offerPOCO = Mapper.DynamicMap<Translation.Offer, Offer>(translatedOffer); 
        offerPOCO.Id = offerEntity.Id; 

        return offerPOCO; 
       } 
      } 

      return Mapper.Map<Entities.Offer, Offer>(offerEntity); 
     } 

而且

public Hotel GetHotel(int id, string languageCode = Website.LanguageSettings.DefaultLanguageCode) 
     { 
      Entities.Hotel hotelEntity = _db.Hotels.FirstOrDefault(hotel => hotel.Id == id); 

      if (languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode) 
      { 
       using(IDocumentSession session = store.OpenSession()) 
       { 
        Translation.Hotel translatedHotel = session.LuceneQuery<Translation.Hotel>(Website.RavenDbSettings.Indexes.Hotels) 
         .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode)) 
         .OrderByDescending(hotel => hotel.Id) 
         .FirstOrDefault(); 

        Hotel hotelPOCO = Mapper.DynamicMap<Translation.Hotel, Hotel>(translatedHotel); 
        hotelPOCO.Id = hotelEntity.Id; 

        return hotelPOCO; 
       } 
      } 

      return Mapper.Map<Entities.Hotel, Hotel>(hotelEntity); 
     } 

他們是完全一樣在許多方面:他們採取同樣的參數,可以建相同的查詢並進行相同的操作,唯一不同的是它們使用和輸出的對象的類型。除了構建一個生成Where()參數字符串的方法之外,我想不出任何方法可以將大部分(或全部)代碼合併到一個方法中,然後從GetOffer()和GetHotel()中調用它,方法,因爲我最終會得到幾個就像這兩個。

任何意見非常感謝。

編輯:添加解決方案,因此,如果另一個可憐的人遇到這個問題,他/她可以有一個起點:

private TReturn GetObject<TReturn, TEntity, TTranslation>(int id, string languageCode, string ravenDbIndex) where TEntity:EntityObject 
                                where TTranslation:Translation.BaseTranslationObject 
                                where TReturn:BasePOCO 
     { 
      // TODO Run more tests through the profiler 
      var entities = _db.CreateObjectSet<TEntity>(); 
      var entityKey = new EntityKey(_db.DefaultContainerName + "." + entities.EntitySet.Name, "Id", id); // Sticking to the Id convention for the primary key 
      TEntity entity = (TEntity)_db.GetObjectByKey(entityKey); 

      if(languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode) 
      { 
       using(IDocumentSession session = store.OpenSession()) 
       { 
        TTranslation translatedObject = session.LuceneQuery<TTranslation>(ravenDbIndex) 
         .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode)) 
         .OrderByDescending(translation => translation.Id) 
         .FirstOrDefault(); 

        TReturn poco = Mapper.DynamicMap<TTranslation, TReturn>(translatedObject); 
        poco.Id = id; 

        return poco; 
       } 
      } 

      return Mapper.Map<TEntity, TReturn>(entity); 
     } 

然後我就叫:

GetObject<Hotel, Entities.Hotel, Translation.Hotel>(id, languageCode, Website.RavenDbSettings.Indexes.Hotels); 

每當我需要一家酒店。

謝謝大家的好評,從他們那裏學到了很多。

回答

6

看起來好像你可以將它重構成一個通用的方法。類似的事情這(我在調查重構一些方法調用等能力的一些假設,但希望你的想法)

public T Get<T>(int id, string languageCode = Website.LanguageSettings.DefaultLanguageCode) 
     { 
      Entity<T> entity = _db<T>.FirstOrDefault(entity => entity.Id == id); 

      if (languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode) 
      { 
       using(IDocumentSession session = store.OpenSession()) 
       { 
        Translation<T> translatedEntity = session.LuceneQuery<Translation<T>>(Website.RavenDbSettings.Indexes.Entities<T>) 
         .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode)) 
         .OrderByDescending(entity=> entity.Id) 
         .FirstOrDefault(); 

        T POCO = Mapper.DynamicMap<Translation<T>, T>(translatedEntity); 
        POCO.Id = entity.Id; 

        return POCO; 
       } 
      } 

      return Mapper.Map<Entities<T>, T>(Entity); 
     } 
+0

這是我一直在尋找的一般想法!謝謝堆 – JoseMarmolejos 2010-08-10 15:24:07

1

建議保持它們原樣。他們返回不同的類型,並保證不同的方法。我的直覺是它屬於Do One Thing - Single Responsibility Principle

確實,他們在工作中實施相同的策略,但我建議如果您合併/重構它們,將會比受益更容易混淆。

考慮業務邏輯變化的可能性。會不會比其他人更不穩定?執行此操作是否與GetFlights()GetCarRentals()相同?我認識到,當使代碼相同,並可能複製/粘貼/調整方法之間的代碼時,你會覺得你可以減少代碼行,並且不要重複自己。我同時看重SRP和DRY,但在這種情況下,我寧願爲每個實體Offer,Hotel等讀取和維護不同的方法。

+2

我認爲這兩種方法共享一個責任(或者「改變原因」,因爲你的鏈接定義了它)。他們都從數據存儲中檢索實體。您不可能在不更改這兩種方法的情況下改變其中一種方法(例如數據的存儲方式)。在這種情況下,我認爲DRY原則優先於單一責任原則。 – StriplingWarrior 2010-08-09 18:50:47

+0

我同意你的看法,把它們作爲兩種獨立的方法是合理的。我只是讓他們調用一個通用的方法來處理那裏的通用功能。 – JoseMarmolejos 2010-08-10 15:26:01

0

在這種情況下,我將可變項隔離並將它們放入sig,如果sig變得太大而且難以/難以調用,那麼查看泛型是否可以使這個更簡單,或者如果可以將各個部分分解成它們的類型,這是我認爲在這種情況下要做的。也有在SIG操作或FUNC可以幫助,如果它永遠不會是很難在呼叫填寫的東西,你也許可以撥打:

GetDalObject(db => db.Hotels.FirstOrDefault(hotel => hotel.Id == id), ... 

然後你就可以將其交換呼叫酒店或報價之間或者等等,但在你的情況下,我不知道這可以提供多大的幫助,因爲我認爲信號真的會變壞,所以我會考慮採用可變部分並在提供類型和酒店類型中實現它們,通過接口訪問,然後提供/酒店類交給這種方法。

public interface ICommonDalObject 
{ 
    public string LuceneQueryString { get; } 
    public ITranslation GetTranslation(); 
} 
相關問題