Платформы и инструментальные стеки

Если рассмотреть продуктное/конструктивное/модульное многоуровневое разбиение (PBS, product breakdown structure в отличие от функционального разбиения SBS, system breakdown structure), в нём можно увидеть на каждом уровне какие-то наборы мелких конструктивных «кирпичиков», представляющих через свои интерфейсы сервисы для сборки на их основе «кирпичиков» более высокого уровня. Вот такой согласованный по предоставляемым ими совместно сервисам набор модулей с их предопределёнными интерфейсами называют платформой.

Платформа --- это всегда продуктное/конструктивное/модульное рассмотрение системы с подчёркиванием стандартности получения требуемого от модуля сервиса через опубликованный интерфейс. Обсуждение платформы всегда связано с её сервисами, т.е. внешним поведением, предоставляемом на интерфейсе к вышестоящим в продуктном/конструктивном/модульном разбиении продуктам/модулям. Для программных модулей этот интерфейс обычно называется API (application program interface), программный интерфейс приложения/application program. Приложение --- это более высокий уровень, чем платформа.

Если речь идёт не о программной системе, то можно говорить просто о прикладном интерфейсе (application interface, а не application program interface). Прикладной интерфейс --- это определяемый интерфейс модуля к модулям надсистемы.

Платформа, если реализована библиотекой программ или «железными» модулями, то буквально входит в состав приложения в ходе его работы, является его подсистемой. Но если речь идёт о платформе провайдера, сервис которой изменяет что-то в предлагаемой ему части работающей целевой системы, то в состав приложения или «железной» системы входят только интерфейсные модули (часто называемые адаптерами/конверторами/соединителями), а саму платформу рассматривают находящейся во внешнем окружении (run-time, время operation для платформы).

В уже упоминавшихся социальных танцах (танго, кизомба, форро, сальса и т.д.) тоже есть интерфейсы, они обычно стандартизуются на уровне «базы»: есть условные сигналы, которые подаются leader/ведущим follower/следующему (это безгендерная терминология для «партнёра» и «партнёрши», на которую сейчас перешёл весь мир). Скажем, рука follower находится у вас (leader) на плече --- и вы не можете крутить follower, эта рука будет мешать. Вы даёте небольшой толчок руке (это и есть «сигнал ведения») --- и рука follower взлетает вертикально вверх. Теперь возможны повороты, эта рука не будет мешать. Вот это и есть один из интерфейсов в социальных танцах (есть и другие): между плечом и рукой, а также описание стандарта, какие в этом месте возможны взаимодействия, какие передаются сигналы и что происходит в ответ на эти сигналы.

В мышлении это мало отличается от обращения к программному сервису (помним, что «сервисом» часто называют и поведение провайдера, и самого провайдера сервиса, «службу», «сервер»), или обращением за сервисом к какому-то оборудованию. В этом плане follower, следуя стандарту «базы» танца с её сигналами, представляет платформу этой «базы». И важная особенность социальных танцев: стандартизация интерфейса, «платформенность» приводит к тому, что leader и follower, приехав на какую-то фестивальную вечеринку из разных стран и впервые танцуя друг с другом, смогут абсолютно предсказуемо и надёжно взаимодействовать друг с другом. Это взаимодействие в системном мышлении описывается примерно в том же наборе понятий, что взаимодействие смартфона и его сотовой станции, трамвая с его путями, веб-браузера с веб-сервером. Если думаешь о взаимодействии двух продуктов/модулей, думай об интерфейсе.

Основной вопрос при обсуждении платформ --- это так называемая видимость интерфейсов. Интерфейсы какого-то низкого системного уровня не должны быть видны снаружи модуля, то есть нельзя соединятьмодули иначе, чем через предусмотренные в нём интерфейсы. Грубо говоря, если у вас коробочка с каким-то разъёмом, то нельзя воткнуть внешнее устройство не в этот разъём, а куда-нибудь внутрь коробочки, мимо этого разъёма, даже если очень хочется. В системах всё со всем связано, и по неотслеженному соединению (это ведь будет тоже интерфейс, только «неучтённый») могут пройти паразитные связи, возникнут непредвиденные ошибки.

