В последнее время я наблюдаю все больше и больше проблем, подобных тем, которые описаны в этой статье при пересечении функций. Другим термином для этого были бы линейки продуктов, хотя я склонен приписывать их фактически различным продуктам, тогда как я обычно сталкиваюсь с этими проблемами в форме возможных конфигураций продукта.
Основная идея этого типа проблемы проста: вы добавляете функцию в продукт, но каким-то образом все усложняется из-за комбинации других существующих функций. В конце концов, QA обнаруживает проблему с редкой комбинацией функций, о которых раньше никто не задумывался, и то, что должно было быть простым исправлением, может даже превратиться в серьезные изменения дизайна.
Размеры этой проблемы пересечения признаков представляют собой невероятную сложность. Допустим, текущая версия программного обеспечения имеет N
функции, и вы добавляете одну новую функцию. Давайте также упростим ситуацию, сказав, что каждая из функций может быть только включена или выключена, тогда у вас уже есть 2^(N+1)
возможные комбинации функций для рассмотрения. Из-за отсутствия более точных формулировок / поисковых терминов, я имею в виду существование этих комбинаций как проблему пересечения признаков . (Бонусные баллы за ответ, включая ссылку (и) на более установленный термин.)
Теперь вопрос, с которым я борюсь, заключается в том, как решить эту сложную проблему на каждом уровне процесса разработки. По очевидным стоимостным причинам, вплоть до утопии, нецелесообразно рассматривать каждую комбинацию индивидуально. В конце концов, мы стараемся держаться подальше от алгоритмов экспоненциальной сложности по уважительной причине, но превращение самого процесса разработки в монстра экспоненциального размера неизбежно приведет к полному провалу.
Итак, как вы получите лучший результат систематическим образом, который не разрушает бюджеты и является достойным, полезным и профессионально приемлемым способом.
Спецификация: Когда вы указываете новую функцию - как вы гарантируете, что она хорошо работает со всеми другими детьми?
Я вижу, что можно систематически проверять каждую существующую функцию в сочетании с новой функцией, но это было бы в изоляции от других функций. Учитывая сложную природу некоторых особенностей, это изолированное представление часто уже настолько вовлечено, что нуждается в структурированном подходе само по себе, не говоря уже о
2^(N-1)
факторе, вызванном другими особенностями, которые один охотно игнорировал.Реализация: когда вы реализуете функцию - как вы гарантируете, что ваш код правильно взаимодействует / пересекается во всех случаях.
Снова, я задаюсь вопросом о явной сложности. Я знаю различные методы для уменьшения вероятности ошибок двух пересекающихся элементов, но ни один из них не будет масштабироваться каким-либо разумным способом. Однако я предполагаю, что хорошая стратегия во время спецификации должна держать проблему в страхе во время реализации.
Проверка. Когда вы проверяете объект - как вы справляетесь с тем фактом, что вы можете проверить только часть пространства пересечения этой функции?
Достаточно сложно понять, что тестирование отдельной функции в отдельности не гарантирует ничего, кроме безошибочного кода, но когда вы уменьшаете его до доли,
2^-N
кажется, что сотни тестов даже не покрывают ни одной капли воды во всех океанах вместе взятых. , Хуже того, наиболее проблемные ошибки - это ошибки, связанные с пересечением функций, которые, возможно, не приведут к каким-либо проблемам - но как вы можете их проверить, если не ожидаете такого сильного пересечения?
Хотелось бы услышать, как другие решают эту проблему, меня интересует, прежде всего, литература или статьи, которые более глубоко анализируют эту тему. Поэтому, если вы лично придерживаетесь определенной стратегии, было бы неплохо включить соответствующие источники в ваш ответ.