- PVSM.RU - https://www.pvsm.ru -
Данная статья является первой частью серии статей, предназначенных, по словам автора, для тех, кто не может разобраться с внедрением зависимостей [1] и фреймворком Dagger 2 [2], либо только собирается это сделать. Оригинал написан 18 ноября 2017 года. Изображения и GIF — из оригинала. Перевод вольный.
Dagger 2 — это полностью статический фреймворк для внедрения зависимостей в Java и Android, работающий во время компиляции. Dagger 2 — это адаптация созданного ранее компанией Square [3] фреймворка Dagger [4], поддерживаемая компанией Google.
Если вы начинающий Android разработчик, изучающий непосредственно Android и параллельно получающий знания по Java, то данная статья для вас. Если вы пытались изучать Dagger 2 и то, что вы находили в интернете казалось вам немного сложным — не беспокойтесь, я тоже прошел через это (все мы немного особенные, каждому требуется свой подход в объяснении чего-либо) и эта статья определенно для вас. Если вы уже знакомы с внедрением зависимостей и Dagger, то вы сможете узнать что-нибудь новое или прояснить для себя некоторые вещи.
Предполагается, что вы уже знакомы с языком программирования Java [5], принципами ООП [6] и Android [7] разработкой.
Замечание: для объяснения данной концепции я буду использовать аналогии с телесериалом «Игра престолов». Если вы не знакомы с данным сериалом, то можете заменять имена классов на более удобные для вас. И вы должны обязательно начать смотреть этот сериал.
Понимание зависимостей и связей — это первый шаг для более четкого понимания концепций объектно-ориентированного программирования. Итак, что такое зависимость? Например, у нас есть класс Targaryens
, использующий внутри себя другой класс или интерфейс, который называется Dragons
. Значит класс Targaryens
зависит от класса или инЗаголовок спойлерафейса Dragons
.
Это означает, что класс Targaryens
не может работать без Dragons
. Также это значит, что везде, где будет использоваться класс Targaryens
будет присутствовать класс Dragons
, то есть мы не сможем повторно использовать Targaryens
без повторного использования Dragons
. В этом случае Targaryens
— зависимый класс, а Dragons
— это зависимость. Зависимый зависит от своих зависимостей.
Два класса, использующие друг друга называются связанными (‘coupled’). Связь между классами может быть либо сильной (‘tight’), либо слабой (‘loose’). Зависимости всегда направлены, то есть класс Targaryens
зависит от Dragons
, но класс Dragons
может и не зависеть от класса Targaryens
.
class Targaryens {
public Targaryens() {
//Каждый раз, когда мы используем Targaryens, нам необходимо создать экземпляр Dragons
Dragons dragons = new Dragons();
dragons.callForWar();
}
}
Большое количество зависимостей в классе приводит к проблемам сильных связей (hard dependency), что плохо по следующим причинам:
Когда классы и методы слабо связаны, не связаны или не зависят от множества других — возможности повторного использования кода возрастают. Повторное использование кода — одна из базовых идей объектно-ориентированного программирования.
Для тестирования вы можете подменить (mock) конкретные объекты. Но если в классе или методе множество зависимостей, то тестировать его будет сложно. Если Java класс (например, Targaryens
) создаёт экземпляр другого класса (Dragons
) через оператор new
, то этот класс (Targaryens
) невозможно будет протестировать независимо от класса, который создан через оператор new
(Dragons
).
Когда код не может быть корректно протестирован, его части невозможно или сложно повторно использовать, а проект продолжает расти, тогда проект становится очень сложно поддерживать. Поддерживаемость зависит от множества других факторов, но пока новые разработчики в вашей команде понимают систему и делают работу коллег комфортнее, то ваш проект всё ещё поддерживаемый.
Есть множество типов зависимостей, но можно выделить основные:
Мы рассматривали пример зависимости от класса ранее. Конструктор класса Targaryens
зависит или нуждается в классе Dragons
для вызова метода callForWar()
.
Метод executePlan
принимает интерфейс WarStrategy
как зависимость. WarStrategy
может быть реализован всеми домами (Targaryens, Starks, Lannisters и так далее).
public Result executePlan(WarStrategy strategy) {
//WarStrategy реализуется всеми домами
}
Следующий метод принимает объект HouseClass
, а вызываемый им метод getKing()
является зависимостью, которую невозможно идентифицировать в сигнатуре метода.
public String extractName(HouseClass house) {
return house.getKing();
//возвращает имя короля конкретного дома
}
Позвольте мне отвлечься на другой пример. Класс Targaryens
зависит от класса Starks
в завоевании трона. Но Starks
зависят от других королевств севера, например, Mormont
. Итак, получается, что Targaryens
напрямую зависят от Starks
и косвенно от Mormont
.
Если Java класс создаёт экземпляр другого класса через оператор new
, то этот класс невозможно будет использовать или протестировать независимо от класса, который создан через оператор new
. Это называется зависимостью.
Зависимости плохи тем, что уменьшают возможности повторного использования кода, а также усложняют процесс тестирования, из-за чего поддерживать проект становится сложнее.
Зависимости могут быть различных типов: классовые, интерфейсные, от методов, от полей, прямые, косвенные и другие.
В следующей статье мы поговорим о решении проблем сильных связей (hard dependency), и да, вы правы, через внедрение зависимостей. Рассмотрим реальный пример, найдем сильную связь и проанализируем её.
Автор: Andrei
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/269173
Ссылки в тексте:
[1] внедрением зависимостей: https://en.wikipedia.org/wiki/Dependency_injection
[2] Dagger 2: https://google.github.io/dagger/users-guide.html
[3] Square: http://square.github.io/
[4] Dagger: https://github.com/square/dagger
[5] Java: https://www.javatpoint.com/
[6] принципами ООП: https://www.javatpoint.com/java-oops-concepts
[7] Android: http://developer.android.com/
[8] Источник: https://habrahabr.ru/post/343248/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.