Pull to refresh
13
0
Егор Непомнящих @enepomnyaschih

User

Send message
Как разработчика, однажды унаследовавшего от предыдущей команды кодовую базу на Scala, меня сильно огорчит, если pattern matching появится в прочих языках. Дело в том, что разработчики, имея такой инструмент на руках, начинают использовать его где надо и где не надо. По итогу, у вас вся кодовая база усеяна case'ами, которые очень сложно анализировать. Например, вы видите иерархию классов без единого использования полиморфизма и не понимаете, зачем она вообще нужна. Оказывается, вместо определения полиморфного метода, кто-то написал case по всем подклассам иерархии. Или, допустим, вы хотите добавить еще один подкласс и видите, что сделать это очень легко, т.к. в реализации нуждается лишь один-два метода. Но потом ничего не работает, потому что в коде миллион case'ов с default-реализацией, которые ваш подкласс, само собой, не учитывают. И найти их тяжело. Возможно, дело в привычке, но мне идея не нравится.
Вроде работает. Спасибо!
Подходит ли такая структура для разработки библиотек? Так, при публикации артефакта родительский pom-файл в Maven-репозиторий не попадает. Далее, когда этот артефакт указывается как зависимость некоего приложения, версии транзитивных зависимостей начинают плавать. Есть ли способ элегантно решить эту проблему? Мне в голову ничего не приходит умнее, чем скопировать секцию dependencyManagement из родительского pom библиотеки в pom приложения.
Тот самый случай, когда комментарии к публикации полезнее самой публикации.
Dart или Kotlin не рассматривали? За первым Google, за вторым JetBrains — тоже неслабые конкуренты.
Говоря о производительности, была надежда на Dart, пока Google не объявил об отказе от поддержки виртуальной машины. В тот же день я принял решение отказаться от Dart в пользу TypeScript, т.к. прочих преимуществ у Dart не было. Теперь остается надежда только на WebAssembly, но его релиз будет еще ох как нескоро. Так что на следующие пару лет TypeScript прочно занял место лидера статической типизации в фронт-енд разработке.
Да, к WebPack я прикопался лишь потому, что он совмещает CommonJS с клиентом. На самом деле, как мне кажется, проблема в самом CommonJS. Но и AMD не лучше, а других общепринятых форматов объявления JS-модулей я не знаю.

Я не совсем понял, как ваш сборщик работает. Он бандлит напрямую TypeScript, без промежуточной компиляции в CommonJS/AMD? Одна папка = один бандл? Есть документация какая-нибудь, кроме README.md? Есть поддержка SourceMaps? Я тоже свой велосипед использую, но честно-честно пытаюсь найти что-нибудь для себя подходящее, что все используют. Пока плохо получается :D
Ок, если в Java/JS/.NET это нарушение ISP, так и быть, приведу свой пример.

Есть иерархия классов представлений одной и той же модели — записи в блоге. Запись может отображаться в виде элемента общей ленты, в виде элемента ленты своих записей, в виде попапа на Google-карте, в виде содержимого диалога и никто не знает, какие еще новые представления появятся в будущем. Все представления выглядят по-разному, но у них есть много общего — общая часть вынесена в базовый абстрактный класс. В частности, общее у всех то, что если кликнуть по кнопке «Показать в диалоге», то открывается новый диалог с этой статьей. Здесь и возникает циклическая зависимость. Я реализовал в базовом классе обработку клика по кнопке с показом диалога. Это отлично работает, если явно указать порядок подключения файлов. TypeScript не показывает ошибок компиляции, даже предупреждений. Проблема возникает при попытке собрать это WebPack'ом. Приходится копировать эту логику во все подклассы. Не предлагайте решения с шиной событий или прочими хитрыми штуками: не хватало еще ради использования WebPack перезжать на другой фреймворк.
Я умею отличать класс от интерфейса. Проблема остается в обоих случаях:

interface IA {
 toB(): IB;
}
interface IB extends IA {}
class A implements IA {
 toB(): IB {
  return new B(); // здесь зависимость A от B
 }
}
class B extends A implements IB {} // здесь зависимость B от A


Модули классов A и B все равно могут идти в неправильном порядке.

Конечно, можно убрать из A дефолтную реализацию метода toB. Но зачем? Чтобы бандлер это прожевал? Я лучше выберу другой бандлер, но ограничивать себя ради такой ерунды не стану.

Я не понял, вы считаете, что toString является плохим архитектурным решением, нарушающим ISP?
Как интерфейс, содержащий один метод, может нарушить ISP? Будь их два, можно было бы поспорить.
Под принципами ООП в первую очередь понимают SOLID. Где здесь нарушена инкапсуляция?
Я не собираюсь с вами препираться. Если не знаете ответ на поставленный вопрос о WebPack, я с вами разговаривать не буду. А вы можете продолжать есть этот кактус, оправдываясь, что если он чего-то не поддерживает, значит «архитектура кривая».
Хотя даже при наследовании интерфейсов будет циклическая зависимость между модулями, где классы объявлены.
Возможно, это и решение, если мне не нужна дефолтная реализация. А она иногда нужна =)
Хотите реальный пример?

class Object {
 String toString();
}
class String extends Object {}


Теперь давайте дружно назовем разработчиков языков программирования Java, JS, и всего .NET-совместимого обезьянами.

Инкапсуляция и KISS — это не принципы, а концепции. И они здесь ни при чем. Учите матчасть.
Вообще класс родитель не должен ничего знать о наследниках

Почему? Какому принципу ООП это противоречит?

Почему жесть? Я говорю же, что в Java и .NET это работает. Даже никаких warning'ов не всплывает. И даже в JavaScript без всяких бандлеров это отлично работает, если просто файлы в правильном порядке подключить. Либо это косяк WebPack, либо решение есть, но мы просто не знаем о нем. Никак не иначе.
Нет, он прогонит код B.ts и бандл упадет с ошибкой еще на этапе загрузки. А если в главном модуле поменять их местами, все будет работать. Никакая это не странная зависимость, такое встречается сплошь и рядом. Особенно в TypeScript, где целый модуль надо импортировать лишь для того, чтобы указать имя стороннего класса в семантике какого-нибудь метода. Это не только проблема WebPack: RequireJS тоже этим страдает. В то время как Java и .NET подобной проблемой не страдали никогда. Обидно, что при всем своем развитии в последние годы средства работы с JavaScript все еще такие неудобные.
Может быть, вы сможете ответить на мой вопрос. Есть три модуля TypeScript. Модуль A.ts:

import {B} from './B';

export class A {
 toB(): B {
  return new B();
 }
}


И модуль B.ts:

import {A} from './A';

export class B extends A {
}


И главный модуль:

export * from './A';
export * from './B';


А потом мне надо собрать главный модуль как бандл. Сборка осуществляется через WebPack и ts-loader. Очевидно, в бандле объявление класса A должно идти раньше объявления класса B, иначе возникнет ошибка при попытке наследования. Но из-за циклической зависимости между модулями A и B подключение происходит в обратном порядке. А если подобных модулей добавить еще больше, порядок запуска кода предсказать становится очень сложно. Как решить эту проблему, не объединяя весь код в один модуль? Можно ли заставить WebPack подключать зацикленные модули в том порядке, который мне нужен?
Кстати, а вот и баг в самом WebPack, который изрядно доставляет проблем при подключении CSS. Единственное найденное мной решение — создание промежуточного файла all.css, импортирующего внутрь себя все остальные CSS-файлы в правильном порядке. Как видно по дате, разработчики не торопятся исправлять.
Пока этот баг открыт, к WebPack я не вернусь. Отладка превращается в ад. RequireJS — единственный подход к сборке проекта, не опирающийся на SourceMaps (ну, если не считать моего собственного сборщика).

Information

Rating
Does not participate
Location
Омск, Омская обл., Россия
Date of birth
Registered
Activity