Опитимальное количество методов (1 void или 3 return)?

Есть void метод, в теле которого:

  1. Бинарный поиск первого вхождения
  2. Бинарный поиск последнего вхождения
  3. Цикл,в котором в строку записываются и выводятся на консоль все индексы

По ощущениям, метод получился слишком перегруженным:(

Вопрос: есть ли правила хорошего тона по созданию методов? Например, я могу сделать 3 метода вместо одного:

  1. int первое вхождение
  2. int последнее вхождение
  3. string цикл с индексами

Гораздо лаконичнее будет, но количество методов возрастает с 1 до 3.

Всегда ли следует ли разбивать большой метод на более простые?

Или же это дело сугубо персонального предпочтения и правил хорошего тона здесь нет?

Метод все-в-одном

void IndexFinderArrayBS(int number, int[] array)
{
    int low = 0;
    int high = array.Length - 1;
    int resultfirst = -1;
    int resultlast = -1;

    while (low <= high)
    {
        int mid = (low + high) >> 1;

        if (array[mid] > number)
        {
            high = mid - 1;
        }
        else if (array[mid] < number)
        {
            low = mid + 1;
        }
        else
        {
            resultfirst = mid;
            high = mid - 1;
        }
    }

    low = 0;
    high = array.Length - 1;

    while (low <= high)
    {
        int mid = (low + high) >> 1;

        if (array[mid] > number)
        {
            high = mid - 1;
        }
        else if (array[mid] < number)
        {
            low = mid + 1;
        }
        else
        {
            resultlast = mid;
            low = mid + 1;
        }
    }

    string? indexes = "";
    int counter = 0;

    for (int i = resultfirst; i <= resultlast; i++)
    {
        counter++;
        if (i == resultfirst)
        {
            indexes += Convert.ToString($"{i}");
        }
        else
        {
            indexes += Convert.ToString($", {i}");
        }
    }

    indexes += ".";

    if (resultfirst == -1 && resultlast == -1)
    {
        Console.WriteLine($"\nNumber {number} was not found in the Array");
    }
    else if (resultfirst == resultlast)
    {
        Console.WriteLine($"Number {number} was found only 1 time in the array. Index is: {resultfirst}");
    }
    else
    {
        Console.WriteLine($"\nNumber {number} was found {counter} times in the array. Indexes are: {indexes}");
    }
}

Метод string с двумя вложенными методами int

string IndexFinderArrayBS(int number, int[] array)
{
    int resultfirst = IndexFinderArrayBSFirst(number, array);
    int resultlast = IndexFinderArrayBSLast(number, array);

    string? indexes = "";
    int counter = 0;

    for (int i = resultfirst; i <= resultlast; i++)
    {
        counter++;
        if (i == resultfirst)
        {
            indexes += Convert.ToString($"{i}");
        }
        else
        {
            indexes += Convert.ToString($", {i}");
        }
    }

    indexes += ".";

    if (resultfirst == -1 && resultlast == -1)
    {
        return string.Format("\nNumber {0} was not found in the Array", number);
    }
    else if (resultfirst == resultlast)
    {
        return string.Format("\nNumber {0} was found only 1 time in the array. Index is: {1}", number, resultfirst);
    }
    else
    {
        return string.Format("\nNumber {0} was found {1} times in the array. Indexes are: {2}", number, counter, indexes);
    }
}

И один из int методов

int IndexFinderArrayBSFirst(int number, int[] array)
{
    int low = 0;
    int high = array.Length - 1;
    int result = -1;

    while (low <= high)
    {
        int mid = (low + high) >> 1;

        if (array[mid] > number)
        {
            high = mid - 1;
        }
        else if (array[mid] < number)
        {
            low = mid + 1;
        }
        else
        {
            result = mid;
            high = mid - 1;
        }
    }
    return result;
}

Ответы (1 шт):

Автор решения: aepot

Каждый метод должен быть примитивен и понятен. Много-много мелких методов - непонятно, куча кода в одном методе - тоже непонятно, где-то посередине должно стать понятно.

Про SOLID/SRP вам уже сказали, но этот принцип больше относится к классам, а не к методам, так что вынесение части кода согласно SRP в другие классы должно еще лучше отполировать картину.

Всегда ли следует ли разбивать большой метод на более простые?

Не всегда.

  • Метод должен иметь свою функциональную задачу, которую можно протестировать и понять, сломалось ли что-то в процессе доработки кода или нет. Этот подход может определеть, как распределить код по методам.
  • В критически чувствительных к производительности местах иногда разбитие на методы наносит вред этой самой производительности, но это уже слишком тонкие тонкости со своими еще более тонкими тонкостями, с которыми вы познакомитесь, когда будете писать бенчмарки и научитесь читать ассемблер, производимый JIT-компилятором. Сейчас пока об этом лучше не думать, но упомянуть я должен был.

Всё хорошо в меру. Есть задача - делайте для нее отдельный метод для нее. Есть повторяющийся код - делайте метод, чтобы уйти от повторений, и т.д.

→ Ссылка