Индекс массива часто начинается с нуля по историческим и практическим причинам, связанным с архитектурой компьютеров и принципами работы с памятью. Это поведение стало стандартом в большинстве языков программирования (например, C, C++, Java, Python).
Массивы хранятся в памяти как последовательные ячейки, и для доступа к элементу массива используется смещение от начального адреса.
Если массив начинается с индекса
0, то адрес элемента вычисляется по формуле: \text{Адрес элемента} = \text{Базовый адрес} + (\text{индекс} \times \text{размер элемента})Например, для первого элемента массива (индекс
0): \text{Адрес} = \text{Базовый адрес} + (0 \times \text{размер элемента}) = \text{Базовый адрес}Процессоры и память работают с указателями и смещениями. Начало массива (индекс
0) соответствует базовому адресу, а следующие элементы смещаются на размер данных. Это соответствует базовой логике работы процессора и требует меньше вычислений.Индексация с нуля пришла из языка C и более ранних языков, таких как Assembly. Язык C, созданный в 1970-х годах, получил широкое распространение, и многие современные языки программирования унаследовали его подход. Например, в C указатель на массив указывает на первый элемент (
index 0), а доступ к элементам происходит через арифметику указателей.В языках низкого уровня (например, C) массив и указатель на его начало практически эквивалентны. Индексация с нуля позволяет упростить арифметику указателей: Если
ptr — указатель на начало массива, то ptr + i указывает на i-й элемент массива, где i = 0 указывает на первый элемент.В математике и теории множеств индексы и последовательности часто начинаются с
0. Например: Вектор длиной n имеет n элементов, и их индексы обычно лежат в диапазоне [0, n-1]. Хотя индексация с
1 может быть интуитивно понятной для некоторых людей (особенно не программистов), она требует дополнительных вычислений при адресации. Для индекса 1 формула смещения будет\text{Адрес элемента} = \text{Базовый адрес} + ((\text{индекс} - 1) \times \text{размер элемента})Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2❤1
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Это процесс контроля изменений и обновлений API, чтобы обеспечить стабильность работы существующих клиентов (пользователей API) и возможность внедрения новых функций. Правильное управление версиями помогает избежать неожиданных сбоев у потребителей API при обновлении или изменении его структуры.
Обновления API не должны нарушать работу клиентов, которые используют старые версии.
Новые функции могут сосуществовать с существующим функционалом.
Позволяет вносить улучшения в API без ущерба для текущих пользователей.
Разработчики API могут чётко сообщать, какая версия поддерживается, а какая устарела.
Версия API указывается как часть URL.
https://api.example.com/v1/users
https://api.example.com/v2/users
Плюсы и минусы
Версия передаётся в HTTP-заголовке запроса.
GET /users
Accept: application/vnd.example.v1+json
Плюсы и минусы
Версия указывается в качестве параметра запроса.
https://api.example.com/users?version=1
https://api.example.com/users?version=2
Плюсы и минусы
Версия API определяется через тип содержимого (Content-Type) или заголовок
Accept.GET /users
Accept: application/json; version=1
Плюсы и минусы
Подходит для большинства API, когда изменения значительны и нужны отдельные версии.
Подходят для больших корпоративных систем или случаев, когда нужно сохранить чистый URL.
Подойдут для небольших проектов или временного тестирования новых версий.
Следует правилам
MAJOR.MINOR.PATCH (например, v1.2.3): MAJOR: Несовместимые изменения, ломающие существующий код.
MINOR: Добавление новой функциональности, совместимое с предыдущими версиями.
PATCH: Исправления ошибок и мелкие изменения.
Чётко указывайте, как долго старые версии будут поддерживаться. Устаревшие версии нужно документировать и постепенно выводить из эксплуатации.
Обновления версий API должны сопровождаться подробной документацией. Информируйте пользователей о предстоящих изменениях и сроках вывода старых версий.
По возможности изменения должны быть обратно совместимыми, чтобы клиенты не сталкивались с неожиданными ошибками.
Всегда начинайте с v1 в URL или заголовках. Документируйте все изменения при выпуске новой версии. Устанавливайте сроки поддержки устаревших версий. Используйте семантическое версионирование для отслеживания изменений. Оповещайте пользователей API о планируемых обновлениях заранее. Тестируйте старые и новые версии API на совместимость.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Это веб-приложения, где основная страница загружается один раз, а последующие взаимодействия с пользователем обрабатываются динамически без полной перезагрузки страницы. Хотя SPA имеют ряд преимуществ, таких как улучшенный пользовательский опыт и высокая скорость отклика, у них также есть существенные недостатки, которые стоит учитывать при разработке.
Поисковые системы изначально плохо индексируют контент, который загружается динамически через JavaScript, так как страницы не содержат готового HTML-контента при первоначальной загрузке. Хотя поисковые роботы совершенствуются и могут обрабатывать JavaScript (например, Googlebot), это не всегда гарантирует корректную индексацию. Для решения этой проблемы разработчики используют Server-Side Rendering (SSR) или статическую генерацию страниц.
В SPA большая часть ресурсов приложения (HTML, CSS, JavaScript) загружается сразу при первом открытии страницы. Если приложение имеет много функционала и зависимости, это может привести к увеличению времени загрузки и ухудшению пользовательского опыта на медленных сетях.
SPA требует сложной архитектуры и более глубокого понимания работы фронтенда. Разработка включает управление состоянием приложения (например, с использованием Redux, Vuex) и маршрутизацией (например, React Router или Vue Router). Также необходимо реализовать оптимизацию производительности и кэширование данных для улучшения пользовательского опыта.
SPA более уязвимы для XSS-атак (межсайтовый скриптинг), так как большинство данных и логики обрабатывается на стороне клиента. JavaScript-код пользователя виден в браузере, что может предоставить злоумышленнику больше возможностей для анализа и атак. Необходимы дополнительные меры безопасности, такие как CSP (Content Security Policy), шифрование данных и защита от XSS.
Если JavaScript отключен в браузере пользователя, SPA не будет работать вообще, так как весь функционал зависит от клиентского выполнения JavaScript. Важно учитывать это при разработке приложений, критичных для доступности.
В SPA страницы не перезагружаются при переходах между разделами, что может привести к некорректной работе кнопок «Назад» и «Вперёд» в браузере. Для решения этой проблемы необходимо использовать исторический API браузера (History API) и соответствующие маршрутизаторы.
SPA перекладывает часть вычислений на браузер пользователя, который должен обрабатывать большой объём JavaScript-кода. На слабых устройствах (мобильных телефонах, старых ПК) это может привести к медленной производительности и зависаниям.
В традиционных многостраничных приложениях браузер кэширует статические ресурсы (HTML, CSS, JS), что снижает нагрузку на сервер. В SPA динамическая загрузка данных через API может привести к проблемам с кэшированием, если не реализовать это правильно.
В SPA сложнее поддерживать устаревшие браузеры или устройства с низкой производительностью. Если JavaScript работает некорректно, приложение может полностью выйти из строя.
SPA обычно активно взаимодействуют с сервером через API (например, REST или GraphQL). Если API недоступно или работает с ошибками, приложение теряет часть функционала или становится бесполезным. Необходимо внедрять обработку ошибок и механизмы кэширования данных на клиенте.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2❤1
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤔1
Это структуры или модули в программном обеспечении, которые сильно зависят друг от друга. Высокое сцепление означает, что изменение в одном модуле требует изменений в связанных с ним модулях, что делает систему менее гибкой, сложной для сопровождения и расширения.
Это мера степени зависимости одного модуля или компонента системы от другого. Оно описывает, насколько сильно модули связаны между собой и насколько один модуль знает о деталях работы другого.
Модули независимы друг от друга и взаимодействуют через чётко определённые интерфейсы.
Модули тесно связаны и сильно зависят друг от друга, что делает их взаимозависимыми.
Изменение в одном модуле требует изменения в других модулях.
Один модуль напрямую использует внутренние детали реализации другого модуля.
Из-за сильных зависимостей сложно тестировать модули изолированно.
Внесение изменений становится дорогостоящим и трудоёмким.
При отсутствии чётких интерфейсов часто приходится дублировать код в нескольких местах.
При изменении одного компонента другие компоненты, которые зависят от него, также должны быть изменены или протестированы. Например, если модуль
A напрямую вызывает функции из модуля B и структура модуля B меняется, то модуль A сломается.Высокое сцепление затрудняет рефакторинг и добавление новых функций, так как изменения могут привести к каскадным ошибкам в связанных модулях.
Невозможно протестировать отдельные модули из-за их зависимости от других частей системы. Это приводит к сложным и ненадёжным тестам.
Системы с высоким сцеплением более подвержены ошибкам из-за множества зависимостей. Изменение одного модуля может вызвать неожиданные проблемы в другом.
Система с высоким сцеплением хуже адаптируется к изменяющимся требованиям и сложнее масштабируется, так как изменения требуют больше времени и ресурсов.
Если один класс напрямую создаёт экземпляры других классов или вызывает их методы, это ведёт к высокому сцеплению. Например, если класс
OrderProcessor напрямую вызывает методы DatabaseManager и PaymentGateway, то изменения в их логике повлияют на OrderProcessor.Если модули взаимодействуют напрямую, а не через интерфейсы или абстрактные классы, это приводит к жёсткой привязке к конкретной реализации.
Если несколько модулей обращаются к одним и тем же глобальным данным, это создаёт сильную зависимость между ними.
Внедряйте интерфейсы или абстрактные классы вместо конкретных реализаций, чтобы модули могли взаимодействовать через них.
Внедрение зависимостей позволяет передавать зависимости в модуль извне, что уменьшает их прямую связь.
Разделите систему на логические слои (например, слой представления, бизнес-логики и данных), чтобы минимизировать связи между ними.
Паттерны, такие как Adapter, Facade, Mediator и Observer, помогают уменьшить прямую зависимость между компонентами.
Каждый модуль должен отвечать только за одну задачу. Это делает их более независимыми.
Создавайте модули так, чтобы их можно было тестировать изолированно, не завися от других компонентов системы.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
Это два разных подхода к хранению и обработке данных в программировании. Каждый из них имеет свои плюсы и минусы в зависимости от задачи, контекста и используемого языка программирования.
Это значения или структуры данных, которые могут быть изменены после их создания. Например, массивы, списки и словари в Python или объекты в Java.
Это значения или структуры данных, которые не могут быть изменены после их создания. Любое изменение приводит к созданию нового объекта. Примеры: строки (
string) и кортежи в Python, объекты String в Java, или const в некоторых языках программирования.Поскольку изменяемые объекты обновляются "на месте", нет необходимости создавать новые копии объекта, что экономит память.
Изменение значений в уже существующих объектах часто происходит быстрее, чем создание нового объекта, особенно для больших структур данных.
Изменяемые объекты более гибкие и удобные для задач, которые требуют частых модификаций, таких как добавление или удаление элементов.
Код с изменяемыми объектами часто выглядит проще и чище для операций обновления значений.
При передаче изменяемых объектов между функциями или частями программы их изменение в одном месте может непредсказуемо повлиять на другие части кода.
Из-за изменения значений "на месте" сложнее отследить, где именно произошло изменение объекта.
Одновременные изменения одного и того же объекта в разных потоках могут привести к состояниям гонки (race conditions) и другим багам. Это требует дополнительной синхронизации.
Тестировать функции, которые работают с изменяемыми значениями, сложнее, поскольку их поведение может зависеть от текущего состояния объекта.
Неизменяемые значения гарантируют, что данные не изменятся после создания. Это снижает вероятность непредсказуемых ошибок и упрощает отладку.
Неизменяемые объекты безопасны для многопоточного программирования, так как их состояние не может быть изменено после создания. Это устраняет проблемы синхронизации.
Поскольку неизменяемые объекты всегда остаются в одном и том же состоянии, функции, которые их используют, становятся более детерминированными и проще в тестировании.
Благодаря неизменяемости можно сохранять "снимки" состояния программы, что полезно для версирования данных, откатов и реализации undo/redo функциональности.
Неизменяемые объекты могут кэшироваться и повторно использоваться компилятором или средой выполнения, что повышает производительность.
При каждом изменении неизменяемого объекта создаётся новая копия, что может привести к большому расходу памяти, особенно при работе с большими данными.
Создание нового объекта и копирование данных занимает дополнительное время, что может быть медленнее по сравнению с изменяемыми значениями.
Неизменяемые структуры данных плохо подходят для задач, которые требуют частых и мелких модификаций, например, динамических списков или больших матриц.
Код, работающий с неизменяемыми объектами, может выглядеть более громоздким из-за необходимости создания новых копий при каждом изменении.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это характеристика, показывающая, как изменяются ресурсы (время или память), необходимые для выполнения алгоритма, в зависимости от размера входных данных.
• Временная сложность измеряет количество операций (например, O(n), O(log n)).
• Пространственная сложность измеряет объём памяти, необходимый для выполнения алгоритма.
Сложность позволяет сравнивать эффективность алгоритмов.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Это ошибка, возникающая, когда программа исчерпывает доступное пространство стека из-за чрезмерного количества вызовов функций или выделения данных на стеке. Это приводит к сбою программы, так как система не может выделить дополнительную память для новых вызовов.
Это структура данных, работающая по принципу LIFO (*Last In, First Out*, последним пришёл — первым вышел). В контексте программного исполнения стек используется для хранения:
Функций при их вызовах.
И параметров функции.
Программы.
Если функция вызывает саму себя бесконечное количество раз без условия завершения, стек будет наполняться до тех пор, пока не исчерпает выделенную память. Функция рекурсивно вызывает саму себя без выхода.
Даже если рекурсия корректно завершится, но глубина рекурсивных вызовов слишком велика, доступный размер стека может быть исчерпан.
Стек ограничен по размеру, поэтому выделение больших структур или массивов в локальной области функции может быстро исчерпать стек. Пример: создание большого массива как локальной переменной внутри функции.
Две или более функции могут бесконечно вызывать друг друга, что приводит к быстрому переполнению стека.
В большинстве языков программирования возникает ошибка StackOverflowError или подобная. В C/C++ это может привести к сегментационному сбою (*segmentation fault*). В Java, Python и других языках будет выброшено исключение о переполнении стека.
Программа аварийно завершает работу из-за невозможности выделить дополнительное пространство для стека.
В некоторых системах переполнение стека может привести к непредсказуемому поведению программы, включая повреждение данных или утечку памяти.
Убедитесь, что рекурсивные функции имеют условие завершения (базовый случай). Для глубокой рекурсии можно использовать хвостовую рекурсию, которая оптимизируется компилятором в некоторых языках.
Если возможно, заменяйте рекурсивные вызовы итеративными циклами, чтобы избежать глубокого стека вызовов.
Для больших структур данных используйте кучу (heap) вместо стека для выделения памяти, так как она имеет больший объём доступного пространства.
В некоторых языках можно увеличить размер стека через настройки среды выполнения или компилятора. Например: В C/C++ можно задать размер стека с помощью опций компиляции. В Java размер стека можно увеличить с помощью параметра
-Xss.Используйте анализаторы статического кода и профилировщики, чтобы найти функции, вызывающие избыточную глубину стека.
Старайтесь избегать больших локальных переменных или структур, выделяя их в куче.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
1. 1xx (Информационные): уведомления о процессе запроса (например, 100 Continue).
2. 2xx (Успех): успешное выполнение запроса (например, 200 OK, 201 Created).
3. 3xx (Перенаправления): требуется дополнительное действие клиента (например, 301 Moved Permanently, 302 Found).
4. 4xx (Ошибки клиента): проблемы с запросом (например, 400 Bad Request, 401 Unauthorized, 404 Not Found).
5. 5xx (Ошибки сервера): проблемы на стороне сервера (например, 500 Internal Server Error, 503 Service Unavailable).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Это два разных, но связанных понятия, которые часто используются в контексте выполнения задач в программировании. Хотя они кажутся схожими, их цели, принципы и области применения различаются.
Это одновременное выполнение нескольких задач или частей задачи на нескольких процессорных ядрах или машинах. Он предполагает физический параллельный запуск операций. Например, выполнение двух разных операций одновременно на двух ядрах процессора. Параллелизм направлен на повышение производительности программы за счёт разделения работы.
Это техника, при которой одна программа делится на несколько потоков, выполняющихся псевдопараллельно (по очереди или параллельно, в зависимости от количества ядер процессора). Потоки работают в рамках одного процесса и делят общую память. Многопоточность позволяет эффективно использовать ресурсы процессора при переключении между задачами. Она часто используется для работы с I/O-операциями, где потоки могут ожидать данных и не блокировать выполнение программы.
Параллелизм использует физическую многозадачность, когда задачи выполняются одновременно на разных ядрах процессора или разных машинах. Многопоточность может использовать псевдопараллельность: потоки переключаются на одном ядре процессора (с использованием планировщика ОС) или действительно работают параллельно на нескольких ядрах.
В параллелизме ресурсы распределяются между несколькими задачами (например, вычисления на CPU). В многопоточности потоки могут совместно использовать общую память и другие ресурсы одного процесса.
Параллелизм: задачи, которые можно разделить на независимые подзадачи, работающие одновременно (например, обработка данных в больших системах или рендеринг видео). Многопоточность: задачи, которые включают ожидание ввода/вывода или требуют выполнения нескольких задач внутри одного приложения (например, интерфейс пользователя и фоновый процесс).
Параллелизм: Видеокодирование, где каждый кадр обрабатывается на разных ядрах процессора одновременно. Многопоточность: Веб-сервер, который обрабатывает несколько запросов пользователей одновременно, используя потоки.
Многопоточность может использоваться для достижения параллелизма при наличии нескольких процессорных ядер. Например: Если у программы несколько потоков и у компьютера два ядра, то операционная система может распределить потоки на разные ядра, что создаст параллельное выполнение. Если же у процессора одно ядро, потоки будут псевдопараллельными, так как процессор будет быстро переключаться между ними.
Несколько поваров готовят разные блюда на отдельных кухонных станциях одновременно. Распределённые вычисления: Большая задача разбивается и выполняется на нескольких серверах.
Один человек (процессор) делает несколько задач поочерёдно: ставит суп вариться, затем режет салат, затем проверяет суп. Псевдопараллельность: Даже если задачи не выполняются одновременно, переключение между ними создаёт иллюзию многозадачности.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👾3
1. GET: запрашивает данные с сервера, без изменения.
2. POST: отправляет данные на сервер для создания ресурса.
3. PUT: обновляет или заменяет данные, может создать новый ресурс.
4. DELETE: удаляет ресурс на сервере.
5. PATCH: частично обновляет ресурс.
6. OPTIONS: возвращает информацию о доступных методах для ресурса.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Значение
null считается ошибкой в программировании, потому что оно часто приводит к непредсказуемым ошибкам, сложным для отладки и устранения. Его использование стало настолько проблематичным, что создатель null — Тони Хоар — назвал его "миллиардной ошибкой" из-за огромного количества проблем и уязвимостей, которые оно вызвало.null используется для обозначения "отсутствия значения", но сама по себе идея "пустоты" вводит двусмысленность в код. Например: "Отсутствует ли значение из-за ошибки, или это нормальное поведение?".Попытка вызвать метод или обратиться к полю объекта, который равен
null, приводит к исключению, например, NullPointerException в Java или TypeError в JavaScript. Эти ошибки сложно предсказать на этапе компиляции и они часто приводят к сбоям программы.String name = null;
int length = name.length(); // NullPointerException
null-ошибки часто проявляются в непредсказуемых местах, что делает их сложными для поиска. Программисты тратят много времени на отладку, чтобы понять, откуда возникло null.Каждый раз, когда переменная может быть
null, программист должен явно проверять её наличие перед использованием. Это делает код многословным и менее читаемым. Плохой код if (user != null && user.getAddress() != null) {
String city = user.getAddress().getCity();
}null не соответствует типу, который описывает переменную. Например, если переменная типа String равна null, то фактически в ней нет строки. Это нарушает типобезопасность и вносит неявное поведение в программу.Часто
null используется для обозначения нескольких состояний одновременно: "значение не инициализировано", "значение отсутствует" или "ошибка при получении данных". Это приводит к логическим ошибкам и двусмысленности.Если несколько потоков работают с общим объектом, и один из них устанавливает его в
null, то другие потоки могут столкнуться с ошибками времени выполнения.Из-за потенциального наличия
null разработчики должны добавлять дополнительные проверки, чтобы избежать ошибок. Это делает код менее чистым и увеличивает вероятность пропустить проверку. null
В Java, Kotlin и других языках существуют Optional (или аналоги), которые явно представляют "наличие или отсутствие значения". Это заставляет разработчика явно обрабатывать "пустое" состояние.
Optional<String> name = Optional.ofNullable(user.getName());
name.ifPresent(System.out::println);
В функциональных языках (Haskell, Scala) используются монады Maybe/Option, которые безопасно обрабатывают отсутствие значения.
Вместо использования
null можно задавать значения по умолчанию, например, пустую строку "" или 0 для чисел.Это шаблон проектирования, где вместо
null используется специальный "пустой объект", который имеет предсказуемое поведение. Например, вместо null можно вернуть объект с "пустыми" методами.class NullUser extends User {
@Override
public String getName() {
return "Unknown User";
}
}ength =
В Kotlin и Swift типы разделяются на nullable и non-nullable. Компилятор заставляет разработчика обрабатывать потенциальный
null.val name: String? = null // nullable
println(name?.length) // Безопасный вызов
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это платформа для контейнеризации, позволяющая запускать приложения в изолированных контейнерах. Контейнеры включают всё необходимое для работы приложения: код, библиотеки и зависимости. Это обеспечивает лёгкость развертывания, масштабируемость и консистентность среды выполнения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Это два разных подхода к обмену сообщениями между компонентами распределённых систем. Они различаются архитектурными принципами, целями и способами взаимодействия между отправителями и получателями.
Это коммуникационная модель, при которой один компонент системы отправляет запрос другому компоненту и ожидает ответа.
Обычно предполагает синхронное взаимодействие, где отправитель блокируется до получения ответа.
Один запрос адресован одному конкретному получателю.
Для обработки ответа отправитель использует корреляционный идентификатор, чтобы сопоставить его с исходным запросом.
Это асинхронная модель взаимодействия, в которой один компонент публикует сообщения, а другие компоненты, подписанные на эти сообщения, получают их.
Публикация сообщений и их получение подписчиками происходят независимо.
Сообщение может быть отправлено нескольким подписчикам одновременно.
Публикация осуществляется в рамках определённых тем или каналов, а подписчики получают только интересующие их сообщения.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Различия в обработке родных (first-party) и сторонних (third-party) куки обусловлены соображениями безопасности, конфиденциальности и контекста использования. Эти различия возникают из-за того, что родные куки создаются и используются непосредственно сайтом, который пользователь посещает, в то время как сторонние куки обычно принадлежат и используются другими доменами (например, рекламными сетями), которые интегрированы в сайт.
Родные куки создаются доменом, который пользователь непосредственно посещает. Они используются для хранения информации, связанной с сессией пользователя или предпочтениями.
Авторизация пользователя.
Сохранение настроек сайта, таких как язык или тема оформления.
Хранение данных о товарах в корзине интернет-магазина.
Они считаются менее рискованными с точки зрения безопасности и конфиденциальности. Доступ к этим кукам имеет только сайт, который их установил. По умолчанию браузеры предоставляют полный доступ к родным кукам.
Сторонние куки устанавливаются другим доменом, отличным от того, который пользователь посещает. Обычно это происходит через интеграцию внешних сервисов, таких как рекламные сети, аналитические платформы или социальные виджеты.
Таргетированная реклама.
Аналитика кросс-доменного поведения пользователей.
Ретаргетинг.
Считаются более уязвимыми с точки зрения конфиденциальности, так как позволяют сторонним организациям отслеживать поведение пользователей на множестве сайтов.
Современные браузеры ограничивают или блокируют доступ к сторонним кукам:
Safari (Intelligent Tracking Prevention) и Firefox (Enhanced Tracking Protection) автоматически блокируют сторонние куки.
Google Chrome также планирует отказаться от сторонних куков, заменяя их на Privacy Sandbox.
a) Защита конфиденциальности
Сторонние куки используются для отслеживания пользователей на разных сайтах, что может нарушать их приватность. Регуляции, такие как GDPR и CCPA, требуют строгого контроля над сбором персональных данных.
b) Минимизация рисков безопасности
Сторонние куки могут быть использованы злоумышленниками для атак (например, CSRF). Ограничение доступа к таким кукам снижает эти риски.
c) Пользовательский контроль
Современные браузеры предоставляют пользователям больше контроля над тем, какие куки они принимают. Ограничение сторонних куков снижает вероятность нежелательной активности со стороны третьих лиц.
d) Регуляторные требования:
Правовые нормы требуют информировать пользователей о сборе данных и получать их согласие. Разные подходы к обработке куков помогают соблюдать эти требования.
Родные куки доступны только для домена, который их установил, и передаются только в рамках запросов к этому домену. Сторонние куки могут использоваться только если браузер явно разрешает это, либо если сервер настроен для совместимости с современными политиками (например,
SameSite=None; Secure).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
2. LEFT JOIN: возвращает все строки из левой таблицы и совпадающие строки из правой.
3. RIGHT JOIN: возвращает все строки из правой таблицы и совпадающие строки из левой.
4. FULL OUTER JOIN: объединяет все строки из обеих таблиц, заполняя несоответствия NULL.
5. CROSS JOIN: возвращает декартово произведение строк двух таблиц.
6. SELF JOIN: соединяет таблицу саму с собой.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Событийно-ориентированная архитектура (event-driven architecture, EDA) улучшает масштабируемость за счет асинхронного и независимого взаимодействия между компонентами системы. Основной принцип EDA — использование событий в качестве триггеров для выполнения задач, что устраняет прямую зависимость между инициатором события и его обработчиками. Это позволяет системе более гибко реагировать на рост нагрузки и распределять её между различными частями системы.
В событийно-ориентированной архитектуре компоненты взаимодействуют через обмен сообщениями (событиями) без необходимости ожидания ответа. Это снижает блокировки, позволяет эффективно использовать ресурсы и масштабировать каждый компонент независимо. Если пользователь инициирует действие, например, загрузку файла, событие записывается в очередь. Обработка события выполняется в отдельном потоке или сервисе, что позволяет обрабатывать множество запросов одновременно.
EDA строится на слабой связанности компонентов: каждый сервис отвечает только за обработку определённых событий. Компоненты могут масштабироваться автономно, без влияния на другие части системы. Если в системе интернет-магазина одновременно увеличивается количество заказов и запросов аналитики, можно масштабировать сервис обработки заказов независимо от аналитического сервиса.
События отправляются в очереди сообщений или брокеры (Kafka, RabbitMQ, AWS SNS/SQS), которые выступают посредниками между производителями и потребителями событий. Это позволяет сглаживать пики нагрузки и временно сохранять события до их обработки, что улучшает масштабируемость. Если нагрузка на обработку увеличивается, можно просто добавить больше обработчиков событий, не изменяя остальную часть системы.
Сервисы, реагирующие на события, могут быть легко клонированы (горизонтально масштабированы), чтобы увеличить пропускную способность системы. Видеохостинг может масштабировать сервисы обработки видео, чтобы справляться с увеличением количества загрузок.
В EDA события — это четко определённые сообщения, которые передают состояние системы. Это упрощает добавление новых компонентов без изменения существующих. Новые компоненты могут подписываться на события и обрабатывать их, не нарушая текущую логику системы. Аналитическая система может быть подключена для обработки событий о действиях пользователей без необходимости вмешательства в код основной системы.
При внезапных всплесках трафика (например, во время распродаж) EDA позволяет накапливать события в очередях до тех пор, пока они не будут обработаны. Это снижает риск отказа системы под нагрузкой. Если сервис обработки платежей перегружен, события транзакций могут временно оставаться в очереди, чтобы быть обработанными позже.
EDA хорошо подходит для распределённых систем, так как её архитектура учитывает разнородность компонентов. Каждый компонент работает автономно, что облегчает их масштабирование и развёртывание в различных средах.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
2. Парсинг HTML: полученный код анализируется, создаётся DOM-дерево, которое описывает структуру страницы.
3. Загрузка ресурсов: CSS, JavaScript, изображения загружаются асинхронно. CSS формирует CSSOM (модель стилей), объединяясь с DOM.
4. Рендеринг: DOM и CSSOM объединяются в Render Tree, и браузер отображает страницу, выполняя раскладку и отрисовку.
5. JavaScript: выполняется на этапе рендеринга или после загрузки страницы, обновляя DOM.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2