【问题标题】:How to remove duplication in this simple code?如何删除这个简单代码中的重复?
【发布时间】:2012-01-04 09:14:30
【问题描述】:

有一个函数AppendLastSlashIfNotExist我做了。
今天决定再做一个功能AppendLastBackSlashIfNotExist

wstring AppendLastSlashIfNotExist(__in const wstring& path)
{
    if (path == L"/")
    {
        return path;
    }

    if (path.size() == 0 || path[path.size() - 1] != L'/')
    {
        return path + L"/";
    }
    return path;
}

wstring AppendLastBackSlashIfNotExist(__in const wstring& path)
{
    if (path == L"\\")
    {
        return path;
    }

    if (path.size() == 0 || path[path.size() - 1] != L'\\')
    {
        return path + L"\\";
    }
    return path;
}

是的,很糟糕。只有 Slash -> BackSlash 是变化。我想删除重复项。

wstring AppendLastSlashIfNotExist(__in const wstring& path, bool backSlash)
{
    if (path == (backSlash ? L"\\" : L"/"))
    {
        return path;
    }

    if (path.size() == 0 || path[path.size() - 1] != (backSlash ? L'\\' : L'/'))
    {
        return path + (backSlash ? L"\\" : L"/");
    }
    return path;
}

我整合了它们。删除了重复。但是一个额外的参数来了。我还是觉得不舒服。 没有其他方法可以消除重复吗?例如,通过高阶函数使用。
请有任何想法。

【问题讨论】:

  • 我猜你应该合并 Path 类而不是使用这些函数。在您的类路径中,您将注意路径字符串的有效性。使用 OO 概念。
  • 表示bool backSlash=false的默认值。

标签: c++ design-patterns refactoring code-duplication


【解决方案1】:

除了传递一个布尔值来指示斜线类型,您可以只传递所需的斜线字符,并且可能有斜线字符的默认值:

wstring AppendLastSlashIfNotExist(__in const wstring& path,
                                  wchar_t slash = L'\\')
{
    // This is superfluous and is handled in next if condition.
    /*if (1 == path.length() && path[0] == slash)
    {
        return path;
    }*/

    if (path.size() == 0 || path[path.size() - 1] != slash)
    {
        return path + slash;
    }
    return path;
}

std::wstring s(L"test");
std::wcout << AppendLastSlashIfNotExist(s) << "\n";
std::wcout << AppendLastSlashIfNotExist(s, L'/') << "\n";

【讨论】:

    【解决方案2】:

    template是此类问题的答案:

    template<char SLASH_TYPE>
    wstring AppendLastSlashIfNotExist(__in const wstring& path)
    {
        if (path[0] == SLASH_TYPE)  // <--- comparing char (not const char*)
        {
            return path;
        }
    
        if (path.size() == 0 || path[path.size() - 1] != SLASH_TYPE)
        {
            return path + SLASH_TYPE;
        }
        return path;
    }
    

    为此,您需要稍微更改您的逻辑,因为您看到您传递的是 char 而不是 const char* 作为模板参数。

    函数将被调用为:

    y = AppendLastSlashIfNotExist<'/'>(x);
    y = AppendLastSlashIfNotExist<'\\'>(x);
    

    【讨论】:

    • 您不应该在比较path[0] == SLASH_TYPE 之前检查path.size() == 0 吗?
    • 顺便说一句,由于您的更改,逻辑不再相同。 path[0] == SLASH_TYPE
    • 为什么不将相关字符作为运行时参数传递?我以使用模板拍摄而闻名,但这似乎是一个太大的佳能,无法发射。您可能希望将此作为模板的唯一原因是避免在传递函数对象时绑定 char。
    【解决方案3】:

    您应该尝试考虑稍后阅读代码的人。 bool 是不可读的代码,但 AppendLastSlashIfNotExistsAppendLastBackSlashIfNotExists 是。我的建议是保留这两个函数,然后从它们调用通用函数。

    wstring AppendLastSlashIfNotExistInternal(__in const wstring& path, bool backSlash)
    {
        // as before..
        return path;
    }
    
    wstring AppendLastBackSlashIfNotExist(__in const wstring& path){
        return AppendLastSlashIfNotExistInternal(path, true);
    }
    
    wstring AppendLastSlashIfNotExist(__in const wstring& path)
    {
        return AppendLastSlashIfNotExistInternal(path, false);
    }
    

    这样,您仍然可以为以后维护代码的人保持可读性

    【讨论】:

    • +1。保留可读的函数名称,但将它们的共同行为委托给另一个函数。就个人而言,我会传递要附加的字符而不是布尔值,否则这是我将采取的方法。
    • @CarlManaster 我完全同意。使其尽可能通用
    【解决方案4】:

    一种解决方案是使用带参数的 TrimEnd 以从字符串末尾删除所有不需要的字符:

    template<class T> 
    T TrimEnd( const T& arg, const T& unwantedCharacters )
    {
      // Do manipulations here using stringstream in order to cut unwanted characters.
    }
    

    或者您可以避免使用模板并使用带有字符串和 wstring 参数的此函数的 2 个版本。

    之后,您只需在结果字符串上附加所需的尾部字符。

    【讨论】:

      猜你喜欢
      • 2015-06-26
      • 1970-01-01
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 2012-07-09
      • 2020-02-26
      • 2013-03-20
      • 1970-01-01
      相关资源
      最近更新 更多