Сложность ПП - это кол-во вариантов поведения ПП, но на практике сложность рассматривают, как количество рассматриваемых вариантов.
Количество вариантов полного поведения ПП бесконечно — т.к. если брать тот же string.ToLower, то полное кол-во вариантов поведения функции для unicode-строки = количество вариантов символа * все возможные длины = 65536 * бесконечность.
у функции клонирования двумерного массива bool-ов полная сложность = 2 * бесконечность^2.
поэтому использовать оценку количество вариантов полного поведения ПП на практике не получается, т.к. оно сразу зашкаливает в бесконечность.
Поэтому используют другую оценку: количество рассматриваемых вариантов.
И для уменьшения количества рассматриваемых вариантов разработано куча методик; и большинство принципов(или огней в терминологии данного треда) программирования направлено именно на уменьшение рассматриваемых вариантов.
Сложность использования — сколько вариантов поведения ПП надо рассматривать (держать в голове) при попытке использования ПП.
Сложность реализации — сколько вариантов надо рассматривать при реализации ПП.
Сложность тестирования — сколько вариантов надо рассмотреть при тестировании ПП.
Сложность восприятия реализации — сколько вариантов надо рассмотреть при попытке понять реализацию.
Сложность внесения исправления — сколько вариантов надо рассмотреть для внесения изменения, и складывается из сложности восприятия решения и сложности реализации исправления
Рассмотрим все это на примере функции string.ToLower:
а) Сложность использования = 1, т.к. всего лишь один вариант поведения — на входе строка, на выходе — строка, где все буквы в нижнем регистре.
b) Сложность использования (уточненная) = 2, т.е. если посмотреть детальнее, то заметим, что мы еще забыли вариант с null-строкой, на которую функция кидает исключение, а не возвращает null (как могло быть для уменьшения вариантов поведения)
с) Сложность реализации — (зависит от реализации) возьмем для простоты Ascii-строки без использования символов выше 128-го.
при реализации в лоб — сложность = 128, для каждого символа определяется на какой символ он должен замениться
при думающей реализации — сложность = 2, т.к. для каждого символа есть лишь два варианта поведения:
если это большая английская буква, то заменить ее на маленькую,
иначе оставить символ как есть
от длины строки сложность решения не меняется, т.к. каждый символ обрабатывается независимо и одинаковым образом
string ToLower(string s)
{
var builder = new StringBuilder(s.Length);
foreach (var ch in s)
builder.Append('A' <= ch && ch <= 'Z' ? (char)(0x20+(int)ch) : ch);
return builder.ToString();
}
d) Сложность тестирования 6 + 128=134, т.к. несмотря на незавимость решения от длины все равно необходимо проверить на всякий случай — поведение ПП при следующих длинах:
1. null-строка,
2. пустая строка,
3. строка длины 1,
4. небольшая строка,
5. очень большая строка,
6. строка настолько большая, что кидает исключение по нехватке ресурсов
+ надо проверить, что каждый символ обрабатывается правильно (128 — вариантов)
e) Сложность восприятия реализации — 2 (если код выполняет все соглашения и т.д.), т.к. достаточно проверить два варианта, что убедиться, что функция имеет алгоритм — если большая буква, то поменять, иначе оставить как есть
f) Сложность внесения исправления при добавлении обработки русских букв = 4, и складывается из сложности восприятия решения=2 и сложности нового решения = 2, сложность такая низкая потому что обработка русских букв не зависит от обработки английских букв.