[英]Is Kigg MVC application DRY? Can we tweak the Repository
我最近看了Kazi Manzur Kigg MVC實現(Kazi rocks),並注意到一些代碼似乎打敗了DRY / SOC原理。 我希望每個人都能想到可能的重構問題。
Kigg在每個存儲庫類上實現了Add
和Remove
方法( 注意 : BaseRepository
具有虛擬方法,而不是每個具體實現都可以重載。)
Kigg.Repository.LinqToSql.CategoryRepository
和Kigg.Repository.LinqToSql.StoryRepository
都通過其Remove
方法級聯刪除,以便刪除子實體。 ( 注意 :類別與Story具有父關系(一對多),因此它們從Story向下通過對象圖共享相同的子關系) 請參見圖表 。 違規代碼是兩個存儲庫刪除彼此子實體的方式:
CategoryRepository
namespace Kigg.Repository.LinqToSql.CategoryRepository{ //using statements omitted public class CategoryRepository : BaseRepository<ICategory, Category>, ICategoryRepository { //code omitted public override void Remove(ICategory entity) { Check.Argument.IsNotNull(entity, "entity"); Category category = (Category) entity; Database.DeleteAll(Database.StoryViewDataSource.Where(v => v.Story.CategoryId == category.Id)); Database.DeleteAll(Database.CommentSubscribtionDataSource.Where(cs => cs.Story.CategoryId == category.Id)); Database.DeleteAll(Database.CommentDataSource.Where(c => c.Story.CategoryId == category.Id)); Database.DeleteAll(Database.VoteDataSource.Where(v => v.Story.CategoryId == category.Id)); Database.DeleteAll(Database.MarkAsSpamDataSource.Where(sp => sp.Story.CategoryId == category.Id)); Database.DeleteAll(Database.StoryTagDataSource.Where(st => st.Story.CategoryId == category.Id)); Database.DeleteAll(Database.StoryDataSource.Where(s => s.CategoryId == category.Id)); base.Remove(category); } } }
StoryRepository
namespace Kigg.Repository.LinqToSql { //using statements omitted public class StoryRepository : BaseRepository<IStory, Story>, IStoryRepository { //code omitted public override void Remove(IStory entity) { Check.Argument.IsNotNull(entity, "entity"); Story story = (Story) entity; Database.DeleteAll(Database.StoryViewDataSource.Where(sv => sv.StoryId == story.Id)); Database.DeleteAll(Database.CommentSubscribtionDataSource.Where(cs => cs.StoryId == story.Id)); Database.DeleteAll(Database.CommentDataSource.Where(c => c.StoryId == story.Id)); Database.DeleteAll(Database.VoteDataSource.Where(v => v.StoryId == story.Id)); Database.DeleteAll(Database.MarkAsSpamDataSource.Where(sp => sp.StoryId == story.Id)); Database.DeleteAll(Database.StoryTagDataSource.Where(st => st.StoryId == story.Id)); base.Remove(story); } } }
假設更好的設計讓CategoryRepository
在StoryRepository
上調用Remove
方法,從而將Story的子對象刪除的關注委托給它所屬的StoryRepository
,我是否正確? 從維護的角度來看,對Story的子項的任何添加都需要將DeleteAll
調用添加到CategoryRepository
和StoryRepository
。
什么是更好的實施?
應該重構CategoryRepository
以直接使用StoryRepository
嗎?: CategoryRepository(refactor)
namespace Kigg.Repository.LinqToSql.CategoryRepository{ //using statements omitted public class CategoryRepository : BaseRepository<ICategory, Category>, ICategoryRepository { //code omitted public override void Remove(ICategory entity) { Check.Argument.IsNotNull(entity, "entity"); Category category = (Category) entity; // refactor - start StoryRepository _storyRepository = new StoryRepository( Database ); category.Stories.ForEach( story => _storyRepository.Remove( story ) ); // refactor - end base.Remove(category); } } }
此重構允許CategoryRepository
重用StoryRepository
的刪除邏輯,並且還應該重用與StoryRepository
構造函數提供的Database
參數相同的LinqToSql DataContext
。 但是當談到單元測試時,它開始有氣味。
會更好的重構包括使用IOC(Kigg使用統一作為IOC容器)的注入PerWebRequest
的范圍的情況下IStoryRepository
到CategoryRepository
的構造?
CategoryRepository(重構取2)
namespace Kigg.Repository.LinqToSql.CategoryRepository{ //using statements omitted public class CategoryRepository : BaseRepository<ICategory, Category>, ICategoryRepository { private readonly IStoryRepository _storyRepository; public CategoryRepository(IDatabase database, IStoryRepository storyRepository) : base(database) { Check.Argument.IsNotNull(storyRepository, "storyRepository"); _storyRepository = storyRepository; } public CategoryRepository(IDatabaseFactory factory, IStoryRepository storyRepository) : base(factory) { Check.Argument.IsNotNull(storyRepository, "storyRepository"); _storyRepository = storyRepository; } //code omitted public override void Remove(ICategory entity) { { Check.Argument.IsNotNull(entity, "entity"); Category category = (Category) entity; // refactor - start category.Stories.ForEach( story => _storyRepository.Remove( story ) ); // refactor - end base.Remove(category); } } }
有了這個第二個重構,我們現在可以在單元測試期間通過Unity Ioc將一個IStoryRepository
實例注入到CategoryRepository
中。 當然,我們必須將這個重構擴展到每個存儲庫類,以便他們可以傾向於自己孩子的責任。
每個人的想法是什么?
請原諒我對L2S的無知(我使用NHibernate),但是它不能自動處理級聯嗎?
JBland,LingToSql將處理數據庫中定義的級聯。 雖然,SQL Server不允許多個級聯路徑 。
Kigg數據庫沒有定義級聯的刪除或更新規則,但如果存儲庫實現執行必要的刪除,則不需要它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.