Утверждения не выживают в реальности
Обычно утверждения не выдерживают контакта с данными реального мира. Это часть процесса разработки программного обеспечения, чтобы решить, с какими данными вы хотите иметь дело, а какие нет.
Циклические семейные графы
Относительно семейных «деревьев» (на самом деле это полноразмерные графы, включая циклы), есть хороший анекдот:
Я женился на вдове, у которой была взрослая дочь. Мой отец, который часто посещал нас, влюбился в мою падчерицу и женился на ней. В результате мой отец стал моим сыном, а моя дочь стала моей матерью. Некоторое время спустя я подарил своей жене сына, который был братом моего отца, и моего дядю. У жены моего отца (которая также является моей дочерью и моей матерью) родился сын. В результате я получил брата и внука в одном лице. Моя жена теперь моя бабушка, потому что она мама моей мамы. Итак, я муж моей жены и одновременно внук моей жены. Другими словами, я мой собственный дедушка.
Все становится еще более странным, если принять во внимание суррогаты или «нечеткое отцовство».
Как с этим бороться
Определить циклы как выходящие за рамки
Вы можете решить, что ваше программное обеспечение не должно иметь дело с такими редкими случаями. В таком случае пользователь должен использовать другой продукт. Это делает работу с более распространенными случаями гораздо более надежной, поскольку вы можете сохранить больше утверждений и более простую модель данных.
В этом случае добавьте некоторые хорошие функции импорта и экспорта в свое программное обеспечение, чтобы при необходимости пользователь мог легко перейти на другой продукт.
Разрешить ручные отношения
Вы можете позволить пользователю добавлять ручные отношения. Эти отношения не являются «первоклассными гражданами», то есть программное обеспечение принимает их как есть, не проверяет их и не обрабатывает их в основной модели данных.
Затем пользователь может обрабатывать редкие случаи вручную. Ваша модель данных все еще останется довольно простой, и ваши утверждения выживут.
Будьте осторожны с ручными отношениями. Существует соблазн сделать их полностью настраиваемыми и, следовательно, создать полностью настраиваемую модель данных. Это не будет работать: ваше программное обеспечение не будет масштабироваться, вы получите странные ошибки и, наконец, пользовательский интерфейс станет непригодным для использования. Этот анти-паттерн называется «мягким кодированием» , и «Ежедневный WTF» полон примеров для этого.
Сделайте вашу модель данных более гибкой, пропустите утверждения, протестируйте инварианты
В крайнем случае, ваша модель данных будет более гибкой. Вам придется пропустить почти все утверждения и основывать свою модель данных на полномасштабном графике. Как показывает приведенный выше пример, легко быть вашим собственным дедом, поэтому вы можете даже иметь циклы.
В этом случае вам следует тщательно протестировать свое программное обеспечение. Вы должны были пропустить почти все утверждения, так что есть хороший шанс для дополнительных ошибок.
Используйте генератор тестовых данных для проверки необычных тестовых случаев. Есть быстрые библиотеки проверки на Haskell , Erlang или C . Для Java / Scala есть ScalaCheck и ньяя . Одной из проверочных идей будет симуляция случайной популяции, случайное скрещивание, затем сначала ваше программное обеспечение импортирует, а затем экспортирует результат. Ожидалось бы, что все соединения на выходе также находятся на входе и наоборот.
Случай, когда свойство остается неизменным, называется инвариантом. В этом случае инвариант - это набор «романтических отношений» между индивидами в моделируемой популяции. Постарайтесь найти как можно больше инвариантов и протестируйте их со случайно сгенерированными данными. Инварианты могут быть функциональными, например:
- дядя остается дядей, даже когда вы добавляете больше "романтических отношений"
- у каждого ребенка есть родитель
- население с двумя поколениями имеет по крайней мере одного прародителя
Или они могут быть техническими:
- Ваше программное обеспечение не будет зависать на графике до 10 миллиардов участников (независимо от того, сколько соединений)
- Ваше программное обеспечение масштабируется с O (количество узлов) и O (количество ребер ^ 2)
- Ваше программное обеспечение может сохранять и перезагружать каждый семейный граф до 10 миллиардов участников.
Запустив смоделированные тесты, вы обнаружите множество странных угловых случаев. Их исправление займет много времени. Также вы потеряете много оптимизаций, ваше программное обеспечение будет работать намного медленнее. Вы должны решить, стоит ли оно того и входит ли оно в сферу вашего программного обеспечения.