В чём проблемы с функцией SalesTax

145
16 ноября 2020, 19:20

Начал читать C# 7 и .NET Core. Кросс-платформенная разработка для профессионалов. 3-е издание.

В книге есть метод считающий НДС:

static decimal SalesTax(decimal amount, string twoLetterRegionCode)
{
    decimal rate = 0.0M;
    switch (twoLetterRegionCode)
    {
        case "CH": // Switzerland
            rate = 0.08M;
            break;
        case "DK": // Denmark
        case "NO": // Norway
            rate = 0.25M;
            break;
        case "GB": // United Kingdom
        case "FR": // France
            rate = 0.2M;
            break;
        case "HU": // Hungary
            rate = 0.27M;
            break;
        case "OR": // Oregon
        case "AK": // Alaska
        case "MT": // Montana
            rate = 0.0M;
            break;
        case "ND": // North Dakota
        case "WI": // Wisconsin
        case "ME": // Maryland
        case "VA": // Virginia
            rate = 0.05M;
            break;
        case "CA": // California
            rate = 0.0825M;
            break;
        default: // most US states
            rate = 0.06M;
            break;
    }
    return amount * rate;
}

и вопрос от автора со знаком !:

Можете ли вы представить какие-либо проблемы с функцией SalesTax в том виде, в котором мы ее написали? Что случится, если пользователь введет код региона Великобритании? Как бы вы переписали функцию для улучшения программы в этом аспекте?

Поведайте недогадливому, что с этим методом можно сделать?

Answer 1

Проблема этого кода в том, что функция нарушает принцип единственной ответственности (SRP). И эта проблема будет спать до того момента, когда вам понадобится этот код расширить (новички в программировании при этом нарушат ещё и Open-Close Principle, то есть поменяют уже написанный ранее код, а не напишут новый код не трогая старый)

Предполагается, что rate зависит от страны, но уже даже для США видно, что в некоторых странах есть регионы - и в них может быть разная ставка.

Представьте себе, что будет с этим кодом, если окажется, что в Британии в разных регионах разная ставка? Ваш switch распухнет, так как внутри будет вложенный switch. А если в какой-то из стран ставка зависит не от региона, а он расстояния до столицы - вы замучаетесь указывать параметры и т.п.

Для достижения большей поддерживаемости кода нужно разделить ответственности: отдельно определять страну, отдельно возвращать ставку для страны. И вот этот расчёт ставки для страны либо будет константой, либо будет зависеть от региона страны.

На днях на хабре была статья Непростой принцип единственной ответственности — в ней как раз очень хорошо объяснены те вещи, о которых идёт речь в вопросе.

И тут на сцену выходит принцип Open-Close принцип, который прямо говорит, что изменять уже существующий файл было нельзя. Надо было писать код так, чтобы при добавлении новой функциональности нужно было добавить новый файл, а не править уже существующий.

Почитайте, попробуйте самостоятельно переписать код функции SalesTax так, чтобы при последующих доработках кода для определения расчёта ставки для стран с/без учёта региона (США, Британия) не пришлось бы менять существующий код этой функции и код её unit-тестов, а только дописывать новые функции и новые юнит-тесты к ним.

READ ALSO
Wpf и горячие клавишы

Wpf и горячие клавишы

Да, я знаю как использовать хоткеи (XAML):

140
свайп в окне эмулятора Android через winapi

свайп в окне эмулятора Android через winapi

Имею эмулятор BlueStacksЦель: написать простого бота, который в окне эмулятора нажимает на определенные области экрана эмулируя тапы, а также...

141
Проблема при работе БД с IIS

Проблема при работе БД с IIS

Опубликовал свой проект в IISПри работе с БД выдаёт следующую ошибку: "Не удается открыть базу данных "RefsDB", запрашиваемую именем входа

155