是否在此代码中键入检查代码气味?

时间:2010-10-06 20:59:34

标签: c# oop typechecking

我有一个“IPartyCountService”接口,用于计算客户数量和供应商数量。

实施类“PartyCountService”使用类型检查来检查该方是客户还是供应商。

实现类PartyCountService使用类型检查是否会产生代码异味?

任何反馈,评论和批评都表示赞赏。

public interface IPartyCountService
{
    int GetTotalNumberOfCustomers();
    int GetTotalNumberOfSuppliers();
}

internal class PartyCountService:IPartyCountService
{
    IPartyRepository _partyRepository;

    public PartyCountService(IPartyRepository partyRepository)
    {
        _partyRepository = partyRepository;
    }

    public int GetTotalNumberOfCustomers()
    {
        var counter = 0;
        foreach(var customer in _partyRepository.GetAll())
        {
            if (customer is Customer) counter++;
        }
        return counter;
    }

    public int GetTotalNumberOfSuppliers()
    {
        var counter = 0;
        foreach (var customer in _partyRepository.GetAll())
        {
            if (customer is Supplier) counter++;
        }
        return counter;
    }
}

public interface IPartyRepository
{
    IList<IParty> GetAll();
}
internal class PartyRepository:IPartyRepository
{
    public IList<IParty> GetAll()
    {
        // put together all parties, including customers and suppliers
        return allParties;
    }
}
internal class Customer:IParty{}
internal class Supplier:IParty{}
public interface IParty{}

7 个答案:

答案 0 :(得分:2)

我会使用.OfType&lt;&gt;扩展方法。

return _partyRepository.GetAll().OfType<Customer>().Count();

编辑:如下面的SP所述,这使得一些更清洁的代码,但不一定能修复气味。

答案 1 :(得分:1)

对我来说感觉不对,但你可以做出一点改变就是这个。

return _partyRepository.GetAll().Count(p => p is Customer);

答案 2 :(得分:1)

也许IParty应该有一种方法来询问你在计算“顾客”时感兴趣的东西吗?

答案 3 :(得分:1)

我认为您不应该隐藏公共API中的CustomerSupplier。但是,建议您使用ICustomerISupplier 接口替换它们。基于接口的设计基于组件的最前端(即其公共API)将帮助您很自然地实现更好的设计。

关于类型检查和计数:我没有看到显式动态类型检查是坏事。但是,通过使用接口,它们在语义上变得更加自然。另外,为了保存明确的foreach和一对{ },我不认为只有无处不在引入类似LINQ的语句。

答案 4 :(得分:1)

客户和供应商是否存储在partyRepository中的单个异构集合中?似乎简单地挂在一组客户和一个单独的供应商集合上要容易得多;然后它可以暴露像GetCustomers(),GetSuppliers()或Get&lt; T&gt;()这样的函数。

使用这种方法,您仍然可以实现GetAll() - 将2个集合“联合”在一起非常容易。比过滤异构集合更容易(可能性能更好)。

答案 5 :(得分:0)

它有点臭,但不是我见过的(或自己完成的)最臭的东西。几点想法:

  • 将供应商和客户存放在同一个系列中的任何理由?如果您发现您的代码始终有所区别,请重构您存储它们的方式。
  • 存储接口集合但随后转换为具体类型会产生异味。每当我看到那种类型的演员表时,我立即认为抽象泄漏或需要第二次看的静态结构。
  • 如果组合它们确实有意义,LINQ可以使这更简单。
像这样:

return _partyRepository.GetAll().OfType<Supplier>().Count();

答案 6 :(得分:0)

首先,我认为这是一个选择问题。您必须知道每种可能的替代方案所涉及的权衡:

  1. 此致。
  2. 在基类上创建一个字段,使您能够知道哪一方。
  3. 备选方案(1)的优点是更简洁,并且对OO采用友好方法。 (但是,请记住,当您查看对象的具体类型时,您正在打破多态性。)

    备选方案(2)的优点是,首先,您不依赖元数据来了解对象类型。其次,is调用比检查变量类型更昂贵。因此,请确保您能够轻松获得性能。

    编辑:现在我看一下它,你正在抽象出一个接口类型,然后再将它转换回它的具体类型。这是为什么?如果使用集合的类知道不同的类型,它应该直接访问存储在那里的类型。