Например, если в ваше подразделение, где вы тщательно планируете работу сотрудников, получая заказы на эти работы через какой-нибудь трекер (весь этот трекер тут --- только интерфейсный модуль, предоставляющий интерфейс заказа работ, это неважно, что это довольно большая программная система, на рассматриваемом системном уровне это просто интерфейсный модуль для заказа работ, средство коммуникации подразделения с внешним миром), могут прийти какие-то люди из других подразделений и попросить сделать работы для них «вне очереди» --- и им не откажут, то последствия для организации будут фатальны: какие-то неожиданные работы будут выполнены, какие-то вроде как свободные сотрудники окажутся заняты, какие-то важные (но важность определяется надсистемой! Внутри модуля-подразделения как заказчика, так и исполнителя важность может быть неизвестной) работы не будут выполнены из-за задержек, связанных с этой внезапно появившейся «из ниоткуда» (мимо запланированного интерфейса, поддерживаемого трекером) работой.

В электротехнике есть три типа неисправностей: есть контакт там, где он не должен быть, нет контакта там, где он должен быть, и плохой контакт. Это шутка как раз про интерфейсы --- которые должны быть именно там, где они предусмотрены конструкцией!

Для обсуждения видимости интерфейсов используется диаграмма модульных/продуктных/конструктивных/платформенных уровней. Каждый платформенный уровень отделён от другого уровня каким-то стандартизированным (то есть описанным и документированным!) интерфейсом. Реализации/воплощения нижестоящих уровней тем самым могут быть сменены так, что надсистемы этого не заметят, если модули будут соблюдать интерфейсные соглашения. Итоговое многоуровневое модульное/продуктное разбиение называют платформенным стеком или инструментальным стеком (stack, стопка --- диаграммы похожи на стопку подносов в столовой или стопку листов бумаги в пачке). Вот пример различных инструментальных стеков для межкомпьютерной коммуникации в интернете вещей (IoT, internet of things)[1]:

На диаграмме видно, что в разных сравниваемых стандартах связи описываются/определяются/defined пять платформенных уровней (по отношению часть-целое) модулей/конструктивных частей, которые можно разделить на реализующие передачу физического сигнала (physical), передачу данных (Data Link) и т.д. При этом модули передачи данных при работе обращаются к модулям передачи физического сигнала, используя указанные в диаграмме протоколы[2]. И так по всем уровням выше, вплоть до уровня приложения/application: каждый уровень инструментального стека (уровень реализующих этот стек модулей) даёт интерфейс сервиса наверх и использует сервисы нижележащих модулей.

Неважно, что делают/как работают эти уровни платформенного стека. Для «как работают» нужно обсуждать функционирование в run-time, а обсуждение платформ --- это design-time, «из чего собрано и как соединено», время создания системы. Главное в показе этого инструментального стека то, что никакой модуль/продукт вышестоящего уровня «не видит» модули более низкого уровня (не имеет к ним доступа, не может туда «воткнуться»), чем находящийся непосредственно под ним, и интерфейсы реализующих сервисы этих платформенных уровней стандартизованы --- как стандартизован и сам набор этих уровней. В танцах вы передаёте сигнал от плеча к плечу, а не от мышц к мышцам, или даже от мышц плеча через кожу, затем кожу и дальше через рецепторы и нервы дальше к мышцам руки follow. Мышцы --- это конструктивные объекты более низкого уровня, и если у «плеча» и «руки» ничего не поломалось, чтобы чинить это на более низком уровне, то лезть на этот уровень не нужно, нужно пользоваться предписанными интерфейсами.

Есть два способа изображения таких диаграмм модульных/платформенных/инструментальных стеков:

  • на некоторых диаграммах плашка-«платформа» именуется названием описывающего её стандарта прикладного интерфейса. Прикладного --- это наверх по системным уровням, прикладность идёт в стеке сверху. Реализация этого стандарта интерфейсным модулем находится как бы «между уровнями» (ровно этот способ показан на диаграмме инструментальных стеков IoT, он самый распространённый)
  • показ собственно модулей (именование платформ) на плашках, тогда интерфейс этих модулей либо считается проименованным самим модулем (скажем, программный модуль/пакет/библиотека глубокого обучения TensorFlow имеет API TensorFlow, и поэтому его не нужно отдельно прописывать --- названия модуля достаточно), либо его указывают отдельно.

