Это два ключевых свойства модульной архитектуры программного обеспечения, которые помогают оценить качество кода и архитектурных решений.
Описывает степень зависимости одного модуля от других. Высокое сцепление означает, что модули сильно зависят друг от друга, что затрудняет их изменение, тестирование и повторное использование, так как изменения в одном модуле требуют изменений в зависимых модулях. Идеально стремиться к слабому сцеплению, чтобы модули были максимально независимыми. Это позволяет изменять или заменять один модуль без необходимости изменения других.
Описывает, насколько тесно связанные и объединённые общей задачей элементы внутри одного модуля. Высокая связанность означает, что все функции и данные модуля логически связаны и выполняют одну задачу. Это упрощает понимание кода и делает модуль более автономным.Высокая связанность считается хорошей практикой, так как модуль с высокой связанностью проще в обслуживании, его легче изменить или заменить.
Представьте модуль, который управляет пользователями: если в модуле только функции для работы с пользователями (например, добавление и удаление), он обладает высокой связанностью, так как его функции направлены на одну задачу. Если модуль при этом минимально зависит от других частей системы, это говорит о слабом сцеплении.
Это желательные качества. Они помогают создать более гибкую и поддерживаемую систему.
Лучше, когда оно слабое, так как снижает зависимость между модулями.
Лучше, когда она высокая, так как все функции модуля работают на достижение одной цели.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Логика предметной области в хранимых процедурах — это подход, при котором бизнес-логика (правила и операции, связанные с управлением данными) реализуется непосредственно на уровне базы данных с использованием хранимых процедур. Этот подход имеет свои плюсы и минусы, которые важно учитывать при проектировании архитектуры приложения.
Хранимые процедуры выполняются на уровне базы данных, что позволяет избежать сетевых задержек при передаче данных между приложением и базой. Процедуры могут работать с данными напрямую, избегая лишних перегрузок и ускоряя обработку сложных запросов.
Современные СУБД могут кэшировать планы выполнения хранимых процедур, что снижает накладные расходы на компиляцию и оптимизацию запросов. Благодаря кэшированию повышается производительность повторных вызовов процедур, особенно в случаях обработки больших объёмов данных.
Хранимые процедуры могут содержать бизнес-логику, обеспечивая консистентность её выполнения независимо от источника вызова. Это удобно при использовании единой базы данных для нескольких приложений. Такой подход уменьшает дублирование кода, так как логика определена в одном месте — в базе данных.
Хранимые процедуры могут содержать сложные транзакции, обеспечивая целостность данных и управление транзакциями на уровне базы. Это может быть удобнее, чем реализация транзакций на уровне приложения, особенно для сложных многошаговых операций.
Логика, встроенная в хранимые процедуры, позволяет лучше контролировать доступ к данным. Разработчики могут ограничить прямой доступ к таблицам, предоставляя доступ к данным только через процедуры. Это повышает безопасность, так как доступ к данным осуществляется через контролируемые процедуры, где можно задать права доступа.
Реализация бизнес-логики в хранимых процедурах может усложнить кодовую базу, так как SQL и процедурные языки базы данных, такие как PL/pgSQL или T-SQL, могут быть менее выразительными и сложными в поддержке. Такой код часто труднее тестировать, отлаживать и версионировать, чем код на языке высокого уровня, таком как Java или Python.
Бизнес-логика, встроенная в хранимые процедуры, делает приложение сильно зависимым от конкретной СУБД, что затрудняет переносимость. Если требуется смена СУБД, перенос логики может оказаться сложным и трудозатратным. Различия в реализации хранимых процедур для разных СУБД также могут затруднять кросс-платформенное развитие.
Базы данных, хотя и мощные, могут столкнуться с ограничениями производительности при высокой нагрузке. В случае высокой нагрузки сервер приложений может масштабироваться горизонтально (добавлением серверов), а сервер базы данных — нет. Вложение большого объёма бизнес-логики в базу данных может привести к её перегрузке, ограничивая гибкость и масштабируемость приложения.
Изменение хранимых процедур часто требует обновлений на уровне базы данных, что может быть сложным и требовать простоя. В отличие от кода приложения, обновление хранимых процедур затрагивает работу всей базы. Этот фактор особенно неудобен в условиях Agile-разработки, где быстрое внесение изменений является важной частью процесса.
Тестирование и автоматизация развертывания хранимых процедур сложнее, чем тестирование и развертывание бизнес-логики на стороне приложения. CI/CD процессы для хранимых процедур менее развиты и часто требуют дополнительных инструментов и сложной настройки, что добавляет накладные расходы на разработку.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Оператор
goto считается "злом" в программировании, потому что его использование может значительно усложнить структуру и логику программы, делая код трудным для понимания, сопровождения и отладки. goto нарушает последовательный поток выполнения программы, произвольно перемещая управление в другое место кода. Это может привести к хаотичной структуре, где трудно проследить, как данные перемещаются и как выполняется логика. Переходы с помощью goto делают код нечитаемым, поскольку программисту приходится "прыгать" по коду, чтобы понять, что происходит. В больших программах это приводит к запутанной логике и фрагментированности.В коде с частым использованием
goto может появиться так называемый "спагетти-код", где переплетённые переходы между различными частями кода делают его сложным для понимания. В "спагетти-коде" контроль над выполнением разбросан по многим местам, что приводит к ошибкам, особенно при модификации программы.Логика с использованием
goto труднее отлаживать, поскольку управление переходит в произвольные места. Это осложняет трассировку и отслеживание исполнения программы, делая выявление ошибок более трудоёмким. Внесение изменений также становится рискованным: даже малейшее изменение может привести к неожиданным ошибкам из-за непредсказуемого изменения порядка выполнения.Структурное программирование основывается на трёх базовых конструкциях: последовательности, ветвления и цикла.
goto же позволяет "вырваться" за пределы этих конструкций, что разрушает структурированность программы. Программы с goto теряют понятную иерархию и становятся неуправляемыми, так как переходы могут происходить в любой момент, минуя условные конструкции, циклы и функции.Код с
goto часто сложно разделить на отдельные модули или функции, поскольку переходы могут приводить к произвольным точкам в коде, включая те, которые выходят за пределы функций. Это также усложняет повторное использование кода, так как фрагменты, использующие goto, могут зависеть от конкретного места выполнения.В системном программировании или драйверах, где требуется максимальная производительность и минимальные накладные расходы.
В некоторых языках, таких как C,
goto может использоваться для выхода из нескольких уровней вложенных циклов, что иногда более эффективно и проще, чем добавление флагов или вспомогательных функций.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍2🎉1
Термин «Ошибка на миллиард долларов» в отношении
NULL был введён известным учёным и программистом Тони Хоаром, который в 1965 году изобрёл NULL-ссылки. Спустя годы он назвал это решение "ошибкой на миллиард долларов", поскольку использование NULL привело ко множеству ошибок и уязвимостей, стоивших компаниям и разработчикам огромных затрат на устранение последствий.NULL часто приводит к ошибкам из-за его некорректной обработки. Если программа ожидает, что переменная содержит значение, а вместо этого встречается NULL, это приводит к сбоям, падениям и исключениям. Популярная ошибка — это NullPointerException, которая происходит, когда программа пытается использовать NULL как объект или ссылку. Такие ошибки трудно обнаружить, так как их проявление зависит от условий выполнения программы и использования данных, что делает их сложными для отладки и тестирования.Использование
NULL обязывает программистов проверять каждую переменную на предмет NULL, чтобы избежать сбоев. Это усложняет код, делает его менее читаемым и подверженным ошибкам, особенно когда проверки на NULL игнорируются или забываются. Чем больше кода, связанного с обработкой NULL, тем выше вероятность появления багов, особенно если пропущены проверки.NULL разрушает понятие инкапсуляции, так как от программиста требуется знать, может ли переменная быть NULL или нет. Часто интерфейсы неявно предполагают, что некоторые данные могут быть NULL, что может вводить разработчика в заблуждение. В дополнение, использование NULL неявно снижает выразительность кода, так как вместо определённого значения "ничего" (например, "не определено" или "неизвестно") часто используется просто NULL, что ухудшает понимание кода.Ошибки, связанные с
NULL, могут привести не только к сбоям, но и к уязвимостям, открывающим путь для атак. Например, злоумышленники могут использовать уязвимости, вызванные неправильной обработкой NULL, чтобы вызвать некорректное поведение системы или обойти ограничения доступа.В языках, таких как Java, Kotlin, C# и других, существуют типы
Optional (или Option в функциональных языках), которые обязывают явно указывать, что переменная может не содержать значения. Optional заставляет программиста явно обрабатывать случаи отсутствия значения, что уменьшает вероятность случайного использования NULL и упрощает работу с отсутствием данных.Некоторые языки, например Kotlin и Swift, поддерживают строгую систему типов, которая позволяет объявлять
nullable и non-nullable переменные. Если переменная объявлена как non-nullable, компилятор не позволит присвоить ей NULL или использовать её как NULL. Этот подход повышает безопасность кода на этапе компиляции, предотвращая распространённые ошибки с NULL-ссылками.Современные инструменты статического анализа (такие как SonarQube, ReSharper, FindBugs) могут автоматически обнаруживать места потенциального использования
NULL и предупреждать разработчиков. Эти инструменты помогают выявить случаи, когда переменная может оказаться NULL, и помогают предотвратить ошибки до выполнения программы.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Плохая организация кода проявляется в признаках, которые затрудняют его понимание, сопровождение и расширение. Такие проблемы могут быть следствием недостатков в архитектуре, неверного структурирования модулей, низкой читаемости и слабой гибкости.
Повторение одних и тех же блоков кода в нескольких местах. Дублированный код усложняет сопровождение, поскольку изменения нужно вносить в нескольких местах, что повышает вероятность ошибок. Выявлять общие фрагменты кода и выделять их в отдельные функции или методы. Следовать принципу DRY (Don't Repeat Yourself).
Модуль содержит функции, которые не связаны общей задачей, или класс имеет свойства и методы, не объединённые одной логикой. Пониженная связанность затрудняет понимание того, за что отвечает модуль или класс, увеличивает вероятность ошибок. Стремиться к высокой связанности, чтобы модули выполняли одну чёткую задачу. Следовать принципу Single Responsibility (единственная ответственность).
Модули или классы сильно зависят друг от друга и для работы требуют конкретной реализации других частей системы. Высокое сцепление снижает гибкость и увеличивает время на изменения. Модификация одной части кода требует модификации множества зависимых компонентов. Стремиться к слабому сцеплению, разрабатывая независимые модули с понятными интерфейсами. Использовать инверсию зависимостей и интерфейсы.
Сложные алгоритмы или структуры, которые можно упростить без потери функциональности. Усложнённый код труднее понимать, тестировать и отлаживать. Большая вероятность ошибок из-за запутанной логики. Применять KISS (Keep It Simple, Stupid) и YAGNI (You Aren't Gonna Need It) для минимизации сложности и реализации только необходимых функций.
Функции, занимающие несколько экранов кода, и методы, которые выполняют несколько задач одновременно. Длинный код труден для понимания, тестирования и повторного использования. Длинные функции часто имеют слишком много ответственности. Разделять функции на более короткие, каждая из которых выполняет только одну задачу. Стремиться к следованию принципу SRP (Single Responsibility Principle).
Непонятные или непоследовательные имена, которые не отражают назначение переменной, функции или класса. Повышает сложность чтения и понимания кода для других разработчиков, увеличивает вероятность ошибок. Использовать осмысленные, выразительные имена, которые чётко отражают их цель. Следовать принятым стандартам именования и писать самодокументируемый код.
Подключение библиотек или модулей, которые не используются или используются минимально. Увеличивает сложность кода, усложняет деплой и повышает риск конфликта версий. Регулярно проверять зависимости и удалять неиспользуемые, использовать только необходимые библиотеки и модули.
Модули и классы не соответствуют базовым принципам SOLID (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion). Проблемы с расширяемостью и поддержкой. Изменения могут привести к ошибкам в коде и сильному сцеплению. Проверять архитектуру на соответствие принципам SOLID и вносить улучшения, если структура нарушена.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
Полезен анализ планов выполнения (
EXPLAIN), системные логи запросов и внешние инструменты мониторинга вроде Percona или Datadog. В PostgreSQL используйте pg_stat_statements для анализа запросов по времени выполненияSELECT query, total_time FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;
В MySQL включите
slow_query_log для записи медленных запросовSET GLOBAL slow_query_log = 1; SET GLOBAL long_query_time = 1;
В SQL Server используйте
sys.dm_exec_query_statsSELECT TOP 10 total_elapsed_time / execution_count AS AvgTime, text FROM sys.dm_exec_query_stats CROSS APPLY sys.dm_exec_sql_text(sql_handle) ORDER BY AvgTime DESC;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤯2
Разработчики могут не любить Java по нескольким причинам, связанным с особенностями языка, его экосистемы и исторической репутацией.
Java часто критикуют за необходимость писать много шаблонного (boilerplate) кода. Например, для выполнения простых операций, таких как создание POJO-классов (Plain Old Java Object), разработчики вынуждены прописывать геттеры, сеттеры, конструкторы, методы
equals и hashCode. Несмотря на наличие библиотек, таких как Lombok, для уменьшения шаблонности, это остается одной из претензий к языку.Исторически Java обновлялась медленно, что вызывало недовольство. До перехода на модель выпуска версий каждые шесть месяцев (с Java 9), промежутки между релизами были слишком большими. Это приводило к отставанию языка от более динамично развивающихся конкурентов, таких как Kotlin, Scala или Python.
Некоторые считают Java "устаревшим" языком из-за особенностей, таких как ручное управление многопоточностью (до появления улучшенных инструментов в Java 8 и последующих версиях) или отсутствие "современного" синтаксиса (например, до появления
var).Раньше Java часто ассоциировалась с медленной работой из-за интерпретируемой природы байт-кода и большого объема памяти, необходимого для запуска JVM. Хотя современные реализации JVM (HotSpot, GraalVM) сделали Java очень быстрой, этот стереотип все еще живет.
В крупных проектах на Java все еще можно столкнуться с использованием старых библиотек и инструментов, таких как XML-конфигурации для Spring. Такие проекты требуют больше усилий для модернизации и поддержки.
Java — строго типизированный язык. Это обеспечивает надежность и удобство поддержки, но снижает гибкость при разработке прототипов или экспериментировании. Это особенно заметно в сравнении с языками, такими как Python или JavaScript.
Kotlin, развиваемый JetBrains, стал официальным языком разработки для Android в 2017 году. Он предлагает более лаконичный синтаксис, мощные функции работы с null-значениями, и в целом воспринимается как более "современный" язык.
Java обладает огромной экосистемой, которая может быть одновременно преимуществом и недостатком. Иногда требуется глубокое понимание JVM, инструментов сборки (Maven, Gradle), и других особенностей.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Это технология, позволяющая приложениям вызывать функции или процедуры, которые выполняются на удалённом сервере, как если бы они были локальными. Несмотря на удобство, такая модель имеет ряд подводных камней, которые необходимо учитывать при проектировании и разработке распределённых систем.
Удалённые вызовы маскируют тот факт, что операция выполняется через сеть. Это может создать ложное чувство локальности у разработчиков, которые не учитывают:
Сетевую задержку: вызовы занимают больше времени, чем локальные операции, особенно при медленных сетях. Сетевые сбои: соединение может быть потеряно, что приведёт к ошибкам выполнения или длительным тайм-аутам. Изменение задержки: время выполнения одного и того же вызова может существенно варьироваться в зависимости от сетевых условий.
Обработка ошибок в распределённых системах сложнее, чем при локальных вызовах:
Необходимо обрабатывать такие ошибки, как потеря соединения, тайм-ауты, отказ сервера. В некоторых случаях может возникнуть "проблема повторного вызова" (например, запрос был выполнен, но подтверждение потерялось), что приводит к возможной идемпотентности операций.
Для передачи данных через сеть они должны быть преобразованы в сериализованный формат. Это может:
Увеличивать задержки из-за времени, необходимого на преобразование. Создавать проблемы совместимости, если клиент и сервер используют разные версии протокола. Усложнять отладку и диагностику ошибок в данных.
Взаимодействие между распределёнными компонентами приводит к необходимости поддерживать согласованность данных: Проблема согласованности особенно актуальна при частичных отказах системы. Может потребоваться использование распределённых транзакций, что усложняет архитектуру.
Удалённые вызовы подвержены угрозам: Необходимо обеспечивать шифрование данных, чтобы избежать утечек. Аутентификация и авторизация играют ключевую роль в защите системы. Возможны атаки на уровень сети или использование слабостей в протоколах передачи данных.
При большом числе клиентов сервер может стать узким местом: Нагрузка на сервер может привести к деградации производительности. Требуется правильная стратегия масштабирования и балансировки нагрузки, например, использование нескольких серверов или очередей сообщений.
Различные протоколы (например, HTTP, gRPC, Thrift) обладают своими особенностями: Протокол может накладывать ограничения на производительность и возможности. Ошибки конфигурации или несоответствие версий могут вызвать проблемы.
Микросервисные архитектуры. Взаимодействие клиент-сервер (например, мобильное приложение и API). Системы с тяжёлой серверной логикой.
Чётко проектировать архитектуру, учитывая особенности сети. Использовать идемпотентные операции. Обеспечивать надёжные стратегии обработки ошибок. Применять мониторинг и трассировку (например, OpenTelemetry) для отслеживания поведения системы.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Принципы разделения ответственности (Separation of Concerns, SoC) предполагают разделение логики программы на отдельные части, каждая из которых выполняет строго определённую функцию. Это позволяет сделать код более структурированным, гибким и легче сопровождаемым. Популярные паттерны проектирования, основанные на разделении ответственности, включают MVC, MVP, MVVM и другие. Они применяются в разработке приложений для чёткого разграничения пользовательского интерфейса, бизнес-логики и работы с данными.
Хранит данные и логику их обработки. Отвечает за взаимодействие с базой данных или другими источниками данных. Уведомляет представление об изменениях данных.
Отображает данные пользователю. Реагирует на обновления данных от модели. Не содержит логики обработки данных.
Обрабатывает пользовательский ввод (например, нажатия кнопок, ввод текста). Вызывает соответствующие методы модели и обновляет представление.
Работает с данными и бизнес-логикой.
Интерфейс пользователя. Не содержит логики, только вызывает методы презентера.
Посредник между моделью и представлением. Получает данные из модели и передаёт их в представление. Не знает деталей реализации интерфейса (только абстракция).
Плюсы и минусы
Управляет данными и бизнес-логикой.
Отображает данные и предоставляет интерфейс для взаимодействия.
Посредник между моделью и представлением. Содержит логику преобразования данных для представления. Часто использует привязку данных (data binding), что позволяет автоматически обновлять UI при изменении данных.
Плюсы и минусы
Централизованное состояние приложения.
Компоненты, которые отображают состояние.
Описывают, какие изменения должны произойти в состоянии.
Функции, описывающие, как изменяется состояние на основе действий.
Плюсы и минусы
можно тестировать компоненты независимо друг от друга.
код проще понять и сопровождать.
компоненты можно использовать в других частях приложения.
команда может работать над разными частями параллельно.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это термин, которым называют старый код или программное обеспечение, созданное много лет назад, но до сих пор используемое. Важно понимать, что "легаси" не обязательно означает "плохой". Этот код может быть ценным и выполнять критически важные задачи, но у него есть свои особенности и проблемы, которые делают работу с ним сложной.
Программы, написанные 5, 10 или даже 20 лет назад, продолжают работать, хотя технологии уже изменились.
Разработчики, написавшие код, могли уйти из компании, не оставив подробных объяснений.
Код, который был написан для одних задач, со временем начинает использоваться для других, часто без переработки.
Код создавался на старых версиях языков программирования, библиотек или платформ, которые сегодня уже не поддерживаются.
Код может быть сложно понять, особенно если он написан без соблюдения современных стандартов или правил.
Старый код часто создавался без автоматизированных тестов, что усложняет внесение изменений.
Код может использовать библиотеки или платформы, которые больше не обновляются или не поддерживаются.
Даже небольшие правки могут вызвать неожиданные ошибки, поскольку никто не знает всех последствий изменений.
Если код выполняет свою задачу, компании часто решают оставить его как есть.
Легаси-код может управлять банковскими системами, производственными линиями или другими системами, от которых зависит бизнес.
Полная переработка кода может занять годы и потребовать огромных ресурсов.
Исправлять ошибки и улучшать работу системы по мере необходимости.
Переходить на современные технологии частями, чтобы минимизировать риски.
Создать новую систему, если старая больше не отвечает требованиям, но это требует времени и ресурсов.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3