Pull to refresh

Зачем нужно внедрение зависимостей в JS

Level of difficultyEasy
Reading time4 min
Views5K

Этот пост является ещё одной попыткой сформулировать идею, зачем нужно внедрение зависимостей в ванильном JavaScript (именно в ES6+, а не в TS).

Основная сложность в том, что шаблон «внедрение зависимостей» (DI) есть следствие применение на практике «принципа инверсии зависимостей» (DIP). Классическая формулировка этого принципа выглядит так:

A. Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций.

B. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Для JS‑программиста данная формулировка представляет определённую сложность в силу того, что в JS нет классических абстракций (в виде «интерфейсов» из других ЯП). В JS вообще нет абстракций, тут всё очень конкретно: вот объекты, вот примитивы — комбинируй.

Тем не менее, если спуститься с уровня теории на уровень практики, внедрение зависимостей вполне успешно может применяться даже в таком «конкретном» языке.

Читать далее
Total votes 6: ↑6 and ↓0+6
Comments17

Инверсия зависимостей и 'import' в JS

Reading time4 min
Views7.1K

В процессе обсуждения статьи "Почему я «мучаюсь» с JS" у меня сложилось понимание, что связка export / import в JS является базой для указания зависимостей между элементами кода (классами и функциями). А так как современные приложения вышли за рамки однофайловых и давно уже строятся из блоков, то выстраивание зависимостей между элементами кода имеет весомое значение. Настолько весомое, что в знаменитой аббревиатуре SOLID этому посвящена отдельная буква — D (Dependency inversion — инверсия зависимостей, не путать с Dependency injection — внедрение зависимостей).


Размышляя над тем, как связываются зависимые элементы кода в JS через export / import, я пришёл к выводу, что не все зависимости в коде es6-модулей SOLID'ных приложений можно описать инструкциями import. Излагаю свои соображения, чтобы коллеги могли указать, где я ошибаюсь, или подтвердить мои выкладки.

Читать дальше →
Total votes 4: ↑2 and ↓20
Comments76

Тысячная статья про принципы SOLID

Reading time3 min
Views27K

Ещё будучи совсем-совсем начинающим разработчиком, я услышал про принципы SOLID и, конечно же, совершенно их не понял. Их не помогли понять ни лекции Дядюшки Боба, ни книга его же авторства, не несколько десятков (а то и сотен) статей в интернете, которые я тогда прочитал (по какой-то причине мне эти принципы казались чем-то очень важным, прямо-таки фундаментальным). Сейчас я могу сказать, что понимаю их как-то, по-своему, и пользуюсь ими каждый день. В данной короткой статье хочу поделиться своими размышлениями о сути принципов, которые были бы понятны тому мне из прошлого, который пытался загуглить доступное объяснение этих принципов.

Читать далее
Total votes 35: ↑24 and ↓11+13
Comments36

Про модель, логику, ООП, разработку и остальное

Reading time29 min
Views109K
Часто ли вы задумываетесь – почему что-то сделано так или иначе? Почему у вас микросервисы или монолит, двухзвенка или трехзвенка? Зачем вам многослойная архитектура и сколько у вас вообще слоев? Что такое бизнес-логика, логика приложения, презентационная логика и почему все так разделено? Посмотрите на свое приложение – как оно вообще спроектировано? Что в нем и где находится, почему это сделано именно так?
Потому что так написано в книжках или так говорят авторитетные личности? Какие ВАШИ проблемы решает тот или иной подход/паттерн?
Даже то, что на первый взгляд кажется очевидным, порой бывает очень сложно объяснить. А иногда, в попытке объяснения, приходит понимание того, что очевидные мысли были и вовсе ошибочны.
Давайте попробуем взять какой-нибудь пример и изучить на нем эти вопросы со всех сторон.
Читать дальше →
Total votes 55: ↑51 and ↓4+47
Comments34

Любовь или брак по расчету с Dependency Injection?

Reading time3 min
Views7.9K
В своей статье хочу рассмотреть пример неправильного, на мой взгляд, использования Dependency Injection принципа и попробовать отыскать мотивацию для других разработчиков команды (а может и кому еще сгодится) писать новый код лучше, а также по мере сталкивания в рамках рабочих активностей с чужим кодом, написанным неграмотным образом, делать рефакторинг.

Итак, суть проблемы. На проекте мы используем OData WebApi и все контроллеры наследуются от базового, используют метод GetService из базового класса который вытягивает зависимости через статический класс ApiControllerScopeContextMediator.

public abstract class ODataControllerBase : ODataController
{		
	protected T GetService<T>()
        {
              return ApiControllerScopeContextMediator.GetService<T>(this);
        }		
}	
internal static class ApiControllerScopeContextMediator
 {		
	internal static T GetService<T>(ApiController controller)
        {
              return (T) controller.Configuration.DependencyResolver.GetService(typeof (T));
        }		
}
	

А в Global.asax конфигурируем подтягивание зависимостей для OData через StructureMap:

    GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver(container);

Во всех action у контроллеров повсеместно используется метод GetService, как, например, здесь:

public class DisconnectedAppsController : ODataControllerBase
{
	public IHttpActionResult Get()
        {		
		var query = GetService<IQuery<IQueryable<DisconnectedAppDomain>, DisconnectedAppFilter>>();		
	}
}

Но почему? Ведь можно было бы просто использовать constructor injection:

public DisconnectedAppsController(IQuery<IQueryable<DisconnectedAppDomain>, DisconnectedAppFilter> query){
    _query = query;
}

Так что же все-таки: «Таити, Таити» (Constructor Injection) или «нас и здесь неплохо кормят» (GetService)?
Читать дальше →
Total votes 11: ↑4 and ↓7-3
Comments78