Когда я был ребенком, я любил играть с LEGO. Я думаю, что в какой-то момент у меня было 3000 блоков общего назначения, поезд и несколько наборов Дикого Запада. Самое приятное в LEGO - это модульность различных частей. Если вы собираетесь построить что-то маленькое, вам, скорее всего, не понадобится база, но если вы собираетесь построить что-то более сложное, вам понадобится база, которая поможет определить, где должны располагаться различные части. Хороший код во многом похож на LEGO.

Маленькие блоки становятся большими блоками

Представьте, что вам нужно построить дом из блоков LEGO. Для этого дома мы собираемся измерить его с помощью ручек на базе LEGO. Для этого дома вы хотите, чтобы он был шириной 97 ручек и глубиной 103 ручки. Для стороны, которая имеет длину 97 ручек, вы можете использовать 24 блока из 4 широких ручек вместе с 1 из 1 блока ручек шириной. Таким образом, вы смогли легко удовлетворить это требование. А теперь представьте, что блока с одной ручкой не существовало. Внезапно простая задача стала практически невозможной без инструмента, позволяющего разрезать большой блок на меньший.

Как насчет другого примера? Вы хотите построить машину, и для этой машины вы хотите, чтобы у нее было 2 колеса спереди и 4 колеса сзади. С LEGO вы можете брать каждое колесо и свободно размещать его там, где вам нужно. Хорошо, теперь представьте, что человек до вас решил, что колеса должны быть расположены только по 2 спереди, а затем после 12 ручек у вас будет еще 2 (одно слева и одно справа). Внезапно эта задача снова стала невыполнимой.

Эти примеры предназначены для того, чтобы быть примерами того, в чем все мы были виноваты в то или иное время (и, вероятно, до сих пор временами). Очень легко решить проблему узкоспециализированным способом, и часто это происходит немного быстрее заранее. За годы работы профессиональным инженером-программистом я могу сказать это с уверенностью: я никогда не пинал себя по заднице, потому что сделал класс слишком маленьким и общим.

Создавайте небольшие общие классы

В этой части статьи я даю несколько советов, и этот совет состоит в том, чтобы создавать небольшие общие классы. В качестве примера предположим, что вам нужно добавить виджет погоды на панель управления вашей компании. Этот виджет будет включать текущие погодные условия в Чикаго, штат Иллинойс, и должен обновляться каждые 15 минут. Вы можете построить его специально для этого одного варианта использования или разбить его на более мелкие части и работать для многих других вариантов использования. Пойдем со вторым вариантом.

Погода будет классом, в котором хранятся данные, полученные из некоторого API. Это позволит вам прочитать из него информацию, такую ​​как текущая температура, облачность, процент осадков и скорость ветра. Чтобы создать этот объект, вам необходимо предоставить ему детали, которые я только что упомянул.

WeatherRequest будет использоваться для запроса текущих погодных условий для местоположения из некоторого API. Он не будет обрабатывать потоки и не будет обрабатывать анализ ответа за вас. Он просто берет местоположение и синхронно возвращает ответ от сервера.

WeatherParser будет использоваться для получения ответа JSON и возврата вам объекта Weather. Это можно использовать вместе с WeatherRequest. Это немного хрупко, поскольку изменения, внесенные в источник WeatherRequest, могут потенциально нарушить его работу, но это всего лишь пример.

WeatherView будет использоваться для отображения текущих погодных условий для пользователя.

WeatherUpdater примет WeatherRequest и WeatherParser, а также то, как часто он должен обновляться. Это будет обрабатывать потоки и уведомить любой заинтересованный объект, когда у него есть обновление, и это вернет объект Weather.

WeatherController по сути все организует вместе. Он позаботится о создании всех вышеперечисленных объектов (кроме Weather) и будет действовать как мост между WeatherUpdater и WeatherView.

А теперь представьте, изменятся ли требования, и теперь вам нужно отобразить текущие погодные условия для Чикаго, Сан-Франциско и Парижа. Что ж, это просто, просто обновите WeatherController, чтобы принять местоположение в качестве параметра и создать три отдельных его экземпляра.

Теперь есть новое требование: автоматически обновлять погодные условия только в Чикаго. Вы можете создать новый класс под названием WeatherDownloader, который будет использовать WeatherRequest и WeatherParser так же, как WeatherUpdater, за исключением того, что он будет загружать погоду только один раз. Видите ли, поскольку это было разбито, это позволило нам довольно легко реагировать на изменения. Конечно, это можно было сделать в одном или двух классах, но было бы сложнее отреагировать на эти изменения.

Что это на самом деле означает

Моя цель в этой статье - осветить использование более мелких повторно используемых классов. Если вы приобретете привычку делать это, то следующий шаг к использованию композиции станет намного проще. С помощью композиции вы, по сути, создадите интерфейс, который будет определять различные методы, но не будет предоставлять тело метода. Оттуда вы можете создавать отдельные классы для каждого из этих методов, известных как делегаты, эти делегаты могут обрабатывать повторное использование логики для методов интерфейса. Тогда у вас, наконец, будет класс, который может реализовывать несколько интерфейсов, и он может решать, какие делегаты использовать для каждого метода. И вуаля, у вас есть наследство без минусов.

Хороший код похож на LEGO. Он построен из множества небольших блоков для создания более крупного конечного продукта. Его должно быть легко разбирать и переставлять в случае изменения требований.

Вот и все. Эта статья немного отличается от того, что я публиковал. Я знаю, что это немного абстрактно, поэтому, если у вас есть вопросы, не стесняйтесь оставлять комментарии :)