Раз зашла речь про софт-скиллы, напомню ещё раз анекдотическую ситуацию с половиной статей про эти самые софт-скиллы: https://news.1rj.ru/str/systemswing/213
Помните! Если вы видите в какой-нибудь статье фразу "Ученые из Гарварда, Стэнфорда и Фонда Карнеги выяснили, что «гибкие навыки» — это 85% успеха человека в профессии, жесткие составляют только 15%." — это из книги 1918 (не опечатка!) года про обучение инженеров в США, и главный "софт-скилл" там — твердость характера!
Помните! Если вы видите в какой-нибудь статье фразу "Ученые из Гарварда, Стэнфорда и Фонда Карнеги выяснили, что «гибкие навыки» — это 85% успеха человека в профессии, жесткие составляют только 15%." — это из книги 1918 (не опечатка!) года про обучение инженеров в США, и главный "софт-скилл" там — твердость характера!
Telegram
Системный сдвиг
Есть такое модное понятие, применительно к медиа —фактчекинг. То есть, поиск и проверка источников. У аналитика это должно срабатывать на уровне рефлекса: кто-то сказал — нужно проверить и найти подтверждение, что это действительно так. Особенно интересно…
🔥15👍9😁4
В обсуждении софт-скиллов и хард-скиллов возник вопрос -- а какие, собственно, у аналитика хард-скиллы? Ну, кроме, цитирую, "сбора требований и базовых знаний по отрисовке диаграмм". Если речь про знание технологий, то любой программист погружен в нюансы технологии гораздо больше аналитика.
Про харды именно по анализу напишу чуть позже, а вот про знания технологий вспомнил хорошую метафору из Руководства по написанию требований INCOSE:
Про харды именно по анализу напишу чуть позже, а вот про знания технологий вспомнил хорошую метафору из Руководства по написанию требований INCOSE:
Представим, что на дворе 1930-е годы. На выставке инструментов для лесного хозяйства фирма Андреаса Штиля только что представила бензопилу, способную сделать революцию в отрасли. Герои нашей истории работают в небольшой компании, занимаются валкой леса. Её менеджеры только что вернулись с выставки. Просто взять и начать валить деревья с большей скоростью — это прекрасно. Но ведь нельзя просто так взять и посадить первого попавшегося представителя какой-нибудь из заинтересованных сторон за стол и попросить его написать требования для закупки бензопилы. Системное мышление заставляет задуматься: как же эта новая технология будет применяться с точки зрения бизнес-операций?Эта метафора показывает разницу между использованием технологии и системным анализом использования технологии. Программисты, безусловно, отлично знают все детали технологий, но задача аналитика (на мой взгляд) -- рассмотреть технологию и её влияние в комплексе и с разных сторон.
К сожалению, менеджмент также не может с пользой для дела прийти к заинтересованным сторонам, видимым с точки зрения бизнес-операций, и попросить их сформулировать потребности и требования к возможностям, открываемым новой бензопилой. Операционные менеджеры ведь управляют лесорубами, которые работают топорами. А эти серьезные мужчины вряд ли смогут рассказать, что им придется делать с новым инструментом: они никогда этого не делали, их никто не учил, не проводил инструктаж по безопасности или обслуживанию пилы. Или, что более вероятно, не захотят помогать: ведь в лучшем случае им придется переучиваться. А в худшем вообще остаться без работы.
Похожая ситуация с отделом снабжения. Его сотрудники знают своё дело — и в мельчайших подробностях! Сколько топоров ломается на метр поваленного леса (и сколько нужно закупить и доставить) известно. Но совершенно непонятно, как поддерживать работу новой бензопилой: что делать с топливом, смазкой, где всё это хранить, сколько запчастей и какие закупать, как часто. Как вообще узнать, что всё это нужно?
Перед тем, как на уровне бизнес-операций кто-то сможет ответить на все эти вопросы (то есть, выполнить требования), на уровне бизнес-менеджмента необходимо решить, как и зачем внедрять технологию на предприятии. Предприятию нужны эти бензопилы, чтобы быстрее валить деревья? Или скорость работы должна остаться такой же, просто выполнять ее хочется эффективнее (например, уволив несколько сотрудников)? В любом из этих случаев придется решить, что делать с людьми: переучивать ли их или нанять новых?
Обслуживание топоров устоялось: торговцы не просто продают инструмент, но и отвечают за его состояние. Сломалось топорище? Просто отправляем его торговцу, он заменит. Затупилось лезвие? Снова к торговцу: он заточит. А с кем и как вести дела, если закупить бензопилы? Как поддержать снабжение? Как перевозить материалы— топливо, масла — с которыми сегодня в компании никто не работает? Как и кто эту новую способность предприятия (все эти двигатели, цепи) будет поддерживать? Как поменять структуру организации? Как внедрять эту новую способность: выдать всем операторам бензопилы сразу, командам по очереди или начать скаких-то определенных регионов? Если начать валить деревья быстрее, нужно ли будет найти дополнительный транспорт для перевозки материала? Не придется ли расширять лесопилку? В конце концов, бизнес-менеджменту придется решить, стоит ли поставлять больше продукции и наводнить ею рынок, обрушив таким образом цены.
🔥30👍16❤7💯1
Знаете ли вы, что у ChatGPT можно попросить нарисовать вашу жизнь по мотивам вашего общения?
Промпт такой: "Based on what you know about me from our previous conversations, please draw a picture how in your opinion my life could look like“
Мне рисует вот такое 👆
Не знаю, откуда он взял всех этих Supplers Suppllelers Suppleton, но если считать, что я поддерживаю и обеспечиваю деятельность аналитиков — то даже похоже :)
Промпт такой: "Based on what you know about me from our previous conversations, please draw a picture how in your opinion my life could look like“
Мне рисует вот такое 👆
Не знаю, откуда он взял всех этих Supplers Suppllelers Suppleton, но если считать, что я поддерживаю и обеспечиваю деятельность аналитиков — то даже похоже :)
🔥17😁8👍4
Вообще, если говорить о софт-скиллах, одним из самых важных я считаю такой скилл, который не знаю, как называется, и про который почему-то редко говорят, когда говорят про софт-скиллы. Что-то вроде способности преодолевать страх наказания и смело идти навстречу неприятностям, вот так многословно.
Отсутствие такого скилла иллюстрируется очень простой ситуацией: это тот чувак из фильма про зомби, который будет до последнего скрывать, что заразился, и превратится в зомби в самый неподходящий момент.
Есть отличный текст на эту тему, он прекрасен, приведу его полностью:
Отсутствие такого скилла иллюстрируется очень простой ситуацией: это тот чувак из фильма про зомби, который будет до последнего скрывать, что заразился, и превратится в зомби в самый неподходящий момент.
Есть отличный текст на эту тему, он прекрасен, приведу его полностью:
Чуваки! Идите навстречу неприятностям. Не бегайте и не прячьтесь от неприятных ситуаций - инициируйте их разруливание сами, будучи виновной стороной.
Ты три дня тупил, и работа не будет готова к пятнице. Скажи об этом в среду сам, а не в пятницу, когда у тебя спросят результат! Дай другим возможность передвинуть планы, поискать, как тебе помочь сделать побыстрее, предупредить клиентов и так далее! Тогда ты остаешься ответственным вменяемым человеком - ты не подвел.
Ты проболтался врагам о секретах. Ты сломал чужую вещь или общий проект. Ты ляпнул теще правду о ее прическе. Ты недооценил трудность и понял, что не выполнил обещание. Ты недооценил сроки и ваша команда не запустит проект в день, обещанный клиенту. Ты недооценил расходы и проект собирается уйти в убыток. В ту же секунду, как ты это понял - иди и скажи об этом тем, кого это касается. Тем, кому важно как можно раньше об этом узнать, чтобы начать спасательные действия, позвонить маме и задобрить ее, открыть финансовый план и поискать резервы, позвонить рекламщикам и отложить старт заранее, не попадая на штрафы, и так далее. Чем раньше они узнают - тем меньше ты их подведешь, тем больше у них шанс спасти ситуацию. Не молчи до последнего, когда спасать поздно. Да, тебя ждет неприятный разговор - но в основном он будет про конструктивное решение, а не про отрицательные эмоции. В отличие от ситуации, когда об этом твоя команда, начальник, жена или друг узнают не от тебя и слишком поздно.
Ты понял, что занят, и не хочешь выполнять обещание или заказ. Скажи об этом сразу, а не когда у тебя придут спросить результат - дай человеку время найти другого исполнителя или план Б! Ты будешь неприятным снобом - но не раздолбаем, с которым больше не станут иметь дело.
Ты занял денег или взял кредит на бизнес, и понимаешь, что твои надежды проваливаются, и в срок ты отдать не сможешь? Бегом к кредитору. Первым. Заранее, а не когда придет этот срок. Тогда ты остаешься вменяемым и ответственным заемщиком. Твой кредит реструктурируют, срок продлят, после возврата с удовольствием дадут следующий кредит: ты же не подвел, дал кредитору шанс перекрыться из других источников вовремя.
Мне это и жизнь, и бизнес, и кредитную историю спасало в невегетарианские времена, друзья. И отношения с людьми тоже. Ошибки, фейлы, факапы бывают у всех. Не их отсутствием зарабатывается репутация. 90% того, что называется "ответственный, вменяемый, надежный" описано выше.
Казалось бы, простые, очевидные вещи. Однако почему-то сплошь и рядом взрослые люди тупо боятся пройти через неприятный момент. Когда что-то идет не так - прячутся, исчезают с горизонта. Постоянно на это натыкаюсь - человек до последнего молчит, а когда приходит пора спросить (как там результат, проект, деньги, подарок дяде...) - исчезает из интернета, отключает мобильный. Словно не понимает, что отложенный момент окажется хуже в сто раз. Словно включается внезапно в нем маленький мальчик с рефлексом "разбил мамину вазу - будут ругать - надо затихариться - а дальше чем на два часа я думать не умею".
Убей в себе маленького мальчика! Не прячься от неприятного! Не дай кредиторам, партнерам, начальникам, друзьям искать тебя после того, как прошел срок - позвони им сегодня, сейчас, скажи худшее из своих прогнозов! Мир станет гораздо более удобным местом, когда все станут взрослыми в этом смысле. Идите навстречу неприятностям.
🔥78👍14❤6🤔3💯1
В комментариях к предыдущему посту замечают (справедливо!), что, следуя таким советам, можно легко остаться без проектов и без заработка. Это верно — всё определяется культурой управления, в которой вы находитесь.
Я знаю про два типа управленческой культуры: культура зонтика и культура воронки (Umbrella vs Funnel). Эти образы на картинке (с сайта https://sketchplanations.com/umbrella-funnel). В первом случае ваш менеджер ограждает вас от потока разнообразных... скажем так... внезапных входящих дистракторов. Дистракторы образно изображены на второй картинке.
То есть, ваш менеджер дает вам возможность просто делать вашу работу, прикрывая вас от отвлекающих факторов. У меня был такой руководитель, когда я работал программистом — мы просто работали, а он всё время где-то пропадал, а потом приходил и тупо глядя в экран гонял какого-нибудь сапера или шарики. Это уже потом, когда он уволился, а я стал тим-лидом, я узнал — от чего и в каких количествах он нас прикрывал. Собственно, этот стиль руководства я воспринял, и всегда старался ему следовать — насколько это возможно.
И вот в этом стиле мне, как руководителю, как раз важно вовремя узнавать про проблемы, чтобы вовремя принять меры и прикрыть команду. А потом уже выяснять причины, извлекать lessons learned и придумывать противодействие таким ситуациям на будущее.
В культуре воронки ваш менеджер не собирается вас прикрывать. Наоборот — он собирает всё втекающее сверху, и направляет свою воронку на кого-то из своих подчиненных — по очереди равномерно, или целевым образом на кого-то одного, пока тот не сгорит. Тут, конечно, предупреждать на ранней стадии о своих косяках может быть чревато, т.к. вы становитесь видимыми и уязвимыми, и воронка будет направлена прицельно на вас. Ну или нет, так и продолжит поливать всех равномерно, как раньше — тут не угадаешь.
Говорят, есть ещё третий стиль — "культура вентилятора". Тут уже не воронка, тут если что-то прилетит — неважно, снизу или сверху — разлетится во все стороны. В этой культуре ваше раннее предупреждение станет тем самым набросом, который так здорово можно разнести по всем, до кого долетает. Валить, понятное дело, будут на источник, а не на вентилятор.
Вот такие корпоративные игры, так что выбирайте аккуратно — в какой культуре вам работать. Или учитывайте, в какой вы сейчас работаете.
Я знаю про два типа управленческой культуры: культура зонтика и культура воронки (Umbrella vs Funnel). Эти образы на картинке (с сайта https://sketchplanations.com/umbrella-funnel). В первом случае ваш менеджер ограждает вас от потока разнообразных... скажем так... внезапных входящих дистракторов. Дистракторы образно изображены на второй картинке.
То есть, ваш менеджер дает вам возможность просто делать вашу работу, прикрывая вас от отвлекающих факторов. У меня был такой руководитель, когда я работал программистом — мы просто работали, а он всё время где-то пропадал, а потом приходил и тупо глядя в экран гонял какого-нибудь сапера или шарики. Это уже потом, когда он уволился, а я стал тим-лидом, я узнал — от чего и в каких количествах он нас прикрывал. Собственно, этот стиль руководства я воспринял, и всегда старался ему следовать — насколько это возможно.
И вот в этом стиле мне, как руководителю, как раз важно вовремя узнавать про проблемы, чтобы вовремя принять меры и прикрыть команду. А потом уже выяснять причины, извлекать lessons learned и придумывать противодействие таким ситуациям на будущее.
В культуре воронки ваш менеджер не собирается вас прикрывать. Наоборот — он собирает всё втекающее сверху, и направляет свою воронку на кого-то из своих подчиненных — по очереди равномерно, или целевым образом на кого-то одного, пока тот не сгорит. Тут, конечно, предупреждать на ранней стадии о своих косяках может быть чревато, т.к. вы становитесь видимыми и уязвимыми, и воронка будет направлена прицельно на вас. Ну или нет, так и продолжит поливать всех равномерно, как раньше — тут не угадаешь.
Говорят, есть ещё третий стиль — "культура вентилятора". Тут уже не воронка, тут если что-то прилетит — неважно, снизу или сверху — разлетится во все стороны. В этой культуре ваше раннее предупреждение станет тем самым набросом, который так здорово можно разнести по всем, до кого долетает. Валить, понятное дело, будут на источник, а не на вентилятор.
Вот такие корпоративные игры, так что выбирайте аккуратно — в какой культуре вам работать. Или учитывайте, в какой вы сейчас работаете.
👍34❤6💯1
Если вам задают вопрос "Что происходит, когда вы набираете в браузере 'google.com'?", вспомните это видео: https://www.youtube.com/watch?v=atcqMWqB3hw
Осторожно, видео со звуком! В офисе используйте наушники. Ну или наоборот — зовите всех вокруг, особенно разработчиков — они наверняка порадуются. В комментариях отметился Даниэль Стенберг — собственно, создатель утилиты curl. Он такой подход одобряет! :)
Осторожно, видео со звуком! В офисе используйте наушники. Ну или наоборот — зовите всех вокруг, особенно разработчиков — они наверняка порадуются. В комментариях отметился Даниэль Стенберг — собственно, создатель утилиты curl. Он такой подход одобряет! :)
YouTube
curl -v https://google.com
The little men in your computer do this every time you open google.com
0:00 Shell
0:11 DNS Lookup
0:21 TCP Connect
0:30 TLS Negotiation
1:14 Guitar Solo
1:23 X509 Certificate Validation
2:20 HTTP/2 Session Open & HTTP/2 Client Request
2:30 HTTP/2 Server…
0:00 Shell
0:11 DNS Lookup
0:21 TCP Connect
0:30 TLS Negotiation
1:14 Guitar Solo
1:23 X509 Certificate Validation
2:20 HTTP/2 Session Open & HTTP/2 Client Request
2:30 HTTP/2 Server…
😁16🔥9🥰3❤1
По принципу Баадер-Майнхоф, вопрос "Что происходит, когда вы набираете google.com" не отпускает.
Шутки-шутками, но тут можно поговорить на серьёзную тему: про абстракции.
Ведь в этой картинке шутка в чем: никто не ожидает услышать в ответ на этот вопрос рассказ о таких глубоких уровнях реализации, как скан-коды клавиатуры (а если она USB — можно ещё и про потоки данных рассказать, стандарт USB довольно интересно устроен с точки зрения передачи данных — как маленькая сеть с иерархической топологией, и с разными режимами передачи пакетов данных). Даже в видео из предыдущего поста, на мой взгляд, чересчур подробно расписаны взаимодействия в процессе установки соединения TLS — аналитики в это обычно не погружаются.
Между тем, если абстрагироваться от устройства компьютера и ОС, а рассмотреть только сетевое соединение, остаются 7 уровней абстракции по модели OSI (никто не помнит все 7): от физического уровня — как электрончики бегают — до прикладного (собственно, протокол HTTP, например).
В модели TCP/IP уровней всего 4 (над физическим), легче запомнить: уровень передач пакетов в одной сети (link), уровень передачи между сетями (internet), уровень транспорта — как эти ваши пакеты собирать, что вам, например, важнее — надежность доставки (TCP) или своевременность (UDP), и, наконец, уровень приложений — что мы вообще передаем: файлы, гипертекст? Тут мы опять останавливаемся в лучшем случае на уровне приложений, а то и выше — SOAP и GraphQL — это надстройки на HTTP. Собственно, абстракции хороши чем — можно не думать, как они внутри устроены, а просто ими пользоваться.
Ну, до какого-то предела. Пока абстракция не начинает протекать.
Шутки-шутками, но тут можно поговорить на серьёзную тему: про абстракции.
Ведь в этой картинке шутка в чем: никто не ожидает услышать в ответ на этот вопрос рассказ о таких глубоких уровнях реализации, как скан-коды клавиатуры (а если она USB — можно ещё и про потоки данных рассказать, стандарт USB довольно интересно устроен с точки зрения передачи данных — как маленькая сеть с иерархической топологией, и с разными режимами передачи пакетов данных). Даже в видео из предыдущего поста, на мой взгляд, чересчур подробно расписаны взаимодействия в процессе установки соединения TLS — аналитики в это обычно не погружаются.
Между тем, если абстрагироваться от устройства компьютера и ОС, а рассмотреть только сетевое соединение, остаются 7 уровней абстракции по модели OSI (никто не помнит все 7): от физического уровня — как электрончики бегают — до прикладного (собственно, протокол HTTP, например).
В модели TCP/IP уровней всего 4 (над физическим), легче запомнить: уровень передач пакетов в одной сети (link), уровень передачи между сетями (internet), уровень транспорта — как эти ваши пакеты собирать, что вам, например, важнее — надежность доставки (TCP) или своевременность (UDP), и, наконец, уровень приложений — что мы вообще передаем: файлы, гипертекст? Тут мы опять останавливаемся в лучшем случае на уровне приложений, а то и выше — SOAP и GraphQL — это надстройки на HTTP. Собственно, абстракции хороши чем — можно не думать, как они внутри устроены, а просто ими пользоваться.
Ну, до какого-то предела. Пока абстракция не начинает протекать.
👍17❤9
В проектировании систем есть фундаментальная проблема:
Закон Дырявых Абстракций: Все нетривиальные абстракции дырявы. (All non-trivial abstractions, to some degree, are leaky)
Как бы мы не абстрагировались от всего, что ниже, мы не можем этого не учитывать. Ну, или немного можем, раз у нас есть разделение труда по уровням абстракции. Главное, четко провести границу.
Вот, например, кэширование — кто про него должен думать? Я каждый раз задаю этот вопрос на тренингах — нет, аналитики про это не думают. И нагрузку на сервера не считают. Традиционно, все нефункциональные требования не в области интересов аналитиков. Это только потом выясняется, что каждое соединение расходует на сервере память и процессор, и они, вообще говоря, могут закончиться.
А ещё бывают конкурирующие запросы — один клиент изменяет ресурс, а другие в этот момент его читают. А ещё внезапно оказывается, что запросы выполняются не мгновенно, и передача большого куска данных может идти довольно долго (а при случайном или намеренном сложном запросе может и вообще завесить ваш сервер, см. XML Bomb или Billion Laughs Attack).
Вопрос границ ответственности в данном случае очень спорный. В общем случае аналитик не может быть глубоко погружен в технические детали. Пока абстракции не начали течь, и пока своими глазами не увидишь, как два почти идентичных запроса к БД выполняются за время, отличающееся в десятки раз, потому что запрошенные данные не попали на страницу, подгруженную в кэш СУБД (какой кэш? какие страницы? почему я вообще должен об этом думать?)
Итого, ответ такой: про зоны ответственности лучше договориться заранее. Где мне остановиться и что не описывать в моем документе? Кэширование — это ещё мое, или нет? А обработка ошибок? А санитаризация ввода — об этом нужно писать?
Я знаю, во многих компаниях есть соглашение о моделировании (бизнес-процессов, архитектуры). Почему-то гораздо реже встречается соглашение о содержании требований. Где останавливается БА, что добавляет СА, а что является технологической документацией, которую пишут разработчики/архитекторы или SRE?
Заодно при составлении такого соглашения может выясниться, что у вас в команде недостает каких-то специальных компетенций (например, по тем же уязвимостям API или по оптимизации запросов к БД).
Это риски, а системный анализ — он весь про риски. Лучше их выявить и принять меры.
Ну а чтобы выявить и разобрать, что кому уходит, нужно представлять весь процесс в мельчайших деталях. И, к сожалению, на нескольких уровнях абстракции, вплоть до физического. До сих пор помню, как мы недели две искали плавающий баг — у части клиентов сервер регулярно отваливался на несколько секунд, и не принимал подключения. Вычистили пару реально странных мест в обработчиках соединений, нашли одну утечку памяти. Всё без толку. А оказалось — разъем на свитче разболтался, нужно было патчкорд поменять.
Закон Дырявых Абстракций: Все нетривиальные абстракции дырявы. (All non-trivial abstractions, to some degree, are leaky)
Как бы мы не абстрагировались от всего, что ниже, мы не можем этого не учитывать. Ну, или немного можем, раз у нас есть разделение труда по уровням абстракции. Главное, четко провести границу.
Вот, например, кэширование — кто про него должен думать? Я каждый раз задаю этот вопрос на тренингах — нет, аналитики про это не думают. И нагрузку на сервера не считают. Традиционно, все нефункциональные требования не в области интересов аналитиков. Это только потом выясняется, что каждое соединение расходует на сервере память и процессор, и они, вообще говоря, могут закончиться.
А ещё бывают конкурирующие запросы — один клиент изменяет ресурс, а другие в этот момент его читают. А ещё внезапно оказывается, что запросы выполняются не мгновенно, и передача большого куска данных может идти довольно долго (а при случайном или намеренном сложном запросе может и вообще завесить ваш сервер, см. XML Bomb или Billion Laughs Attack).
Вопрос границ ответственности в данном случае очень спорный. В общем случае аналитик не может быть глубоко погружен в технические детали. Пока абстракции не начали течь, и пока своими глазами не увидишь, как два почти идентичных запроса к БД выполняются за время, отличающееся в десятки раз, потому что запрошенные данные не попали на страницу, подгруженную в кэш СУБД (какой кэш? какие страницы? почему я вообще должен об этом думать?)
Итого, ответ такой: про зоны ответственности лучше договориться заранее. Где мне остановиться и что не описывать в моем документе? Кэширование — это ещё мое, или нет? А обработка ошибок? А санитаризация ввода — об этом нужно писать?
Я знаю, во многих компаниях есть соглашение о моделировании (бизнес-процессов, архитектуры). Почему-то гораздо реже встречается соглашение о содержании требований. Где останавливается БА, что добавляет СА, а что является технологической документацией, которую пишут разработчики/архитекторы или SRE?
Заодно при составлении такого соглашения может выясниться, что у вас в команде недостает каких-то специальных компетенций (например, по тем же уязвимостям API или по оптимизации запросов к БД).
Это риски, а системный анализ — он весь про риски. Лучше их выявить и принять меры.
Ну а чтобы выявить и разобрать, что кому уходит, нужно представлять весь процесс в мельчайших деталях. И, к сожалению, на нескольких уровнях абстракции, вплоть до физического. До сих пор помню, как мы недели две искали плавающий баг — у части клиентов сервер регулярно отваливался на несколько секунд, и не принимал подключения. Вычистили пару реально странных мест в обработчиках соединений, нашли одну утечку памяти. Всё без толку. А оказалось — разъем на свитче разболтался, нужно было патчкорд поменять.
👍25❤8😁8👎1
Вопрос: вижу во многих постах, разборах и шпаргалках для интервью по интеграциям упоминание протокола MQTT. Все с умным видом пишут: легковесный, обеспечивает небольшую нагрузку на каналы связи, может работать в условиях неустойчивой передачи, используется для IoT...
А кто-нибудь его вообще в реальной жизни на работе применял? В смысле, не только для умного дома? Расскажите?
А кто-нибудь его вообще в реальной жизни на работе применял? В смысле, не только для умного дома? Расскажите?
Используете протокол MQTT?
Anonymous Poll
50%
Впервые слышу
25%
Только читал/слышал на курсах
7%
Использую в работе
18%
Хочу посмотреть результаты
Любопытные результаты! Половина аудитории вообще не слышала про MQTT, четверть — слышала, и только 7% (29 человек) используют в работе.
Это при том, что MQTT — один из самых ранних протоколов, реализующих паттерн "Публикация-подписка", ещё 1999 года. AMQP, на котором построен RabbitMQ и прочие брокеры с буквами MQ в названии — предложен в 2003, а Kafka вообще в 2011.
Я, собственно, спрашивал для одной тут инфографики с разными типами интеграции. Вопрос — включать ли туда MQTT, или это совсем экзотика. И, честно, говоря, пока так и не решил — вроде бы, 7% — это не так уж и мало, а знать полезно. Видимо, всё-таки нужно, для общего развития аналитиков.
Интересный набор статей про MQTT есть на сайте Kai Waehner. У него там интересные разборы архитектур систем стриминга данных, причем он часто сочетает MQTT с Kafka (MQTT выступает интерфейсом для сбора данных, а Kafka — для хранения и дистрибуции, как например здесь.
В общем, если в вашем проекте появляются такие слова, как IoT, сбор данных с датчиков, телеметрия, умный дом/умный город, роботы, цифровые двойники, автомобили/самокаты/велосипеды/дроны/самолеты, сотни тысяч и миллионы устройств, realtime processing, слабые каналы связи, mesh networks, а может быть наоборот — 5G для IoT, или, например, каппа-архитектура — то имеет смысл посмотреть в сторону MQTT.
Несмотря на свой почтенный возраст, протокол вполне себе жив — вот отчет о прошлогодней конференции (посмотрите презу в конце статьи, там много интересных архитектур).
Это при том, что MQTT — один из самых ранних протоколов, реализующих паттерн "Публикация-подписка", ещё 1999 года. AMQP, на котором построен RabbitMQ и прочие брокеры с буквами MQ в названии — предложен в 2003, а Kafka вообще в 2011.
Я, собственно, спрашивал для одной тут инфографики с разными типами интеграции. Вопрос — включать ли туда MQTT, или это совсем экзотика. И, честно, говоря, пока так и не решил — вроде бы, 7% — это не так уж и мало, а знать полезно. Видимо, всё-таки нужно, для общего развития аналитиков.
Интересный набор статей про MQTT есть на сайте Kai Waehner. У него там интересные разборы архитектур систем стриминга данных, причем он часто сочетает MQTT с Kafka (MQTT выступает интерфейсом для сбора данных, а Kafka — для хранения и дистрибуции, как например здесь.
В общем, если в вашем проекте появляются такие слова, как IoT, сбор данных с датчиков, телеметрия, умный дом/умный город, роботы, цифровые двойники, автомобили/самокаты/велосипеды/дроны/самолеты, сотни тысяч и миллионы устройств, realtime processing, слабые каналы связи, mesh networks, а может быть наоборот — 5G для IoT, или, например, каппа-архитектура — то имеет смысл посмотреть в сторону MQTT.
Несмотря на свой почтенный возраст, протокол вполне себе жив — вот отчет о прошлогодней конференции (посмотрите презу в конце статьи, там много интересных архитектур).
👌11
Закончился очередной поток очного курса по проектированию интеграций, а я в очередной раз задумался про обучение взрослых. И кстати нашел тезисы по андрагогике Малколма Ноулза (Malcolm Knowles, отличная фамилия для ученого, занимающегося образованием!)
Он много занимался обучением взрослых ещё в середине XX века, и сформулировал следующие принципы:
1. Потребность в знаниях. Взрослым нужно четко понимать — зачем они учатся.
2. Опыт. Обучение взрослых должно быть основано на опыте (включая ошибки).
3. Самостоятельность (self-concept). Взрослые сами отвечают за решения в отношении обучения, в том числе в планирование и оценку качества преподавания.
4. Готовность. Взрослые более готовы изучать предметы, которые могут немедленно применять в своей работе или жизни.
5. Ориентация на проблему. Обучение взрослых должно строиться вокруг проблемы, а не вокруг контента.
6. Мотивация. Мотивация взрослых скорее внутренняя (улучшение жизни, рост уверенности, удовлетворенность работой), чем внешняя (оценки, учебные достижения).
Эти идеи совпадают с тем, как у нас в Systems.Education устроено обучение (мы пришли у этому на собственном опыте, без теории) — работа над кейсом в течение курса, никаких оценок, обучение выстроено вокруг получения реального опыта, применять можно сразу, есть возможность углубить или пропустить какую-то тему, если группе это нужно (или не нужно).
Однако многие онлайн-курсы сделаны по прямо противоположным принципам! Без объяснения, зачем вам нужно это обучение (это скорее внешний фактор, когда вас компания посылает на обучение, не объясняя, зачем). С минимальным опытом (пройдите тесты, вот и весь опыт). Без вариантов влияния на планирование, содержание и темп обучения (а тем более — без оценки качества преподавания). С кучей теории, которую непонятно, как применить. С занятиями, выстроенными вокруг контента (это вообще не обучение, это ознакомление). И с мотивацией в виде оценок и геймификации.
Есть, конечно, совсем противоположный полюс — типа "Арзамаса" и "Страдариума" — курсы явно не для применения прямо сейчас и организованные вокруг контента (хотя в Страдариуме есть курсы с практическими заданиями — например, в курсе по исторической кухне дают задание приготовить что-то по средневековым рецептам). Вот про эту сторону обучения я плохо понимаю, хотя проекты явно успешны.
Он много занимался обучением взрослых ещё в середине XX века, и сформулировал следующие принципы:
1. Потребность в знаниях. Взрослым нужно четко понимать — зачем они учатся.
2. Опыт. Обучение взрослых должно быть основано на опыте (включая ошибки).
3. Самостоятельность (self-concept). Взрослые сами отвечают за решения в отношении обучения, в том числе в планирование и оценку качества преподавания.
4. Готовность. Взрослые более готовы изучать предметы, которые могут немедленно применять в своей работе или жизни.
5. Ориентация на проблему. Обучение взрослых должно строиться вокруг проблемы, а не вокруг контента.
6. Мотивация. Мотивация взрослых скорее внутренняя (улучшение жизни, рост уверенности, удовлетворенность работой), чем внешняя (оценки, учебные достижения).
Эти идеи совпадают с тем, как у нас в Systems.Education устроено обучение (мы пришли у этому на собственном опыте, без теории) — работа над кейсом в течение курса, никаких оценок, обучение выстроено вокруг получения реального опыта, применять можно сразу, есть возможность углубить или пропустить какую-то тему, если группе это нужно (или не нужно).
Однако многие онлайн-курсы сделаны по прямо противоположным принципам! Без объяснения, зачем вам нужно это обучение (это скорее внешний фактор, когда вас компания посылает на обучение, не объясняя, зачем). С минимальным опытом (пройдите тесты, вот и весь опыт). Без вариантов влияния на планирование, содержание и темп обучения (а тем более — без оценки качества преподавания). С кучей теории, которую непонятно, как применить. С занятиями, выстроенными вокруг контента (это вообще не обучение, это ознакомление). И с мотивацией в виде оценок и геймификации.
Есть, конечно, совсем противоположный полюс — типа "Арзамаса" и "Страдариума" — курсы явно не для применения прямо сейчас и организованные вокруг контента (хотя в Страдариуме есть курсы с практическими заданиями — например, в курсе по исторической кухне дают задание приготовить что-то по средневековым рецептам). Вот про эту сторону обучения я плохо понимаю, хотя проекты явно успешны.
👍10❤3😁2
Часто возникает вопрос — какой выбрать режим интеграции — синхронный или асинхронный.
Особенно если у вас в инфраструктуре есть и то, и то. То есть, вы приходите к владельцу/архитектору системы, с которой хотите интегрироваться, а он говорит: у нас и REST API есть, и к Кафке мы подключены, нам в принципе всё равно, что для тебя сделать, а тебе-то как удобнее? То есть, перекладывает выбор на аналитика. А как аналитику выбрать? Ну, провести анализ, а что анализировать-то?
Тем более, что вариантов у вас три (да ещё с подвариантами):
1. Синхронная интеграция (запрос-ответ, выполняемый немедленно)
— в пределе — постоянный двунаправленный канал (websockets)
2. Асинхронная (и запрос, и ответ асинхронные; по сути, двунаправленный паттерн "публикатор/подписчик", обычно это топик для запросов и топик для ответов)
3. Смешанная или гибридная (обычно синхронный запрос и асинхронный ответ), причем тут два варианта:
— ответ через очередь сообщений;
— ответ через прямое обращение (webhook, подписки в graphql / grpc)
Итого, на что смотрим и что анализируем:
1. Требования бизнес-процесса: нужен ли нам по сути деятельности немедленный ответ? (скорость ответа — десятки и сотни миллисекунд). То есть, онлайн-игры, чаты, совместное редактирование документов, управление видеоконференциями — это вебсокеты или что-то похожее. Онлайн-платежи, переводы, запрос баланса, аренда самоката, открытие автомобиля каршеринга, перевод, заполнение форм и вообще действия в интерфейсе — это синхронный запрос-ответ, REST API и RPC в любых видах.
2. Если время выполнения запроса может превышать секунды (граница тут тонкая, как видите) — можно думать про асинхронное взаимодействие. Нужны уточняющие вопросы:
— Нужно ли сохранять все запросы? Будем ли мы перепосылать каждый запрос, если его не смогли обработать? (насколько ценна информация и насколько быстро она меняется? Важен ли нам конкретный экземпляр запроса? Заказ в магазине, вызов такси и запрос на создание документа точно будем перепосылать. А вот запрос остатков товара, оповещение о текущем положении вызванной машины, подтверждающий код — можем и пропустить, сохранять его не нужно — ответ именно на этот запрос нам не актуален, мы другой отправим. То есть, если промежуточное хранение не нужно — выбираем синхронную связь с возможными потерями, если нужно сохранять сообщение или обеспечить точный порядок сообщений — асинхронную очередь.
— Нагрузка, которую мы обеспечим взаимодействующей системе: сможет ли её API выдержать наши запросы? Какой у системы RPS и насколько часто мы к ней собираемся обращаться? Возможно, для разгрузки системы перед ней нужно поставить очередь.
— Как долго обрабатывается наш запрос? Если смежная система будет обрабатывать секунды и минуты — это точно асинхрон или гибрид: мы можем отдать команду на старт процесса синхронно (через REST API), а получить ответ асинхронно: через webhook, если нам ответ не очень важен, или через очередь, если ответ для нас важен, или ответов может быть несколько и важна их очередность.
— Мы обращаемся к одной системе, или ко многим сразу? Например, у нас много систем, в которых учитываются разные банковские или страховые продукты для одного клиента, и мы хотим опросить все системы. Можем на своей стороне делать по запросу к каждой системе, а можем кинуть один запрос в очередь запросов, и пусть все системы оттуда его считают и отвечают в своем темпе. Если число систем неизменно, а отвечают они быстро — это API Gateway. Если системы по-разному нагружены, и число их может расти — лучше очередь.
— Может ли наш запрос выполниться в одной системе за один раз, или это транзакция, которая выполняется в нескольких системах? Скорее всего, распределенная транзакция, особенно если это хореографическая сага, потребует асинхронной интеграции.
Ну и помним, что организация очередей и брокеров не дается бесплатно, это всегда, с одной стороны, вычислительные ресурсы, а, с другой — усложнение логики работы и тестирования.
А если вы встречали хороший алгоритм для выбора режима интеграции — скиньте в комменты, всем будет полезно.
Особенно если у вас в инфраструктуре есть и то, и то. То есть, вы приходите к владельцу/архитектору системы, с которой хотите интегрироваться, а он говорит: у нас и REST API есть, и к Кафке мы подключены, нам в принципе всё равно, что для тебя сделать, а тебе-то как удобнее? То есть, перекладывает выбор на аналитика. А как аналитику выбрать? Ну, провести анализ, а что анализировать-то?
Тем более, что вариантов у вас три (да ещё с подвариантами):
1. Синхронная интеграция (запрос-ответ, выполняемый немедленно)
— в пределе — постоянный двунаправленный канал (websockets)
2. Асинхронная (и запрос, и ответ асинхронные; по сути, двунаправленный паттерн "публикатор/подписчик", обычно это топик для запросов и топик для ответов)
3. Смешанная или гибридная (обычно синхронный запрос и асинхронный ответ), причем тут два варианта:
— ответ через очередь сообщений;
— ответ через прямое обращение (webhook, подписки в graphql / grpc)
Итого, на что смотрим и что анализируем:
1. Требования бизнес-процесса: нужен ли нам по сути деятельности немедленный ответ? (скорость ответа — десятки и сотни миллисекунд). То есть, онлайн-игры, чаты, совместное редактирование документов, управление видеоконференциями — это вебсокеты или что-то похожее. Онлайн-платежи, переводы, запрос баланса, аренда самоката, открытие автомобиля каршеринга, перевод, заполнение форм и вообще действия в интерфейсе — это синхронный запрос-ответ, REST API и RPC в любых видах.
2. Если время выполнения запроса может превышать секунды (граница тут тонкая, как видите) — можно думать про асинхронное взаимодействие. Нужны уточняющие вопросы:
— Нужно ли сохранять все запросы? Будем ли мы перепосылать каждый запрос, если его не смогли обработать? (насколько ценна информация и насколько быстро она меняется? Важен ли нам конкретный экземпляр запроса? Заказ в магазине, вызов такси и запрос на создание документа точно будем перепосылать. А вот запрос остатков товара, оповещение о текущем положении вызванной машины, подтверждающий код — можем и пропустить, сохранять его не нужно — ответ именно на этот запрос нам не актуален, мы другой отправим. То есть, если промежуточное хранение не нужно — выбираем синхронную связь с возможными потерями, если нужно сохранять сообщение или обеспечить точный порядок сообщений — асинхронную очередь.
— Нагрузка, которую мы обеспечим взаимодействующей системе: сможет ли её API выдержать наши запросы? Какой у системы RPS и насколько часто мы к ней собираемся обращаться? Возможно, для разгрузки системы перед ней нужно поставить очередь.
— Как долго обрабатывается наш запрос? Если смежная система будет обрабатывать секунды и минуты — это точно асинхрон или гибрид: мы можем отдать команду на старт процесса синхронно (через REST API), а получить ответ асинхронно: через webhook, если нам ответ не очень важен, или через очередь, если ответ для нас важен, или ответов может быть несколько и важна их очередность.
— Мы обращаемся к одной системе, или ко многим сразу? Например, у нас много систем, в которых учитываются разные банковские или страховые продукты для одного клиента, и мы хотим опросить все системы. Можем на своей стороне делать по запросу к каждой системе, а можем кинуть один запрос в очередь запросов, и пусть все системы оттуда его считают и отвечают в своем темпе. Если число систем неизменно, а отвечают они быстро — это API Gateway. Если системы по-разному нагружены, и число их может расти — лучше очередь.
— Может ли наш запрос выполниться в одной системе за один раз, или это транзакция, которая выполняется в нескольких системах? Скорее всего, распределенная транзакция, особенно если это хореографическая сага, потребует асинхронной интеграции.
Ну и помним, что организация очередей и брокеров не дается бесплатно, это всегда, с одной стороны, вычислительные ресурсы, а, с другой — усложнение логики работы и тестирования.
А если вы встречали хороший алгоритм для выбора режима интеграции — скиньте в комменты, всем будет полезно.
👍36🔥14❤5
Вообще я сегодня про другое хотел написать, но невозможно пройти мимо актуальной темы: буквально на наших глазах развернулась поучительная история: как Яндекс почти положил службу точного времени в Рунете.
Краткое содержание: с середины октября российские сервера точного времени (NTP) второго уровня, поддерживаемые сообществом (то есть, люди по собственной инициативе у себя их развернули на роутерах, на своих серверах), испытали практически DDoS-атаку — трафик на них катастрофически вырос, и люди стали их отключать. Из 140 серверов осталось 5. Оказалось, этот трафик посылают умные колонки от Яндекса, в которые с очередным обновлением прошивки приехал баг, заставляющий их слать запросы на синхронизацию времени каждые 5 секунд.
Обнаружил это один из участников пула NTP, и опубликовал 24 ноября статью на Хабре, чтобы привлечь внимание к проблеме. Сейчас Яндекс баг уже признал и исправил, и пообещал установить собственные сервера точного времени, а не полагаться на общественные.
Вопрос методический: чья эта область ответственности?
Кажется, аналитики вообще не очень часто думают об инфраструктурных вещах, таких как DNS или NTP-сервера; на курсах по проектированию интеграций я, кажется, ни у кого не слышал даже упоминания про синхронизацию времени и протокол NTP, хотя это критически важно для журналирования и для разбора событий безопасности. Почти все стандарты безопасности указывают на необходимость установки единого времени на всех системах, входящих в защищенный контур.
Яндексу в колонке точное время нужно для будильников, таймеров и календаря, а также для некоторых технических вещей.
И когда это устройство было экспериментальным — никто особенно не задумывался над серьезностью такого взаимодействия. Ну, сели на общий pool.ntp.org, который используется всеми линуксами и большинством устройств. Оно работает, и ладно.
Когда колонки стали продавать миллионами в год, это уже совсем другой уровень ответственности (ещё один вопрос из курса по интеграциям — с какой скоростью вы собираетесь масштабироваться?). Один непротестированный апдейт — и вся инфраструктура легла.
На мой взгляд, здесь есть три момента, которые относятся к задачам системного аналитика:
1. Анализ эффектов при масштабировании (рост нагрузки на смежные системы, превышение лимитов внешних API);
2. Анализ условий использования внешних систем (у проекта NTPPool есть гайдлайны для вендоров оборудования, им нужно следовать);
3. Контроль и учет всех входов и выходов системы (Сергей Нужненко рассказывал об этом упражнении на Flow).
Краткое содержание: с середины октября российские сервера точного времени (NTP) второго уровня, поддерживаемые сообществом (то есть, люди по собственной инициативе у себя их развернули на роутерах, на своих серверах), испытали практически DDoS-атаку — трафик на них катастрофически вырос, и люди стали их отключать. Из 140 серверов осталось 5. Оказалось, этот трафик посылают умные колонки от Яндекса, в которые с очередным обновлением прошивки приехал баг, заставляющий их слать запросы на синхронизацию времени каждые 5 секунд.
Обнаружил это один из участников пула NTP, и опубликовал 24 ноября статью на Хабре, чтобы привлечь внимание к проблеме. Сейчас Яндекс баг уже признал и исправил, и пообещал установить собственные сервера точного времени, а не полагаться на общественные.
Вопрос методический: чья эта область ответственности?
Кажется, аналитики вообще не очень часто думают об инфраструктурных вещах, таких как DNS или NTP-сервера; на курсах по проектированию интеграций я, кажется, ни у кого не слышал даже упоминания про синхронизацию времени и протокол NTP, хотя это критически важно для журналирования и для разбора событий безопасности. Почти все стандарты безопасности указывают на необходимость установки единого времени на всех системах, входящих в защищенный контур.
Яндексу в колонке точное время нужно для будильников, таймеров и календаря, а также для некоторых технических вещей.
И когда это устройство было экспериментальным — никто особенно не задумывался над серьезностью такого взаимодействия. Ну, сели на общий pool.ntp.org, который используется всеми линуксами и большинством устройств. Оно работает, и ладно.
Когда колонки стали продавать миллионами в год, это уже совсем другой уровень ответственности (ещё один вопрос из курса по интеграциям — с какой скоростью вы собираетесь масштабироваться?). Один непротестированный апдейт — и вся инфраструктура легла.
На мой взгляд, здесь есть три момента, которые относятся к задачам системного аналитика:
1. Анализ эффектов при масштабировании (рост нагрузки на смежные системы, превышение лимитов внешних API);
2. Анализ условий использования внешних систем (у проекта NTPPool есть гайдлайны для вендоров оборудования, им нужно следовать);
3. Контроль и учет всех входов и выходов системы (Сергей Нужненко рассказывал об этом упражнении на Flow).
🔥38🤔3🙏3
А написать я хотел про синхронные и асинхронные взаимодействия, по следам предыдущего (теперь уже пред-предыдущего) поста.
Андрей Бураков справедливо заметил, что WebSockets-то асинхронный, а я его в синхронные записал, вот позор.
Но логика у меня в этот момент была вот какая: если нам нужен быстрый отклик — мы берем паттерн "запрос-ответ", то есть RPC и REST. Но если нам нужен ещё более быстрый отклик — мы берём WebSockets, где взаимодействие асинхронное. Ну или используем Long Polling, WebHooks или MQTT — все они асинхронные, и все применяются, когда нам нужно очень быстро отреагировать на событие.
Следующий шаг в этом же направлении, но на другом уровне, сделал Google со своим протоколом QUIC, заменяющим TCP. Потому что установка соединения TCP — слишком дорогая и долгая операция, а делать её приходится почти при каждом запросе (да, есть keep-alive, тогда соединения будут держаться дольше, но у этого есть и обратная сторона — именно это соединение нужно использовать, пока оно живо. Иначе у вас будет много живых соединений и, соответственно, много занятых портов).
Протокол QUIC в основном ориентирован на веб-браузеры, а веб-браузеры имеют обыкновение запрашивать много разных ресурсов одновременно. Хотя каждый запрос сам по себе синхронный, выполняются они в java noscript'е асинхронно, через промисы и async/await, и про это есть много шуток у фронтендеров — очень больная тема, сложно понять.
Хуже того, ваш компьютер внутри тоже весь работает асинхронно — через механизм прерываний. Любое действие — нажатие на кнопку на клавиатуре, движение мышью, поступление нового пакета на сетевой адаптер — на самом деле останавливает выполняемую программу и вызывает специальный обработчик. И очереди, очереди везде!
Ну и как только нам не нужна мгновенная реакция, мы тоже используем очереди. Асинхрон, когда нам нужно быстро отреагировать, асинхрон, когда нам не нужно быстро реагировать.
Получается, в этом в целом асинхронном мире есть довольно узкая прослойка — место для условно синхронных коммуникаций, где-то в районе от 100 миллисекунд до секунды, где они могут работать. Именно здесь работают все пользовательские интерфейсы, и именно в этом временном промежутке вырос весь Web на базе REST API.
По случайному совпадению, этот диапазон как раз соответствует человеческому восприятию "мгновенной реакции". Она как раз примерно от 100-120 мс у гонщиков F1, пилотов истребителей и топовых кибер-спортсменов, до 250-300 мс — у обычных людей. Можете проверить себя: https://humanbenchmark.com/tests/reactiontime , у меня как раз 253 получилось в среднем. Хорошее пятничное развлечение :)
Так случайно совпало, что типичные http-запросы выполняются как раз примерно за 300-900 мс (передача данных через websocket — 200 мс). Действий быстрее 13 мс человек вообще не воспринимает (скорость обмена в 5G-сетях — 15 мс, это быстро). Аукцион рекламодателей за рекламное место на веб-странице — RTB — занимает 100-200 мс. В высокочастотном трейдинге решение о сделке принимается за микросекунды. На таких скоростях важным становится расстояние между серверами, поэтому их ставят прямо в датацентре биржи или вообще втыкают прямо в PCI-шину биржевого сервера. Вызов обработчика прерываний вообще в тактах процессора считается — это наносекунды для современных компьютеров.
Такие скорости у нас. И в некоторых случаях становится принципиально, что действие происходит не мгновенно, а за конкретное не нулевое время.
Андрей Бураков справедливо заметил, что WebSockets-то асинхронный, а я его в синхронные записал, вот позор.
Но логика у меня в этот момент была вот какая: если нам нужен быстрый отклик — мы берем паттерн "запрос-ответ", то есть RPC и REST. Но если нам нужен ещё более быстрый отклик — мы берём WebSockets, где взаимодействие асинхронное. Ну или используем Long Polling, WebHooks или MQTT — все они асинхронные, и все применяются, когда нам нужно очень быстро отреагировать на событие.
Следующий шаг в этом же направлении, но на другом уровне, сделал Google со своим протоколом QUIC, заменяющим TCP. Потому что установка соединения TCP — слишком дорогая и долгая операция, а делать её приходится почти при каждом запросе (да, есть keep-alive, тогда соединения будут держаться дольше, но у этого есть и обратная сторона — именно это соединение нужно использовать, пока оно живо. Иначе у вас будет много живых соединений и, соответственно, много занятых портов).
Протокол QUIC в основном ориентирован на веб-браузеры, а веб-браузеры имеют обыкновение запрашивать много разных ресурсов одновременно. Хотя каждый запрос сам по себе синхронный, выполняются они в java noscript'е асинхронно, через промисы и async/await, и про это есть много шуток у фронтендеров — очень больная тема, сложно понять.
Хуже того, ваш компьютер внутри тоже весь работает асинхронно — через механизм прерываний. Любое действие — нажатие на кнопку на клавиатуре, движение мышью, поступление нового пакета на сетевой адаптер — на самом деле останавливает выполняемую программу и вызывает специальный обработчик. И очереди, очереди везде!
Ну и как только нам не нужна мгновенная реакция, мы тоже используем очереди. Асинхрон, когда нам нужно быстро отреагировать, асинхрон, когда нам не нужно быстро реагировать.
Получается, в этом в целом асинхронном мире есть довольно узкая прослойка — место для условно синхронных коммуникаций, где-то в районе от 100 миллисекунд до секунды, где они могут работать. Именно здесь работают все пользовательские интерфейсы, и именно в этом временном промежутке вырос весь Web на базе REST API.
По случайному совпадению, этот диапазон как раз соответствует человеческому восприятию "мгновенной реакции". Она как раз примерно от 100-120 мс у гонщиков F1, пилотов истребителей и топовых кибер-спортсменов, до 250-300 мс — у обычных людей. Можете проверить себя: https://humanbenchmark.com/tests/reactiontime , у меня как раз 253 получилось в среднем. Хорошее пятничное развлечение :)
Так случайно совпало, что типичные http-запросы выполняются как раз примерно за 300-900 мс (передача данных через websocket — 200 мс). Действий быстрее 13 мс человек вообще не воспринимает (скорость обмена в 5G-сетях — 15 мс, это быстро). Аукцион рекламодателей за рекламное место на веб-странице — RTB — занимает 100-200 мс. В высокочастотном трейдинге решение о сделке принимается за микросекунды. На таких скоростях важным становится расстояние между серверами, поэтому их ставят прямо в датацентре биржи или вообще втыкают прямо в PCI-шину биржевого сервера. Вызов обработчика прерываний вообще в тактах процессора считается — это наносекунды для современных компьютеров.
Такие скорости у нас. И в некоторых случаях становится принципиально, что действие происходит не мгновенно, а за конкретное не нулевое время.
Human Benchmark
Reaction Time Test
Reaction Time Test: The simple, accurate online reaction time tester.
👍15❤8
На тренинге по интеграциям возник вопрос: что куда класть в http-запросе (в REST API). Решил разложить по полочкам (pun intended).
Полочек в http четыре штуки:
➡️ путь — path или route, эндпоинт, он же на жаргоне яндексоидов "ручка" (то, что после адреса сервера, за символом '/' — иерархия типов ресурсов и их идентификаторов. По аналогии с путем к файлу на диске, в пути говорят о вложенности — как будто каждый следующий уровень в цепочке '/' вложен в предыдущий. То есть, /orders/123456 — это заказ с id=123456, а /orders/123456/items — это перечень товаров в этом заказе, товары "вложены" в заказ)
➡️ параметры запроса, или query (то, что в конце URL, за символом '?' — перечисление параметров в формате имя=значение, разделенных &.)
Метод http, путь, параметры и версия протокола вместе называется называется строкой запроса или стартовой строкой. Строки запроса сохраняются в логах сервера.
➡️ заголовки запроса — http headers (передаются после строки запроса в виде пар "имя":"значение"). Обычно не сохраняются в логах, но иногда могут (можно настроить частичное сохранение — например, значение cookie или токенов точно не нужно сохранять, т.к. их можно использовать для выдачи себя за другого пользователя).
➡️ тело запроса — http body (тут понятно, это сами содержательные данные, которые мы передаем).
Есть из чего выбрать! Понятно, что идентификатор запрашиваемого ресурса мы обычно размещаем в пути, а содержимое помещаем в теле запроса (если это POST/PUT/PATCH). А если мы хотим указать связь нашего ресурса с другим? Например, связь заказов с клиентом? Тут уже могут быть два варианта: nested resources (вложенные ресурсы: /clients/689697/orders) или flat (плоские: /orders?client=689697, в API только пути с названиями ресурсов).
А если мы хотим указать версию API, у нас ещё больше вариантов: путь (/api/v1/orders), параметры (/api/orders?version=1) и заголовки (через кастомный заголовок: X-API-Version: 1, или через стандартный заголовок Accept: application/json; version=1 ). Я видел даже парочку случаев, когда версия передавалась в теле(!), даже для GET (хотя вообще сервер должен игнорировать тело GET-запроса).
Или, например, параметры пагинации. Тут у нас опять варианты: параметры, заголовок или тело. В пути не видел, но не исключаю — фантазия у людей безгранична.
Вопросы эти очень дискуссионные, я для себя выработал такие правила:
Путь — это указатель на коллекцию ресурсов или конкретный экземпляр. Лучше не тянуть туда ни версионность, ни фильтры, ни метаданные. Идентификатор в пути может быть только один (то есть, если мы описываем вложенные ресурсы, там может быть идентификатор на конце, или вторым от конца. Таким образом, вложенность будет только двухуровневая, и не будет диких URL типа /cities/77/pickpoints/35/clients/689697/orders/123456/items)
Параметры запроса — это ограничения на выдаваемую коллекцию ресурсов или набор полей одного ресурса. Поэтому тут будет простой поиск, фильтрация, набор полей в выдаче, пагинация, сортировка. То есть, это метаданные, относящиеся к ресурсу. Если мы хотим получить заказы клиента, доставленные в пункт выдачи с id=35, это будет выражено так: clients/689697/orders?city=77&pickpoint=35 (мы ограничиваем спискок заказов).
Заголовки — это метаданные запроса (а не ресурса). Это всё, что касается форматов выдачи (я видел API, в которых формат был зашит в путь: /api/xml/orders и /api/json/orders — не делайте так!), версии API и версии ресурса, кэша, параметров соединения, id запроса и т.п. Дискуссионный вопрос про пагинацию: её можно поместить и в заголовки тоже, как и ответную информацию (текущая страница, общее число страниц, число записей всего, следующая страница, предыдущая страница). Часто метаинформацию про пагинацию помещают в тело ответа, но, как по мне, это перегружает структуру ответа и может сделать её разнотипной для разных ответов — будьте с этим осторожнее.
Полочек в http четыре штуки:
Метод http, путь, параметры и версия протокола вместе называется называется строкой запроса или стартовой строкой. Строки запроса сохраняются в логах сервера.
Есть из чего выбрать! Понятно, что идентификатор запрашиваемого ресурса мы обычно размещаем в пути, а содержимое помещаем в теле запроса (если это POST/PUT/PATCH). А если мы хотим указать связь нашего ресурса с другим? Например, связь заказов с клиентом? Тут уже могут быть два варианта: nested resources (вложенные ресурсы: /clients/689697/orders) или flat (плоские: /orders?client=689697, в API только пути с названиями ресурсов).
А если мы хотим указать версию API, у нас ещё больше вариантов: путь (/api/v1/orders), параметры (/api/orders?version=1) и заголовки (через кастомный заголовок: X-API-Version: 1, или через стандартный заголовок Accept: application/json; version=1 ). Я видел даже парочку случаев, когда версия передавалась в теле(!), даже для GET (хотя вообще сервер должен игнорировать тело GET-запроса).
Или, например, параметры пагинации. Тут у нас опять варианты: параметры, заголовок или тело. В пути не видел, но не исключаю — фантазия у людей безгранична.
Вопросы эти очень дискуссионные, я для себя выработал такие правила:
Путь — это указатель на коллекцию ресурсов или конкретный экземпляр. Лучше не тянуть туда ни версионность, ни фильтры, ни метаданные. Идентификатор в пути может быть только один (то есть, если мы описываем вложенные ресурсы, там может быть идентификатор на конце, или вторым от конца. Таким образом, вложенность будет только двухуровневая, и не будет диких URL типа /cities/77/pickpoints/35/clients/689697/orders/123456/items)
Параметры запроса — это ограничения на выдаваемую коллекцию ресурсов или набор полей одного ресурса. Поэтому тут будет простой поиск, фильтрация, набор полей в выдаче, пагинация, сортировка. То есть, это метаданные, относящиеся к ресурсу. Если мы хотим получить заказы клиента, доставленные в пункт выдачи с id=35, это будет выражено так: clients/689697/orders?city=77&pickpoint=35 (мы ограничиваем спискок заказов).
Заголовки — это метаданные запроса (а не ресурса). Это всё, что касается форматов выдачи (я видел API, в которых формат был зашит в путь: /api/xml/orders и /api/json/orders — не делайте так!), версии API и версии ресурса, кэша, параметров соединения, id запроса и т.п. Дискуссионный вопрос про пагинацию: её можно поместить и в заголовки тоже, как и ответную информацию (текущая страница, общее число страниц, число записей всего, следующая страница, предыдущая страница). Часто метаинформацию про пагинацию помещают в тело ответа, но, как по мне, это перегружает структуру ответа и может сделать её разнотипной для разных ответов — будьте с этим осторожнее.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19👍6❤3
Тело — непосредственно сам ресурс или коллекция ресурсов. Метаданные о ресурсе лучше отдать в заголовках ответа, хотя я вижу часто подходы, когда метаданные отдают в одном json'е с содержательными данными, как например, в спецификации JSON:API. Там у них вообще в ответе сразу и данные (data), и ошибки (errors), и метаданные (meta), и ссылки (links), и вложенные объекты (included):
Мне кажется, это уже перебор — каждый раз придется парсить ответ, чтобы вытащить оттуда нужное.
Тут надо принять решение, как вы действуете. Причем лучше на уровне компании, если у вас много API — чтобы они были единообразными. Я за чистоту: тело — для содержательных данных, заголовки — для метаданных, параметры — для ограничения содержания данных, путь — для указания понятий, которыми мы оперируем.
Let's discuss!
{
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"noscript": "JSON:API paints my bikeshed!"
},
"links": {
"self": "http://example.com/articles/1"
},
"relationships": {
"author": {
"links": {
"self": "http://example.com/articles/1/relationships/author",
"related": "http://example.com/articles/1/author"
},
"data": { "type": "people", "id": "9" }
},
"comments": {
"links": {
"self": "http://example.com/articles/1/relationships/comments",
"related": "http://example.com/articles/1/comments"
},
"data": [
{ "type": "comments", "id": "5" },
{ "type": "comments", "id": "12" }
]
}
}
}],
"included": [{
"type": "people",
"id": "9",
"attributes": {
"firstName": "Dan",
"lastName": "Gebhardt",
"twitter": "dgeb"
},
"links": {
"self": "http://example.com/people/9"
}
}, {
"type": "comments",
"id": "5",
"attributes": {
"body": "First!"
},
"relationships": {
"author": {
"data": { "type": "people", "id": "2" }
}
},
"links": {
"self": "http://example.com/comments/5"
}
}, {
"type": "comments",
"id": "12",
"attributes": {
"body": "I like XML better"
},
"relationships": {
"author": {
"data": { "type": "people", "id": "9" }
}
},
"links": {
"self": "http://example.com/comments/12"
}
}]
}Мне кажется, это уже перебор — каждый раз придется парсить ответ, чтобы вытащить оттуда нужное.
Тут надо принять решение, как вы действуете. Причем лучше на уровне компании, если у вас много API — чтобы они были единообразными. Я за чистоту: тело — для содержательных данных, заголовки — для метаданных, параметры — для ограничения содержания данных, путь — для указания понятий, которыми мы оперируем.
Let's discuss!
👍18🔥12
Сейчас будет сложный пост, я бы даже сказал — философский. На Flow в одном разговоре зашла речь о том, что различные документы и диаграммы — это разные проекции будущей системы. Мол, система многомерна и многоаспектна, и мы не можем её представить целиком, но можем создавать отдельные проекции, через эти проекции подсвечивать какие-то аспекты системы, и так приближаться к пониманию системы во всей ей полноте.
То есть, как будто у нас есть какая-то идеальная система, подходящая для решения нашей задачи, и нужно только исследовать этот идеальный объект, описать его доступными нам языками, и проверить сочетаемость этих описаний — и чем тщательней мы это сделаем, тем лучше мы приблизимся к пониманию структуры идеального объекта.
Мне кажется, в таком подходе есть большая доля идей позитивизма, даже логического позитивизма. Его адепты верили, что любое знание можно вывести и доказать либо путем эмпирических наблюдений (то есть, проверить на опыте), либо из логических правил и преобразований. Это идеи 20-30-х годов XX века, т.н. "Венский кружок". Дальнейшие разработки, в том числе членов кружка — Гёделя, например — привели к формальным доказательствам того, что истинность (и даже непротиворечивость) сложных систем доказать невозможно. Дальше больше — в квантовой физике обнаружился принцип неопределенности, в термодинамике — хаотические системы, в информатике — проблема остановки (принципиальная невозможность доказать — зациклится программа или выдаст ответ. в частности, это означает невозможность доказать наличие решений у некоторых уравнений).
Короче, мир оказался основанным на недоказуемых теориях, причем их недоказуемость оказалась строго доказанной!
Поэтому от позитивных представлений о познаваемости и логической выводимости философам пришлось отказаться. В науке критерием стала не доказуемость, а фальсифицируемость: нужно не доказывать верную теорию, а отбрасывать ложные, не прошедшие проверку практикой. Про абсолютную истинность речь уже не идёт — как-то описываем реальность, и ладно.
В ту же ловушку позитивизма попала и разработка ПО — с идеей о том, что есть какое-то идеальное решение, удовлетворяющее всем требованиям, нужно только отыскать эти требования и это решение.
Точнее, разработка прошла все этапы:
— метафизику, то есть разговор об очень абстрактных понятиях, не имеющих строгого содержания ("требование", "решение", "проект", "система", "данные");
— позитивизм (мы можем всё определить, логически выразить и формально доказать);
— постпозитивизм в виде фальсифицируемости (не можем доказать правильность программы, но хотя бы можем сказать, что те функции на тех данных, что мы проверили, работают корректно — тестирование и BDD), конструктивизма (не существует абсолютной истины, мы конструируем подходящий нам результат в процессе совместной деятельности, постоянно проверяя результат опытом; важна структура этой деятельности — agile), и неопрагматизма (нечто, что мы называем, имеет смысл, пока это несёт для нас пользу в определенном контексте; нет описания реальности "вообще", есть описание под конкретную задачу — DDD).
Окончательно добивает остатки позитивизма современный подход к ИИ: оказывается, при помощи "грубой силы" и наращивания числа связей в сети можно гораздо лучше решать практические задачи, чем через построение абсолютной исчерпывающей модели (см. очень показательную историю последних лет компании Abbyy и их проекта Compreno — чем она закончилась, я думаю, вы все слышали).
Наглядно видно это и в истории REST, например — тот же HATEOAS очень оптимистично выглядит в теории, а на практике почти не применяется.
В общем, пост философский, и каждому нужно понять для себя — какие представления я кладу в основание своей картины мира? Метафизику, позитивизм, или современные подходы — лишенные идеального образца, но зато решающие задачу.
То есть, как будто у нас есть какая-то идеальная система, подходящая для решения нашей задачи, и нужно только исследовать этот идеальный объект, описать его доступными нам языками, и проверить сочетаемость этих описаний — и чем тщательней мы это сделаем, тем лучше мы приблизимся к пониманию структуры идеального объекта.
Мне кажется, в таком подходе есть большая доля идей позитивизма, даже логического позитивизма. Его адепты верили, что любое знание можно вывести и доказать либо путем эмпирических наблюдений (то есть, проверить на опыте), либо из логических правил и преобразований. Это идеи 20-30-х годов XX века, т.н. "Венский кружок". Дальнейшие разработки, в том числе членов кружка — Гёделя, например — привели к формальным доказательствам того, что истинность (и даже непротиворечивость) сложных систем доказать невозможно. Дальше больше — в квантовой физике обнаружился принцип неопределенности, в термодинамике — хаотические системы, в информатике — проблема остановки (принципиальная невозможность доказать — зациклится программа или выдаст ответ. в частности, это означает невозможность доказать наличие решений у некоторых уравнений).
Короче, мир оказался основанным на недоказуемых теориях, причем их недоказуемость оказалась строго доказанной!
Поэтому от позитивных представлений о познаваемости и логической выводимости философам пришлось отказаться. В науке критерием стала не доказуемость, а фальсифицируемость: нужно не доказывать верную теорию, а отбрасывать ложные, не прошедшие проверку практикой. Про абсолютную истинность речь уже не идёт — как-то описываем реальность, и ладно.
В ту же ловушку позитивизма попала и разработка ПО — с идеей о том, что есть какое-то идеальное решение, удовлетворяющее всем требованиям, нужно только отыскать эти требования и это решение.
Точнее, разработка прошла все этапы:
— метафизику, то есть разговор об очень абстрактных понятиях, не имеющих строгого содержания ("требование", "решение", "проект", "система", "данные");
— позитивизм (мы можем всё определить, логически выразить и формально доказать);
— постпозитивизм в виде фальсифицируемости (не можем доказать правильность программы, но хотя бы можем сказать, что те функции на тех данных, что мы проверили, работают корректно — тестирование и BDD), конструктивизма (не существует абсолютной истины, мы конструируем подходящий нам результат в процессе совместной деятельности, постоянно проверяя результат опытом; важна структура этой деятельности — agile), и неопрагматизма (нечто, что мы называем, имеет смысл, пока это несёт для нас пользу в определенном контексте; нет описания реальности "вообще", есть описание под конкретную задачу — DDD).
Окончательно добивает остатки позитивизма современный подход к ИИ: оказывается, при помощи "грубой силы" и наращивания числа связей в сети можно гораздо лучше решать практические задачи, чем через построение абсолютной исчерпывающей модели (см. очень показательную историю последних лет компании Abbyy и их проекта Compreno — чем она закончилась, я думаю, вы все слышали).
Наглядно видно это и в истории REST, например — тот же HATEOAS очень оптимистично выглядит в теории, а на практике почти не применяется.
В общем, пост философский, и каждому нужно понять для себя — какие представления я кладу в основание своей картины мира? Метафизику, позитивизм, или современные подходы — лишенные идеального образца, но зато решающие задачу.
❤22👍9🔥8🤔6❤🔥3
Про версионирование API, по итогам нескольких обсуждений: очень сильно зависит, что у вас за API (внутреннее или внешнее), кто ваши клиенты и насколько вы зависите от них (или они от вас).
Например, если ваше API — внешнее, а клиенты сильно зависят от вас, и вы хотите, чтобы они быстрее переходили на новые версии API —бейте лампочки в подъездах ставьте версию API в путь и давайте окно для перехода (несколько месяцев). У клиентов не будет других вариантов, кроме как перейти на новую версию — иначе у них очень грубо сломаются все вызовы, будут выдавать просто 404. Зато не будет шансов, что будет пропущена ошибка или сломается логика из-за разных форматов. Умерла так умерла. Так делают facebook (экстремистская деятельность которой запрещена на территории РФ), twitter и tiktok.
Facebook дает 90-дневный период для перехода, а X обещает не вносить ломающих изменений чаще, чем раз в год.
Кроме того, указание версии в пути позволяет легко отследить число клиентов, использующих каждую версию, по логам. Также не возникает проблемы с кэшем — не случится так, что закэшировалась старая версия. Правда, в URL возникает постоянное мерцание, и их нельзя сохранять — для старых ресурсов они испортятся (вопрос — по логике вашего бизнеса, может ли у клиента возникнуть потребность долго хранить URL ресурсов?)
Доходит иногда до смешного: в API платежного сервиса Stripe, судя по всему, сначала собирались использовать версионирование через путь (/v1/), но потом перешли на хедер Stripe-Version, который переключает(!) версию API, используемую этим клиентом. Если вы отправляете запрос с этим хедером, сервер запомнит, какую версию вы использовали, и остальные запросы будет обрабатывать как к этой версии. Это уже хранение состояния на сервере!
А вот VK принимает версию в параметре, но этот параметр является обязательным. Так у вас не меняется путь, но замусоривается хвост URL. Зато можно добавить параметр для версии, если вы забыли про него с самого начала.
Чтобы не замусоривались URL'ы, а вы сильно зависите от ваших клиентов — лучше не менять URL'ы, и давать возможность указать версию в параметрах или в хедере. Все варианты с хедером добавляют дополнительных мыслей разработчикам — теперь им ещё и про хедеры нужно думать. Тут возникают риски поймать ошибку: во-первых, эту штуку с хедерами тяжело тестировать, во-вторых — если мы меняем все пути в приложении, то подумаем и про остальные изменения.
Ещё один аргумент пуристов RESTа, что обсуждение версии ресурса — это часть обсуждения типа контента между клиентом и сервером. Клиент сообщает серверу о версии контента, который может принимать клиент, поэтому версия должна быть в хедере Accept: application/vnd.myapi.v2+json
В этом смысле интересно услышать мнение Роя Филдинга про версионирование. Оно очень короткое:
DON'T
Чуть подробнее Филдинг обрушивается на версионирование через версию в пути:
А правильный ответ, конечно, HATEOAS (чего бы мы ещё могли ждать от Филдинга).
Типа, если вы меняете структуру ответов и даже API — выразите это в ссылках, через гипермедиа. А если у вас изменения, которые должны сломать всех клиентов — значит, у вас новая система, меняйте не версию API, а сразу доменное имя — ведь теперь это другая система, верно? 🤯🤦🏼♂️
Вот это уже шестой вариант версионирования — через имя домена. Ну действительно — меняем api.server.com на api2.server.com. Интересная мысль!
Например, если ваше API — внешнее, а клиенты сильно зависят от вас, и вы хотите, чтобы они быстрее переходили на новые версии API —
Facebook дает 90-дневный период для перехода, а X обещает не вносить ломающих изменений чаще, чем раз в год.
Кроме того, указание версии в пути позволяет легко отследить число клиентов, использующих каждую версию, по логам. Также не возникает проблемы с кэшем — не случится так, что закэшировалась старая версия. Правда, в URL возникает постоянное мерцание, и их нельзя сохранять — для старых ресурсов они испортятся (вопрос — по логике вашего бизнеса, может ли у клиента возникнуть потребность долго хранить URL ресурсов?)
Доходит иногда до смешного: в API платежного сервиса Stripe, судя по всему, сначала собирались использовать версионирование через путь (/v1/), но потом перешли на хедер Stripe-Version, который переключает(!) версию API, используемую этим клиентом. Если вы отправляете запрос с этим хедером, сервер запомнит, какую версию вы использовали, и остальные запросы будет обрабатывать как к этой версии. Это уже хранение состояния на сервере!
А вот VK принимает версию в параметре, но этот параметр является обязательным. Так у вас не меняется путь, но замусоривается хвост URL. Зато можно добавить параметр для версии, если вы забыли про него с самого начала.
Чтобы не замусоривались URL'ы, а вы сильно зависите от ваших клиентов — лучше не менять URL'ы, и давать возможность указать версию в параметрах или в хедере. Все варианты с хедером добавляют дополнительных мыслей разработчикам — теперь им ещё и про хедеры нужно думать. Тут возникают риски поймать ошибку: во-первых, эту штуку с хедерами тяжело тестировать, во-вторых — если мы меняем все пути в приложении, то подумаем и про остальные изменения.
Ещё один аргумент пуристов RESTа, что обсуждение версии ресурса — это часть обсуждения типа контента между клиентом и сервером. Клиент сообщает серверу о версии контента, который может принимать клиент, поэтому версия должна быть в хедере Accept: application/vnd.myapi.v2+json
В этом смысле интересно услышать мнение Роя Филдинга про версионирование. Оно очень короткое:
DON'T
Чуть подробнее Филдинг обрушивается на версионирование через версию в пути:
a "v1" is a middle finger to your API customers, indicating RPC/HTTP (not REST)
А правильный ответ, конечно, HATEOAS (чего бы мы ещё могли ждать от Филдинга).
"hypermedia as the engine of application state" is a REST constraint. Not an option. Not an ideal. Hypermedia is a constraint. As in, you either do it or you aren’t doing REST. You can’t have evolvability if clients have their controls baked into their design at deployment. Controls have to be learned on the fly. That’s what hypermedia enables.
Типа, если вы меняете структуру ответов и даже API — выразите это в ссылках, через гипермедиа. А если у вас изменения, которые должны сломать всех клиентов — значит, у вас новая система, меняйте не версию API, а сразу доменное имя — ведь теперь это другая система, верно? 🤯🤦🏼♂️
Вот это уже шестой вариант версионирования — через имя домена. Ну действительно — меняем api.server.com на api2.server.com. Интересная мысль!
👍14❤7🤨4🤔3
Учат ли системному анализу в школе? Оказывается, да! В 10-11 классах. Есть вот целый учебник.
Системный анализ, в изложении авторов, представляет собой введение в системную инженерию (даже начинается с типового примера от системных инженеров — морской буровой платформы) + несколько расчетных упражнений по многокритериальному анализу.
Как думаете, поможет это в становлении системного аналитика? Оцените, кстати — на какую профессию там ориентируют школьников — генеральный конструктор, ни много ни мало!
Не знаю, правда, есть ли школы, в которых такой предмет реально преподают.
Системный анализ, в изложении авторов, представляет собой введение в системную инженерию (даже начинается с типового примера от системных инженеров — морской буровой платформы) + несколько расчетных упражнений по многокритериальному анализу.
Как думаете, поможет это в становлении системного аналитика? Оцените, кстати — на какую профессию там ориентируют школьников — генеральный конструктор, ни много ни мало!
Не знаю, правда, есть ли школы, в которых такой предмет реально преподают.
👍34🔥7❤1😁1🏆1