Но если платформенный уровень реализует стандарт с другим именем, то он прописывается где-то в границах реализующего его модуля отдельной строчкой поближе к границе над-модуля, или даже выносится и явно прописывается «между платформами», как это сделано в картинке стека безопасности приложений[3] --- стандарты указаны сбоку картинки платформенного стека, а каждая плашка обозначает слой модулей:

Верхняя скобка для стандарта интерфейса в надсистему от custom code ведёт как бы в никуда при таком способе показа, поэтому чаще используется способ предыдущей картинки, где платформа обозначается не по назначениям/именам её модулей/слоёв, а назначение указывается сбоку.

Часто оба этих способа перемешивают, получая гибридную модульную уровневую диаграмму. Вот, например, модульная диаграмма компилятора искусственных нейронных сетей, где верхние строки --- наименования программных модулей-пакетов реализации нейронных сетей (MXNet, PyTorch, ...), а нижние --- интерфейсных стандартов для какой-то аппаратуры (OpenCL, CUDA, ...)[4]:

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

Платформенность даёт возможность эффективного разделения труда: реализацией каждого уровня платформенного стека может заниматься отдельная команда, хорошо разбирающаяся в работе на их системном уровне (системный подход!), а поскольку речь идёт о модулях, реализующих/исполняющих роль функциональных частей, то такие команды могут соревноваться за эффективность реализации требуемых функций сервисами своих модулей --- на каждом системном уровне своих.

Инженеры, использующие какие-то платформы для создания своих целевых систем, могут не задумываться, как именно и из каких систем были сделаны сами эти платформы. Если вы пользуетесь каким-то сотовым телефоном, то вам всё равно, из чего и как сделан этот телефон, если он умеет связаться с базовыми станциями вашего провайдера сотовой связи. И вам всё равно, в какой школе танцев училась ваша партнёрша или партнёр, если соблюдается стандарт «базы» этого танца: вы сможете танцевать вместе.

Если интерфейсные стандарты не соблюдаются, мир разваливается на плохо и непонятно как взаимодействующие (нет интерфейсов!) части. Взаимодействие происходит, но совершенно незапланированным образом, заканчивается неудачей. Поэтому нужно будет тратить много сил на налаживание взаимодействия там, где его нет, но оно нужно и убирать взаимодействие там, где оно есть, но оно не нужно. Это налаживание взаимодействия в условиях отсутствия стандартов и когда системы уже созданы, называют «федерирование», см. стандарт ISO 11354-1:2011, framework for enterprise interoperability[5]. Он определяет три подхода к налаживанию взаимодействия/interoperability: федерированный/federated, унифицирующий/unified, интеграционный/integrated. Если разработчики взаимодействующих модулей используют при их создании стандарт взаимодействия/интерфейса, то это «унификация», а если они тщательно совместно разрабатывают оба модуля, проектируя их взаимодействие (что является более исключением, чем типовой ситуацией), то это «интеграция». При федерировании разработчики не соблюдают стандарты и не знают друг о друге, и это самый частый случай. И самый дорогой в реализации. Унификация --- это ориентация на стандарты, поэтому вместо федерирования предпочитают унификацию, это обычно дешевле. Интеграция --- это очень редкий случай, и дорогой: вам нужно совместно разрабатывать устройства и согласовывать интерфейс прямо при разработке, это довольно редкий случай. Скажем, электростанцию и электролампочку пришлось бы разрабатывать вместе, договариваясь о напряжении на выходе электростанции и входе электролампочки в рамках общего проекта. При взаимодействии через унификацию этого нет: вы просто соблюдаете стандарт интерфейса, лампочка и электростанция сопрягаются в России на 220 или 230 вольт[6] и не требуют совместной разработки, хотя в других странах на других значениях (240 вольт, 110 вольт и т.д.). Если у вас лампочка на 220 вольт, а напряжение в городской сети 110 вольт, то вам нужно федерирование (например, поставить повышающий трансформатор: адаптер для сетевого интерфейса).

