Вступление:

Акцидентальная и Существенная сложность — термины, упомянутые в книге Мифический человеко-месяц.

По моим собственным словам, определения таковы:

  • Случайная сложность – это сложность, которая возникает в программном обеспечении случайно, и ее можно избежать, тщательно обдумав процесс. Например, ArrayList предлагает бесконечное добавление элементов. Если вы попросите пользователя изменить размер внутреннего массива перед добавлением каждого элемента, это будет безумием. Потому что об этом можно позаботиться внутренне без ведома пользователя.
  • Основная сложность – это сложность программного обеспечения, возникающая из-за характера проблемы. Например, для связи с сервером с самозаверяющим сертификатом пользователь должен взять на себя ответственность за предоставление хранилища доверенных сертификатов или необходимой конфигурации для игнорирования проверки SSL. Потому что JVM не может сделать выбор. Этот тип сложности неизбежен.

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

Недавний опыт работы с Accidental Complexity:

Проблема:

Недавно я экспериментировал с Nexmo Voice API. По сути, Nexmo Voice предназначен для соединения вызова с заданным номером и передачи заданного SSML или потокового аудио.

Существует множество API для Nexmo Voice. Но давайте рассмотрим пару API, чтобы обсудить концепцию.

  • У нас есть startTalk для передачи данного сообщения в вызове, идентифицированном данным идентификатором.
  • stopTalk для прекращения разговора в вызове, идентифицированном данным идентификатором вызова.

Предположим, что вам нужно произнести сообщение, сделать паузу на 2 секунды, произнести еще одно сообщение и замолчать. Вы можете ожидать примерно такой код,

client.startTalk("<call Id>", "SSML for message#1"); #1
Thread.sleep(2000); #2
client.startTalk("<call Id>", "SSML for message#2"); #3
client.stopTalk("<call Id>"); #4

Но это не сработает.

Сервер Nexmo ответит на ваш звонок асинхронно.

Следовательно,

  • Сообщение в #1 будет произнесено для 2s, независимо от того, закончено ли «сообщение №1» или нет, Nexmo начнет говорить «сообщение №2». Следовательно, если «сообщение № 1» не завершено, вы услышите эти два сообщения, произнесенные параллельно.
  • Сразу после этого, независимо от того, завершены «сообщения» или нет, stopTalk резко остановит произнесение сообщений.

Следовательно, чтобы он работал ожидаемым образом, вы должны кодировать следующим образом:

client.startTalk("<call Id>", "SSML for message#1"); #1
Thread.sleep(<number of seconds taken to complete speaking message#1>); #1.1
Thread.sleep(2000); #2
client.startTalk("<call Id>", "SSML for message#2"); #3
Thread.sleep(<number of seconds taken to complete speaking message#2>); #3.1
client.stopTalk("<call Id>"); #4

Вы должны поэкспериментировать и рассчитать количество секунд, необходимое для "#1.1" и "#3.1", чтобы Nexmo произнес сообщение ожидаемым образом.

Теперь проблема заключается в «Nexmo ожидает, что звонящий знает количество секунд, необходимое для произнесения данного сообщения», для синхронизации между несколькими сообщениями. На мой взгляд, это «Случайная сложность». Клиент может просто дать набор инструкций для выполнения сервером Nexmo. Ему не нужно знать, сколько времени требуется серверу для выполнения инструкции.

Предложение:

Чтобы избежать «случайных сложностей», возможно, Nexmo реализовала подход, основанный на очередях, при котором сервер выполняет одну за другой команду, которая вызывается для «идентификатора вызова». Чтоб работало нормально,

client.startTalk("<call Id>", "SSML for message#1"); #1
Thread.sleep(2000); #2
client.startTalk("<call Id>", "SSML for message#2"); #3
client.stopTalk("<call Id>"); #4

Резюме:

  • В случае, если нам нужно средство для вытеснения, могут быть дополнительные вызовы, такие как preemptTalk, preemptStop, которые вытесняют уже сделанные вызовы.
  • Поскольку я использовал Nexmo, API, о которых мы говорим, не имеют ничего общего с тем, что говорит другой пользователь, поэтому его можно ожидать как запустил и забыл.
  • Если вы все еще думаете, что вам нужен статус для каждого вызова перед выполнением следующего вызова, Nexmo может предоставить библиотеки, которые позволяют нам писать инструкции Nexmo условно, или платформу, которая поддерживает DSL с условными инструкциями для Nexmo, но никогда не добавляя сложности к пользователей, как указано выше.

Примечание. Nexmo — один из широко используемых серверов для голосовой связи. Я считаю, что могут быть некоторые моменты, связанные с дизайном, которые я упускаю. В этом случае ожидайте, что эта статья откроет дискуссию на этом фронте.

Первоначально опубликовано в моем блоге.