Разработка
«Давайте просто…»: системные идеи, которые звучат хорошо, но почти никогда не работают
Можете ли вы выбрать эти подходы, и они заработают? Да, конечно, можете. Всегда есть какой-то контекст, в котором они могут сработать, но чаще всего они просто не нужны, и есть лучший способ.
Марти Касадо поделился своей идеей «Идеи, которые звучат хорошо, но почти никогда не работают» в твиттере:
Он спросил, что еще, и я ответил кратким списком. Ниже — «почему» они не работают. Я предлагаю это, понимая, что инженерия — это также социальная наука, и то, что работает/не работает, зависит от контекста. Один из жизненных уроков заключается в том, что каждый раз, когда вы говорите инженеру (или пишете на сайте X), что что-то не будет работать, быстро возникает задача доказать обратное. Вот почему большая часть инженерного менеджмента (и архитектуры программного обеспечения) — это сочетание «правил большого пальца» и уроков, полученных тяжелым путем.
Я начал свои пункты с «давайте просто», потому что в 9 из 10 случаев, когда кто-то говорит «давайте просто», то, что за этим последует, в конечном итоге окажется намного сложнее, чем предполагал каждый из присутствующих в комнате. Я специально буду часто говорить «9 из 10 раз», потому что… опыт. Ниже я приведу два примера, но на каждый из них найдется полдюжины противоположных, которые я пережил.
Так почему же эти примеры «почти никогда не работают»?
Давайте просто сделаем возможность подключения
Когда вы уверены, что одна реализация не будет работать, вы думаете: «Я знаю, мы позволим разработчикам или, возможно, другим людям использовать ту же архитектуру и просто вставить новую реализацию». Тогда все, кто обращается к API, волшебным образом получают некоторые улучшения или новые возможности, ничего не меняя. Есть старая поговорка «API — это поведение, а не заголовочный файл/документация». Почти ничего нельзя сделать до такой степени подключаемым (pluggable), чтобы оно «просто работало». Самыми подключаемыми компонентами современного программного обеспечения, вероятно, являются драйверы устройств, которые позволили создать современный компьютер, но они работали настолько плохо, что либо больше не разрешается, либо современные ОС уже десятилетие создают свои собственные. Единственный способ сделать что-то по-настоящему подключаемым — это разработать вторую реализацию точно в то же время, что и основную. Тогда, по крайней мере, у вас будет доказательство того, что это может работать… один раз.
Давайте просто добавим API
Бесчисленное множество продуктов/компаний достигали определенного уровня успеха, а затем решали «нам нужна платформа и разработчики», и вскоре появлялсяAPI. Проблема с предложением API многогранна. Во-первых, быть поставщиком API — это целый склад ума и навыков, где вы постоянно обмениваете совместимость и интероперабельность на возможности, где вы ограничены в изменении вещей из-за унаследованного поведения или характеристик производительности, и вы, по сути, никогда не сможете изменить ситуацию.
Что еще более важно, предложение API не означает, что кто-то захочет им пользоваться. Почти каждый новый API появляется потому, что совместному продукту нужны функции, но он не хочет уделять им должного внимания (слишком маленький рынок, слишком вертикальный, слишком привязанный к конкретной области и т.д.), и теоретически API будет “распространен” среди некоторых партнеров в этой области. Оказывается, эти люди не сидят сложа руки и не ждут, когда они заполнят пробелы в вашем продукте. У них есть бизнес и клиенты, которые не хотят покупать еще один продукт для решения своих проблем. Наличие API—платформы — это серьезный бизнес с реальными требованиями. В создании платформы есть что-то волшебное, но редко это достигается простым “предложением некоторых API”, и даже если это так, шансы на то, что это обеспечит экономическую базу для сторонних разработчиков, невелики. Сложная задача! Отсюда и вознаграждение.
Давайте абстрагируем это еще раз
Одним из самых мудрых компьютерщиков, с которыми мне когда-либо приходилось работать, был легендарный Батлер Лэмпсон (Xerox, MIT, Microsoft и др.), который однажды сказал: «В компьютерной науке все проблемы могут быть решены с помощью дополнительного уровня косвенности/абстрации» («фундаментальная теорема разработки программного обеспечения”, как ее называют). В этом есть доля правды — настоящей правды. Есть две причины, объясняющие, почему это не удается.
Во-первых, часто инженеры знают об этом заранее, поэтому они слишком рано внедряют абстракции в архитектуру. Windows NT изобилует избыточными абстракциями, которые на самом деле никогда не использовались, в первую очередь потому, что они были там с самого начала, до того, как появился реальный план их использования. Я бы сравнил это с эволюцией Mac OS, где абстракции, которые казались странными, оказались полезными двумя выпусками позже, потому что был план. Во-вторых, абстракции, добавленные постфактум, могут стать очень сложными в обслуживании, трудно обеспечить их безопасность и оптимизировать производительность. Из-за этого вы получаете слишком много кода, который не использует новую абстракцию. Тогда у вас возникает головная боль при обслуживании.
Давайте сделаем это асинхронным
Большая часть первых 25 лет обучения информатике была посвящена выяснению того, как заставить все работать асинхронно. Если вы были аспирантом в 1980-х, вы целыми курсами получали знания об обедающих философах, производителях-потребителях или спящих парикмахерах. Современный мир в основном избавил от этой проблемы большинство инженеров, которые просто работают по правилам на уровне данных. Но на уровне пользовательского опыта остается желание сделать как можно больше работы и не заставлять людей ждать. Веб-фреймворки проделали огромную работу, чтобы абстрагироваться от этого. Но в 9 случаях из 10, когда вы выходите за рамки фреймворка или уровня данных и думаете, что можете самостоятельно управлять асинхронностью, у вас все получится, за исключением ошибки, которая обнаружится через год и которую вы никогда не сможете воспроизвести. Надеюсь, это не будет связано с повреждением данных, но я вас предупредил.
Давайте просто добавим средства контроля доступа позже
Когда в аспирантуре мы не говорили о философах, использующих вилки, мы обсуждали, где именно в системе должен быть контроль доступа. Сегодняшний мир значительно сложнее, чем во времена теоретических дебатов об управлении доступом, потому что системы подвергаются постоянным атакам. Конечно, все знают, что системы должны быть безопасными с самого начала, однако темпы выхода на рынок означают, что практически ни одна система с самого начала полностью не продумывала модель контроля доступа/безопасности. Практически невозможно правильно спроектировать средства контроля доступа к продукту, если вы с самого начала не рассматриваете это с точки зрения клиента и нападающего. Каким бы быстрым это ни казалось, в конечном итоге вы либо потерпите неудачу, либо вам придется переписывать продукт заново, и это будет ужасным испытанием для всех, включая клиентов.
Давайте просто синхронизируем данные
В этом мире множества устройств, SaaS-приложений или хранилищ данных очень часто можно услышать, как кто-то спрашивает: “Почему бы нам просто не синхронизировать данные?” Ха. @ROzzie (Рэй Оззи), который начинал с разработки продукта Plato, изобрел Lotus Notes, а также Groove и Talko и руководил созданием Microsoft Azure, был пионером в области клиент-серверной синхронизации и синхронизации данных. Его мудрые слова: “синхронизация — сложная проблема”. А в информатике сложная задача означает, что она сверхсложна и сопряжена с трудностями, которые можно решить только на собственном опыте. Эта проблема достаточно сложна с полным хранилищем семантических и транзакционных данных, но как только речь заходит о синхронизации больших двоичных объектов или неструктурированных данных, или, что еще хуже, о какой-либо трансляции данных, она очень быстро становится чрезвычайно сложной. Практически никогда не требуется основывать решение на синхронизации данных. Вот почему существуют многомиллиардные компании, которые занимаются синхронизацией.
Давайте сделаем это кроссплатформенным
Я обсуждаю этот вопрос всю свою компьютерную жизнь. Каждый раз, когда речь заходит об этом, кто-то показывает мне что-то, что, по их мнению, “отлично” работает кроссплатформенно, или кто-то рассказывает мне о Unity и играх. По-настоящему умные люди думают, что могут просто сказать “веб”. Я понимаю, но я все равно прав :-) Когда вы берете на себя обязательство создать что-то кроссплатформенное, независимо от того, насколько вы ориентированы на клиента и насколько благи ваши намерения, вы берете на себя обязательство создать операционную систему, облачного провайдера или браузер.
Как бы вы ни думали, что создаете что-то свое, переходя на кроссплатформенность, вы, по сути, создаете что-то из этого, просто “добавляя уровень абстракции” (см. выше). Вы думаете, что можете просто создать платформу с подключениями (см. выше). Реальность кроссплатформенности заключается в том, что она хорошо работает в двух случаях. Это работает, когда платформы новые — например, когда облако было связано с вычислениями и простым хранилищем, — и тогда имеет смысл быть абстракцией для двух игроков, выполняющих эту простую задачу. Это работает, когда ваше приложение/продукт новое и простое.
Оба эти метода терпят неудачу, когда вы отклоняетесь от базовой платформы или когда вы создаете возможности, которые совершенно по-разному проявляются в каждой целевой системе. Самый “известный” пример для меня — это когда Microsoft отказалась от разработки кроссплатформенного программного обеспечения для Mac именно потому, что стало слишком сложно создавать Office для Mac и Windows на основе одного и того же кода. Microsoft, по сути, существовала потому, что она занималась созданием кроссплатформенных приложений. Это работало, когда API ОС состоял из 100 страниц документации, и каждая ОС была производной от CP/M. Но мы форкнули код Office в 1998 году и никогда не оглядывались назад. Каждый день, когда я пользуюсь Mac Office, я вижу, что даже сегодня невозможно выполнять отличную работу на разных платформах. Если вы хотите узнать больше о моем мнении по этому поводу, пожалуйста, ознакомьтесь с этим.
Давайте просто сбежим в нативный код
Поскольку кроссплатформенность работает лишь короткое время, одним из наиболее распространенных решений, предлагаемых фреймворками и API-абстракциями, является возможность «сбежать в native». Идея в том, что платформа развилась или добавила функции, но их фреймворк/абстракция (пока?) не раскрывает, предположительно потому, что нужно будет создавать всю реализацию для других целей, которые еще не имеют такой возможности. На бумаге это «escape to native» звучит замечательно. Но это тоже никогда не работает, более чем в 9 случаях из 10. Причина довольно проста. Фреймворк или API, который вы используете и который абстрагирует некоторую нативную возможность, всегда поддерживает некоторое состояние или кэш того, что происходит в рамках созданной им абстракции. Когда вы обращаетесь к базовой нативной платформе, вы работаете со структурами данных и состоянием, о которых фреймворк не знает. Многие фреймворки предоставляют сложные механизмы для обмена данными или информацией о состоянии от вашего «escape to native» кода обратно к фреймворку. Это может немного помочь, но в мире автоматического управления памятью это решение сродни malloc/free, и я уверен, что сегодня никто не будет голосовать за такую архитектуру :-)
Всегда ли я был категоричным «противником» по всем этим вопросам? Конечно, нет. Можете ли вы выбрать эти подходы, и они заработают? Да, конечно, можете. Всегда есть какой-то контекст, в котором они могут сработать, но чаще всего они просто не нужны, и есть лучший способ. Всегда решайте проблемы, руководствуясь простыми принципами, и не прибегайте к программным шаблонам, которые так часто дают сбои.
-
Видео и подкасты для разработчиков4 недели назад
Как устроена мобильная архитектура. Интервью с тех. лидером юнита «Mobile Architecture» из AvitoTech
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.10
-
Новости2 недели назад
Видео и подкасты о мобильной разработке 2025.11
-
Видео и подкасты для разработчиков2 недели назад
Javascript для бэкенда – отличная идея: Node.js, NPM, Typescript