Кирилл Саксин
@saksmt
Scala/Kotlin/Java/%JVM_LANG_NAME% разработчик
Информация
- В рейтинге
- Не участвует
- Откуда
- Санкт-Петербург, Санкт-Петербург и область, Россия
- Дата рождения
- Зарегистрирован
- Активность
Scala/Kotlin/Java/%JVM_LANG_NAME% разработчик
Ваш аккаунт
Вам не кажется эта проблема притянутой за уши? С тем же успехом вы бы могли жаловаться на то, что любой компонент (функция, класс) завязаны на какой-нибудь кастомный flatMap или промисы.
Не суть, главное, что у JSX есть интерфейс для интеграции. + где-то на просторах интернета была статья о использовании JSX как я описал, вот только ссылочка потерялась.
Проявите фантазию:
P.S. В typescript не очень-то умею.
Не бывает "особого" или не "особого" проектирования, оно либо есть, либо код загнивает. + у каждой библиотеки есть своя философия и если её не придерживаться то непременно выйдет говнокод.
У вас слишком слабая поддержка и никаких гарантий что завтра вы этот проект не забросите. Так что для ынтырпрайза не годится.
Вы путаете, там реализовывали не простые компоненты, а универсальные вундервафли, так что не в счёт.
В таком случае не честно выбирать LOC метрику для сравнения. Хотя можете оставить LOC, только примените его для сравнения покрытия.
Как и в использовании любого другого символа в качестве разделителя, кроме того, который был для этого предназначен.
И потом упорно объяснять, что вы не верблюд когда у вас спрашивают "чем же вас не устроили общепринятые стандарты?"
Я про JS
Это-то тут причём? Если все мои классы вдруг начнут называться
Classer
я наверно приму решение о самовыпиле из мира сего, собственно названийViewer
для всех вьюх тоже будет достаточно.Для этой области вполне обычное дело.
Допустим есть вот такой компонент —
search.customers.CustomersPaneComponent
, для него селектор мог бы быть например таким —search-customers--customers-pane
илиseach-customers--customersPane
Не тот случай, это даже "вариантом" назвать нельзя.
Крайне странный пример, который не показывает в чём же у меня в этой ситуации возникнут проблемы. Особенно при условии, что футер и шапка поумолчанию
null
и не выводятся.Вы привели код, который генерирует реакт+jsx, а не jsx.
Вы его не аргументировали. "Мне не нравится" и "Слишком многословно" — это не аргументы в пользу "XML не наглядный".
Вложенные вызовы, лямбды, ...
При нормальном проектировании компонента это где угодно элементарно реализуется.
Вы точно в продакшне работаете? Своё — это, за редким исключением, велосипед на костылях, который требует поддержки и покрытия.
Тем не менее это будет наверно самая популярная ошибка.
Которые опять-таки не говорят о ущербности реакта, а разве что о ущербности разработчиков конкретных библиотек + у вас там совершенно не честное сравнение вашего компонента, который почти ничего не умеет, и сферических космолётов в вакууме.
Консоль огнелиса:
Именно! Потому что эти символы в этих языках имеют смысл и не пересекаются с уже установленными соглашениями.
А в других языках это можно транслировать, например, как в ангуляре.
Не слишком удобно, когда каждый класс вьюхи называется
View
. С тем же успехом можно было бы назвать вообще все классыClass
и просто класть в разные пакеты.Сомнительно, что человек в здравом уме захочет иметь такие имена классов. А пример — не преувеличение. SID — что-то вроде унифицированной базовой модели любой биллинговой системы.
Вам примеры FQCN (Fully Qualified Class Name) нужны?
Венгерская нотация уже давно умерла (с появлением нормальных IDE), да и то, что вы тут описываете — не венгерская нотация.
То, что вы не правильно поняли концепт реакта не говорит о том, что он плохо расширяется. Это говорит лишь о том, что если вы пилите компонент панели, то всё, что она о себе должна знать — это то, что у неё возможно (nullable) есть шапка, тело и футер, а вот что в них будет решат уже они сами (собственно в моём примере на scala-tags+udash это и реализовано).
Вы в этом уверены? Насколько я понял tsx/jsx транслируется примерно в такие вызовы (псевдокод):
tagName[T](children: List[T], attributes: Map[String, Object]): T
Это лично ваше мнение.
view-tree — это DSL на базе самописного формата. Я же имел ввиду именно DSL на базе стандартных возможностей языка, хоть в JS это и не популярно.
Не могу себе представить кейс, когда это было бы действительно необходимо и не решалось бы несложной композицией других компонентов. Так что это похоже на побочную фичу — т.е. мне это представляется как: вы сначала написали всё это добро, а потом осознали что оно ещё "вот так" умеет, хотя может я и не прав.
Да, но их можно было бы преобразовать при очень большом желании. + nunjucks умеет в транспиляцию насколько я помню.
Я бы сказал расширенный набор компонент. И на самом деле таких фремворков сейчас как-то не видно. В лучшем случае есть набор не связанных сторонних компонент от сомнительных вендоров. У вас же виден прицел на быстрое клепание enterprise-форм, что сильно выделяет среди остальных (в хорошем смысле)
Может внезапно не оказаться вложенного элемента который ожидался и кто-то потратит время на поиск глупейшей ошибки, что может привести к летальному исходу через прошибание лба ладонью. А в худшем случае вспомнит вас (или автора компонента) пару раз за предпочтения неявного перед явным.
Первый это чьё-то поделие (не в обиду автору), количество звёзд говорит само за себя.
Второй — обёртка над бутстрапом никакой жести там кроме самого бутстрапа (способов его конфигурирования) нет.
Третий — пример идеального проектирования (ИМХО) и полного понимания что такое композиция элементов и как её нужно использовать.
Четвёртый — пример того как не надо воспринимать композицию элементов.
И ни один из них не говорит о "неизбежности говнокода", как и о недостаточной гибкости реакта.
"ё" тоже можно одинаково везде использовать, но-таки не стоит. Лучше ввести несложные правила замены, тогда семантически везде будет одно и то же.
В ts же вроде как аннотации есть, зачем тогда так извращаться?
Ровно до тех пор, пока не появятся другие классы в неймспейсе, например,
CustomerDao
иCustomerView
вmycompany.search.customer
Сомнительный момент для, например,
mycompany_search_customer_results_card_subdivision_account_identification_place_registration
и человека, который разрабатывает форму лицевого счёта. И поверьте, в SID бывает ещё и не такое...FQCN, до тех пор, пока не задано иное явно.
Вы JSX видели? Видели чем он по факту является? Так вот я предлагаю вам не городить свои велосипеды и не писать свой парсер (который к слову будет иметь баги, каким бы крутым разработчиком вы не были), а взять уже готовое решение — JSX, mustache, nunjucks или в крайнем случае написать свой DSL (не уверен на счёт TS, но в котлине или скале оно делается совсем не сложно)
>> Вот вы жалуетесь, что реализация подкачала. Но что вы предлагаете? Перевести весь код на scala?
Боже упаси, нет конечно. Не думайте, что я упоротый и пытаюсь воткнуть любимую скалу повсеместно. Это были лишь примеры того, что не обязательно велосипедировать и вполне можно обойтись простеньким DSL-ем.
>> но по факту получить лишь вопросы в духе «ну и зачем ещё один велосипед, который делает то же, что и реакт?!»?
Сомневаюсь, что кто-либо будет задавать такие вопросы. В конце концов вы пилите один из немногих на самом деле реактивных фреймворков + насколько я понял ваши идеи — это сотворить современный extJS «с блекджеком...»
>> В вашем коде потерялись следующие свойства: head, body, foot, позволяющие изменить содержимое соответствующих блоков, не меняя сами блоки
Они через конструктор передаются.
>> Кроме того, потерялся вложенный блок titler, который по умолчанию выводится в header, и который выводит внутри себя свойство title, которое есть у всех компонент.
Представьте себе ситуацию, когда кто-то изменит одновременно header, titler и title и после этого начнёт удивляться что же пошло не так. Нельзя давать слишком много гибкости. Вилкой тоже можно суп съесть, но зачем.
>> Касательно сборщика
Вам не кажется более логичным использовать как разделитель точку? И это всё равно не объясняет зачем вам "$"
>> $mol.gridView и $mol.grid.row.RowView опять же имеют разные пространства имён. Тогда уж $mol.grid.view и $mol.grid.row.view
$mol.grid.GridView и $mol.grid.row.RowView
Дело не в конкретном числе, а именно в малом количестве — я не просто так подметил, что в реальности это число ближе к 4. В целом это больше говорит о KISS. Т.е. никто не будет на самом деле сидеть и считать «а не привысило ли число абстрактной ерунды в в этой штуковине число 7?». Кстати не очень понимаю зачем в той статье упомянуты дизайнеры — мне всегда казалось, что у них число 3 более важно (максимальное число переходов, максимальное число шрифтов/цветов...)
>> Нет никакой рациональной причины фрагментировать сообщество.
У вас нет выбора «фрагментировать своё сообщество или нет» у вас выбор «будет у меня фрагментированное сообщество или его не будет совсем». Сомневаюсь что найдётся много разработчиков (не студентов, которым время девать некуда и не юниоров, которым надо просто «побольше выучить, чтоб казаться про»), которые бы стали копать вашу документацию и разбираться в тонкостях новых способов разметки, если им нужно решение здесь и сейчас, это даже для нелегаси проектов не прокатит.
>> Это нормально, что один и тот же символ в разных контекстах вызывает разные ассоциации.
Нет, это скорее исключение. "!=" везде «не равно» (haskell не в счёт) и "+" везде плюс. Не надо усложнять и так не простую жизнь разработчика новыми значениями для привычных вещей.
>> Целью статьи было поделиться свежими идеями
Я в самом первом комментарии написал, что идея хороша, а вот реализация подкачала.
>> Всегда найдутся те, кто не поняли, не привыкли, не заинтересовались
Естественно. Вопрос в количестве — и чем больше нового вы привносите (прямо скажем за зря) тем больше их будет.
>> $ используется для того, чтобы обозначить глобальное пространство имён. Именно благодаря ему, сборщик быстро находит зависимости.
Вы сейчас про typescript или про префиксы своих компонентов пишете?
>> Для $mol разработчика, в коде view.tree тоже нет ничего нового
Есть принципиальная разница: для scala-разработчика в udash и Binding.scala нет кардинально нового, а для ts-разработчика (и тем более js) в $mol сликом много нового.
>> Но если view.tree можно изучить за пару часов вдоль и поперёк, то на скалу придётся потратить существенно больше времени
Зависит от того насколько глубоко нужно изучить скалу и что уже знает изучающий.
>> Подозреваю, вы не дочитали до того момента, где объясняется, почему вместо описания класса на TypeScript был введён специальный язык.
Либо я плохо искал, либо у вас нет этого объяснения. У вас есть только сравнение с xml-подобным синтаксисом. Не самое убедительное кстати.
>> Он позволяет описывать класс в иерархической форме, при этом не теряя в гибкости, позволяя перегружать любой аспект его поведения.
Не понимаю что из этого нельзя сделать просто через ts или jsx.
>> Попробуйте реализовать аналог
https://gist.github.com/anonymous/17043c00b00117eb7af266df9cd7b802:
/**
* param header Reactive property binding
* param content Reactive property binding
* param footer Reactive property binding
* param attrs Attributes
*/
case class Page(
private val header: Property[Element] = Property[Element],
private val content: Property[Element] = Property[Element],
private val footer: Property[Element] = Property[Element],
private val attrs: Modifier*
) {
def render = div(attrs: _*)(
header,
content,
footer
)
def apply(
header: Property[Element] = this.header,
content: Property[Element] = this.content,
footer: Property[Element] = this.footer,
modifiers: Modifier* = this.attrs
) = copy(
header = header,
content = content,
footer = footer,
modifiers = modifiers
)
}
val myContent = Property(p(«hello»).render)
val mainPage = Page(style := MainPage.styles)(
header = Property(h2(«Hello»))
content = myContent
)
// application in body
body(
onclick :+= { myContent.set(p(«world»)) }
mainPage.render
)
>> Вариант $mol.rowInGridView плох тем, что его имя вылезает за пределы модуля $mol.gridView.
$mol.grid.row.RowView
Сообщество сойдётся на максимум 3 стандартах из которых мейнтейнеру и нужно выбирать, а не думать, что у кого-то "#" начнёт ассоциироваться с идентификатором, а не комментарием. Касательно остальных ваших я согласен разве что с экранированием, да и то относительно.
Как вы думаете почему я первую половину статьи прочитал, а остальную бегло просмотрел и начал «выискивать»? Всегда задавайте себе такой вопрос, когда кто-либо относительно аргументировано начинает критиковать — обычно это значит, что вы что-то не учли или не просчитали либо при написании/проектировании, либо при выборе target группы. Так вот, начал я к "$" докапываться потому что у меня возникло ощущение, что я читаю статью о php/bash/perl, а не о typescript. А про спецсимволы я свою позицию уже объяснил.
Вам это не говорит о том, что код не понятен? Кхм, мой пример имеет в разы большую гибкость, вплоть до выбора типа элемента + оба возможных метода расширения функционала: наследование и композиция элементов. Уж не знаю как вы считали (генерики с лямбдами учли небось?), но для скала разработчика там всего 2 спец символа и те вполне понятны, особенно если уточнить, что ":" просто суффикс, ибо "=" не перегрузить, а именованых вараргов в отличие от питона не завезли. Касательно конструкций — там лишь наследование, генерики, свойства, методы и лямбды — ничего сверхестественного или непонятного. И да, я считаю эту «портянку» ЗНАЧИТЕЛЬНО более предпочтительной, а для тех, кому трудновато пока освоиться с нестандартным синтаксисом, но очень понравилась идея — рекомендую Binding.scala, что выглядит как реакт, с той лишь разницей, что оно действительно реактивно.
И вот моя попытка номер 2 в осознании вашего кода (https://gist.github.com/anonymous/d56c6665ab6fbea6c162f2f76abbc983):
// literally rewrote
def clickableElement(text: Modifier): TypedTag[Button] =
button(
enabled := true,
onclick := { false },
disabled := false,
tabIndex := 0
)(text)
// More generic way:
def button(text: => Modifier): TypedTag[Button] =
typedTag[Button](«button»)(
enabled := true,
onclick := { false },
disabled := false,
tabIndex := 0
)(text)
// My thoughts about what it was…
class Button extends View {
protected def enabled = true
protected def disabled = false
protected def clickHandler: (Event) => Boolean = { e => false }
protected def tabIndex = 0
abstract protected def text: Modifier
def render = button(
enabled := { this.enabled || !disabled }
onclick := clickHandler
tabIndex := { tabIndex }
)
}
>> «clicker» в данном случае — сокращение от «clickable presenter»…
Вы уж определитесь с тем, что это такое: вью, презентер (кстати рекурсивный каламбур по вашей логике получается :) ) или компонент и с тем, для чего вы ставите эти суффиксы как следствие. Я вам предложил суффикс который бы отделял компоненты от полей. И чем вас так не устроил вариант "$mol.rowInGridView"
>> Нечто такое `$.$` писать не нужно.
Оно в статье есть? — Есть. Значит-таки иногда оказывается нужно.
>> Код на некогда популярном jQuery ими утыкан чуть менее, чем полностью.
И вы хотите сказать, что это хорошо?
>> Впрочем, если отставить в сторону эти «фу, мне не нравится, я так не привык», то как бы вы реализовали view.tree?
Да хоть бы и так (https://gist.github.com/anonymous/d05bf00e33fa6e23141178e0aa524cea):
```scala
class MyView[ElementType](val e: TypedTag[ElementType], val clickHandler: (Event) => Any)
extends View
with MySuperBehavior {
val child = div()
override lazy val getTemplate = {
e(
enabled := true,
onclick := clickHandler,
onmouseover :+= { println(s«Someone moved mouse over ${e.tagName}») }
// In reality would be some sort of template method, so there won't be any `getTemplate` methods
getMySuperModifiers()
)(
p(«HEADER PART»),
child,
p(«FOOTER PART»)
)
}
override def renderChild(view: View): Unit = {
child.children.foreach(grand => child.removeChild(grand))
view.getTemplate.applyTo(child)
}
}
```
Пример, очевидно, не рабочий. Если хочется посмотреть на подобную штуку поподробнее — google://udash+scala.js
>> Это соглашение об именовании такое — заканчивать презентеры на «er», что даёт похожие на англоязычные имена.
Эти имена не правильны, большинства этих английских слов либо нет, либо они значат не то, что вы ожидаете. Лучше бы уж тогда по Java косили с повсеместным "-able" оно хотя бы переводится более-менее адекватно, да и по смыслу значительно больше подходит. И ещё раз для закрепления: clicker — «тот, кто кликает», clickable — «то, что по чему можно кликнуть».
Зато вполне есть «comment_9889944» (ваш комментарий) и оно действительно работает как якорь без всякого js
Можно, например, для начала выучить неправильные глаголы и осознать что суффикс «er» предназначен для обозначения объекта выполняющего действие и нет никакого практического смысла пихать его к каждому компоненту.
UPD: и хабру тоже (якорь в комментах)
А за ссылочку спасибо — почитаем-с. Не сталкивался я ни с чем в хаскеле приближенным к реальности, хоть и делал набеги :)
P.S. Зря вообще написал. Не думаю что имеет смысл продолжать эту ветку — не будем заранее отпугивать тех, кто совершенно не в теме.