Сколько раз вы были в ситуации, когда вы хотели добавить новую функцию в свое приложение, но не могли, потому что код был не масштабируемый? Сколько раз вам приходилось переписывать код, чтобы сделать его тестируемым? Сколько раз вам приходилось добавлять больше кода, чтобы сделать его оптимальным для мобильных устройств?
На самом деле, все сводится к принципам дизайна. В этой статье я поделюсь десятью принципами проектирования, которые необходимо знать всем программистам / разработчикам ПО. Эти принципы относятся к тому, как вы разрабатываете дизайн системы, как вы реализуете определенные компоненты и как вы должны писать свой код. Это не то, чем нужно жить. Это просто рекомендации, о которых вы хотите думать, когда разрабатываете или внедряете систему. Другими словами, они сделают вашу жизнь намного проще в будущем, если вы решите следовать им.
Тут есть частичный перевод, потому что порой бывает, что кто то выражает свои мысли, много лучше чем я. И было бы интересно что вы думаете про эти пункты. Есть ли у вас правила, которыми вы пользуетесь при разработке?
1. Разделяй и властвуй
Один из основных принципов в любой ситуации решения проблем, включая проектирование системы, - разделять и властвовать. Это означает разбиение проблемы на более мелкие подзадачи. Идея заключается в том, что эти проблемы трудно решить из-за их сложности. Чтобы упростить задачу, вы можете разделить эти проблемы на более мелкие. Решение этих меньших задач, облегчит решение более крупной проблемы в долгосрочной перспективе.
В разрезе разработки, у вас может быть система, в которой есть подсистемы с разными пакетами, у которых есть классы с разными методами, которые используют некоторые внешние зависимости или некоторые функции. Я только что разбил всю эту систему на подразделы, записав это утверждение. Если бы у указанных подразделов были проблемы, вы бы выяснили, есть ли проблемы с методами, используемыми в классах, затем переходили бы к другим классам и проверяли, были ли они проблемой, затем переходили бы к пакетам, а затем к подсистемам. Думайте об этом как о ситуации с матрешкой.
2. Повышение сплоченности/согласованности
Сплоченность означает объединение вещей, которые имеют смысл, вместе в один пакет. С точки зрения разработки, вы можете согласованно проектировать свои пакеты, модули или классы. Подумайте, например, о математическом пакете в Python. Математический пакет является связным, потому что в нем есть все, что связано с математическими операциями. Вы не найдете в нем ничего не математического.
Сплоченность приводит к организации вашего кода, и это значительно упростит поиск, тем самым упростив систему. Во всем будет больше смысла. Таким образом, вы не будете заходить в пакет словарей в поисках функций, связанных с машинным обучением, или чего-то подобного.
3. Устранять связывание
Проще говоря, связывание происходит, когда пакеты, модули, классы или файлы очень взаимозависимы. Я не уверен насчет вашего проекта, но я знаю, что это не лучшая реализация любой системы. Почему? Если в одном пакете есть какие-то изменения или он сломается, вся система может быть скомпрометирована, потому что некоторые из ее частей зависят от пакета, в котором произошел сбой.
Я знаю, что вначале легче реализовать сильно связанную систему, но будет намного сложнее отлаживать и исправлять, если какой-либо компонент выйдет из строя.
Часто у вас есть системы, которые настолько сильно связаны, что очень трудно определить, где это происходит. У вас может быть пакет, зависящий от другого пакета, который зависит от еще восьми. Вы понимаете, насколько это проблематично? Вы можете оказаться в ситуации, когда вы не знаете, почему один пакет не работает, когда другой, скрытый под четырьмя уровнями связи, может работать неправильно. Надеюсь, вы поняли идею.
Если вы сможете сделать свои компоненты как можно более независимыми, вам будет легче отлаживать их. Это лучший дизайн. Я стараюсь делать свои пакеты практически как отдельный микросервис. То есть всю логику, например, работы с наградами я выношу отдельный модуль. А работу с валютами в другой. И модуль наград может зависеть от модуля валют, потому что награды могут быть из определенной валюты, но в тоже время можно сделать 3й модуль, который объеденит награды и валюты.
4. Увеличьте абстракцию
Что-то более абстрактное - это упрощенная версия чего-то технического. В смысле кодирования нечто более абстрактное является более обобщенным. Позвольте мне привести пример. Это стандартный пример, который разбирается при изучении ООП. Предположим, у вас есть функция, которая принимает в качестве входных данных только треугольник и отображает его на экране. Что бы произошло, если бы на экране отображались разные формы? Вам нужно будет написать функцию для каждой формы, которая у вас есть. Абстракция была бы лучше, если бы у вас была одна функция, которая принимает любую форму и отображает конкретную форму на основе ее свойств. Это был бы более абстрактный дизайн.
В этом примере треугольник - это конкретная реализация формы, а форма - это общая идея. Абстракция уменьшает дублирование кода при одновременном повышении безопасности.
5. Повторное использование
Это довольно просто и интуитивно понятно, но мы хотим быть уверены, что всякий раз, когда мы пишем код, мы думаем о том, как сделать этот код максимально многоразовым. Это идет рука об руку с абстракцией. Вместо того, чтобы писать конкретную функцию, которая хорошо выполняет одну задачу, но работает, возможно, только в одной конкретной реализации, мы можем сделать ее общей - немного более абстрактной. Таким образом, мы допускаем повторное использование в разных контекстах. Это основная идея возможности повторного использования.
Думайте об этом как о небольшой жертве заранее, чтобы сэкономить время позже, вместо того, чтобы возвращаться и понимать этот код, переписывать его или выполнять другую функцию.
6. Возможность расширения
Гибкость проектирования сводится к тому, чтобы предвидеть изменения в вашей системе в будущем. Ваша система может быть простой в настоящее время, но усложняться в будущем. Возможно, вы захотите добавить еще много чего. Вы можете заменить реализацию объекта или элемента на лучшую. Часто люди проектируют системы для использования сегодня. Они не думают о том, что через месяц или, может быть, через год они собираются масштабировать проект.
Для разработчика нет ничего хуже, чем переделывать то, что они уже разработали ранее, но всем нам приходится сталкиваться с нашими ошибками, чтобы учиться. В таком случае исправление базы кода новыми функциями не поможет. Легче разработать полностью новый дизайн, чем пытаться изменить существующий. Я уверен, что вы уже сталкивались с этим раньше.
7. Предвидеть устаревание
Если вы используете внешние зависимости в своем проекте или системе, вам нужно быть очень осторожным с тем, какие зависимости вы используете. Могут ли они в будущем устареть? Есть много разных способов, с помощью которых внешняя зависимость может уйти в небытие. Он может устареть, он может больше не работать для определенной версии вашего языка программирования после обновления, или он может не поддерживаться или поддерживаться, скажем, в Windows, Linux или Mac. Вы уловили суть.
Вам нужно убедиться, что у вас нет проекта, который полагается на сотни внешних зависимостей, потому что, если что-то пойдет не так, вы некоторое время не будете улыбаться. На всякий случай избегайте ранних, не LTS выпусков программного обеспечения, используйте программное обеспечение от уважаемых компаний, сводите использование внешних зависимостей к минимуму и держитесь подальше от плохо документированных или поддерживаемых проектов.
8. “Портируемый” дизайн
При разработке системы вы должны помнить, что она может использоваться на другой платформе или устройстве, отличающемся от того, на что вы в настоящее время нацеливаетесь. Если вы создаете веб-приложение только для Интернета, это будет дорогостоящим и трудоемким, если вы когда-нибудь захотите превратить его в приложение для iOS, приложение для Android, настольное приложение Windows или что-то в этом роде. Это может потребовать создания совершенно новой системы для возможности переноса. Этот пункт особенно актуален разработчикам игр. Поэтому стоит особое внимание обратить на выбор среды разработки. Например в Unity приложения достаточно легко переносятся на Android/iOS/macOS/Windows standalone.
Итак, вам нужно иметь это в виду при проектировании системы.
9. Проектирование тестируемый системы
Вы должны знать, что проектирование с учетом тестирования, становится очень важным при работе с крупномасштабными системами и большими кодовыми базами. Подумайте о компании вроде Google или Microsoft. Как вы думаете, сколько тестов они проводят за день? Еще лучше, сколько тестов, по вашему мнению, они запускают при каждом pull request? Вероятно, где-то в районе 5000+. Почему? Им нужно убедиться, что все, что вы “закоммитили”, ничего не сломает.
Как они могут провести такое количество тестов? Разработчики, которые написали эти массивные кодовые базы, сделали их способными тестировать то, что они пишут. Вывод: если вы пишете много кода в огромной базе кода, убедитесь, что он поддается тестированию.
10. Дизайн понятный новичку
Нет никакого способа облегчить это, но это просто означает защиту вашего кода от идиотов или защиту вашего кода от непрофессионалла. Вы даже можете думать об этом как о проверке кода для новичков. Это лучший способ объяснить это.
Вы должны представить, что любой, кто использует ваш код, фреймворк, классы или что-то еще, является новичком. Вам следует убедиться, что у вас хорошие сообщения об ошибках. Вам нужно удостовериться, что обрабатываются все недопустимые входные данные, которые кто-либо вводит в систему. Сделайте программу прочной. Убедитесь, что в ней есть действительные сообщения об ошибках и возможные уведомления, которые помогут пользователю правильно понять ошибку и устранить ее.
Если вы начнете возиться с синтаксисом на любом языке, вы получите довольно хорошие сообщения об ошибках. Вы будете знать, что делаете неправильно, и если вы посмотрите это в Google или Stack Overflow, вы поймете, что вы сделали не так в своей программе. Единственная причина, по которой вы можете это сделать, заключается в том, что человек, написавший этот код, разработал его в целях защиты. Они знали, что такие люди, как вы и я, будем использовать фреймворк или язык, и они разработали его таким образом, чтобы он помог нам его использовать.
Заключение
Как я сказал в начале, эти принципы - не то, что вам всегда нужно соблюдать. Из этих принципов есть исключения. Основная идея здесь в том, что вам нужно знать об этих принципах. Подумайте о них. Если вы хотите нарушить одно из них, убедитесь, что вы можете обосновать причину и понять, почему этот принцип может не применяться в вашей ситуации.
Я надеюсь, это поможет вам.
Комментарии (5)
ProsWeb
05.08.2021 09:38Нет никакого способа облегчить это, но это просто означает защиту вашего кода от идиотов или защиту вашего кода от непрофессионалла. Вы даже можете думать об этом как о проверке кода для новичков. Это лучший способ объяснить это.
Вообще непонятно о чём речь. Четыре слова "это" на три предложения)
Bams22
Всё по делу(Снаято с уст дядюшки Боба).
Только пункт 7 вызывает вопросы.
Если мы всё таки говорим о Java, то сложно представить себе продуктовое приложение которое не имеет зависимостей. При этом пункт кажется надуманным. Если библиотека критична с точки зрения поддержки, то естественно ты выбирешь нажного поставщика, например если мы говорим о фреймворках на которых стоится наше приложения (Spring). А если говорить о вспомогательной библиотечке, то если перед использованием в своём проекте мы её протестировали и нас устараивает как она работает, то нам обновления не критичны.
Буду рад если кто нибудь приведёт кейс когда нам критично "Предвидеть ускорение", чтобы я понял что я не прав.
deft31 Автор
Я сталкивался в одном из своих проектов с либой которая работала до Java 7. И таких либ было несколько. Из за этого миграция на Java 8 была очень сильно затруднена и болезненна.
xaerom
Ну так эти либы вам время на разработку экономили наверно?