Инженеры могут использовать прикладной интерфейс платформ, не интересуясь устройством этих платформ --- лишь бы эти платформы осуществляли сервис, осуществляя его через описанный интерфейс. Это существенно упрощает задачу создания сложных систем, ускоряет и удешевляет её. Нужно хорошо разбираться в вариантах модулей и выдаваемых ими на их интерфейсах сервисах, но необязательно разбираться, как они устроены внутри, и как именно они внутри себя работают. А если этот прикладной интерфейс стандартизован, и есть конкуренция поставщиков модулей/продуктов/изделий/конструктивных частей, то они могут ещё и выбрать подходящий им по цене и характеристикам вариант реализации. И это происходит на много уровней вверх и много уровней вниз по инструментальному стеку, системное мышление рекурсивно.

Деньги обычно приходят от удачного и массового использования верхнего, самого прикладного уровня (конечно, для каждого уровня инструментального стека вышестоящий уровень является «прикладным», системное мышление применяется рекурсивно --- то есть одинаково для каждого системного уровня, одинаково для каждой в нём системы). Посмотрите примеры явного использования рассуждений о платформе в стратегии фирмы NVIDIA --- при описании структуры интеллект-стека[7], инструментального стека робо-такси[8], стека вычислительной инфраструктуры[9] и обратите внимание на тип диаграмм, который там использован.

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

Например, когда в компьютерах поменялись механические или пневматические элементы на вакуумные электронные лампы, компьютеры стали масштабируемы и они начали напоминать уже функционально современные компьютеры, а не калькуляторы прошлых лет. Замена ламп на дискретную полупроводниковую технику позволила наладить массовый выпуск компьютеров и это разительно изменило компьютерную технику. Замена дискретной электроники на большие полупроводниковые интегральные схемы опять перевернула весь компьютерный рынок со всеми надстройками программного обеспечения. Замена CPU на GPU перевернула рынок искусственного интеллекта. Замена людей-исполнителей на роботов-исполнителей переворачивает все производство. Эта особенность делает инструментальные/платформенные/модульные/продуктные/аппаратные/софтверные стеки удобными для обсуждения стратегии компании. При стратегировании обсуждается, какие из модулей на этих платформенных уровнях будет компания делать сама, а что закупать вовне, какие стандарты интерфейсов для этих модулей она будет устанавливать сама, а какие брать из уже готовых стандартов. Хороший пример такого стратегирования на системных уровнях инструментального стека для искусственного интеллекта даёт компания NVIDIA[10].


  1. http://www.slideshare.net/Techtsunami/cn-prt-iot-v1 ↩︎

  2. Соглашение о взаимодействии, подразумевающее какую-то последовательность/порядок действий двух систем, называют протоколом. Стандарты, описывающие обмен данными, часто тоже называют протоколами: они ведь описывают последовательность обменов данными. ↩︎

  3. https://f5.com/about-us/blog/articles/why-cves-should-be-given-priority-one-for-resolution-27910 ↩︎

  4. https://tvm.ai/2017/10/06/nnvm-compiler-announcement ↩︎

  5. https://www.iso.org/standard/50417.html ↩︎

  6. До 2003 года стандарт был 220 вольт, но сейчас 230 вольт, хотя в некоторых нормативных документах по-прежнему 220 вольт, ГОСТ 29322-2014 определяет стандартное напряжение 230В с возможностью использовать 220В. Электросети поставляют электроэнергию согласно действующего на сегодняшний день ГОСТ 32144-2013, устанавливающего напряжение 220В. https://ru.wikipedia.org/wiki/Сетевое_напряжение ↩︎

  7. https://ailev.livejournal.com/1380163.html ↩︎

  8. https://ailev.livejournal.com/1384766.html ↩︎

  9. https://ailev.livejournal.com/1416697.html ↩︎

  10. Болваны для искусственного интеллекта http://ailev.livejournal.com/1356016.html, NVIDIA как поставщик инфраструктуры для интеллект-стека, https://ailev.livejournal.com/1380163.html, NVIDIA как поставщик инфраструктуры для роботакси-стека https://ailev.livejournal.com/1384766.html ↩︎