较大的函数与重复相同代码的较小函数

时间:2016-02-15 17:28:28

标签: c++ performance function

我一直在阅读关于保持功能简单和特定只有一个目的。即便是一个简单计算并打印出结果的函数已经太多了。

我一直在为小型游戏开发物品商店系统。该商店有一个游戏中所有项目的向量。每个项目跟踪自己的计数(这是不是很糟糕?),如果计数为零,则不会显示在库存输出中。

当玩家(骑车人)想要购买物品时,商店应该检查玩家是否有足够的信用额度以及在物品从商店中移除之前是否有库存(然后添加到玩家的库存中)。

我将所有这些结合到一个函数中,认为这样可以避免重复遍历Items的向量。

/* ItemShop.cpp
 * non-binary boolean:
 *   returns 0 if item is not in stock
 *   returns 1 if rider has insufficient creds to buy the item
 *   returns 2 if purchase is successful */

int ItemShop::buyItem(const string& itemName, const int cred, Item& newItem) {
    // go through shop inventory and search for item with given name
    for (int i = 0; i < items.size(); i++) {
        if (items[i].getName() == itemName) {
            if (items[i].getCount() > 0) { // item is in stock
                if (items[i].getValue() <= cred) { // rider has enough creds to buy the item
                    newItem = items[i];    // pass a copy of the item by ref
                    newItem.setCount(1);   // take one of that item
                    items[i].removeOne();  // remove one from the shop
                    return 2; // purchase is successful
                }
                return 1; // rider cannot afford to buy the item
            }
        }
    }
    return 0; // item is not in stock
}

在这种方法中,我最终得到了一个更大的多功能函数,但我不必多次遍历Item向量。我想如果我将功能分解为单独的功能,它们将是:

  1. 检查物品是否有货
  2. 检查玩家是否负担得起
  3. 交易
  4. 每个函数都必须通过并在向量中找到项目(除非我从函数中传递它的引用?)。

    总而言之,更少的代码重复使我的方法合理吗?如果没有,我应该如何分解?

4 个答案:

答案 0 :(得分:2)

两条建议:

  1. 将商品存储在字符串所在的std::map<string,Item>中 项目名称。这将删除搜索循环。
  2. 使用枚举作为返回值而不是int。
  3. 你也可以为不同的检查实现简单的功能,但这是我要说的味道。

答案 1 :(得分:1)

您可以将其分解为以下操作:

  • 按名称查找相应的项目(这是循环主要执行的操作)并返回对找到的项目的引用
  • 检查库存中是否有足够的物品。 item本身已经包含了它看起来的信息,它不需要在循环中执行
  • 检查玩家是否能负担得起。您显然已经拥有cred值,它不需要在循环中执行
  • 如果满足后两个条件,则执行事务,再次不需要在循环内执行

答案 2 :(得分:0)

您的功能并没有做太多事情 - 您正在购买一件物品,其中包括这三个必要步骤(顺便说一下:您是否错过了付款?)。

但是(除了可以改进的其他内容之外),您应该确保这些步骤不会混杂在一起。特别是尽可能避免使用嵌套结构 你可以像这样写下你的身体(不改变界面):

int ItemShop::buyItem(const string& itemName, const int cred, Item& newItem) {
    //find item
    auto it = std::find_if(items.begin(), items.end(), [&](const Item& item) {return item.getName() == itemName; });

    //Check if Item can be purchased
    if (it == items.end() || it->getCount == 0) {
        return 0; //item is not in stock
    }   
    if (it->getValue() > cred) {
        return 1; //rider can't afford item
    }

    //buy item
    newItem = *it;          // pass a copy of the item by ref <- Avoid that if possible
    newItem.setCount(1);    // take one of that item
    it->removeOne();        // remove one from the shop
    return 2; // purchase is successful 
}

答案 3 :(得分:0)

我认为一个项目保持自己的计数是一个糟糕的主意。 &#34;库存&#34; (或该订单上的某些东西)跟踪库存中的物品和每个物品的数量。一个项目应该只是:一个项目。

我认为使用[unordered_]地图的建议很好。它预先实现了当前函数中可能是最复杂的部分(尽管它们都不是特别复杂)。

请注意,当/如果涉及多个线程时,其中一些可能会变得更加棘手。如果涉及多个执行线程,那么您当前的模式是&#34;如果我们可以这样做,那么就这样做&#34;分解,因为它引入了竞争条件。您需要确保从库存中删除项目并为项目付款发生在单个原子事务中。只要您确定它只涉及单个执行线程,您当前的方法就是安全的。