Обновить
6
0
Вячеслав@riogod

Пользователь

Отправить сообщение

Вы большой молодец, и решение Ваше - знаю, помню даже смотрел ваш доклад на одной из конференций.

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

А куда делись eventListener? :)

Вы уверены что данное решение будет работать и хранить в себе данные ?

А дайте пример из прода, где в рамках. Модели и вью реализуется много функционала. Если есть конечно что-нибудь на гите.

Мы рассматриваем только относительно концепции используемой в статье и не погружаемся вглубь, иначе дискуссия растянется на несколько дней или месяцев :) конечно есть куча паттернов, при помощи которых это можно автоматизировать на разных слоях(не только в рендере)

Так collecor.log(soleLog) точно так же вызывается откуда угодно, как угодно и логирует что угодно)

Тогда залогируйте мне пожалуйста следующее:

<a href="#" onClick={vm.someHandler}> link0</a>
<a href="#" onClick={vm2.someHandler1}> link1</a>
<a href="#" onClick={vm3.someHandler2}> link2</a> // Хочу писать в лог 'Пользователь кликнул на ссылку 1'
<a href="#" onClick={vm4.someHandler3}> link3</a> // Хочу писать в лог 'Пользователь кликнул на ссылку 2'
<a href="#" onClick={vm5.someHandler4}> link4</a>

Вот только эти два варианта.
Записи должны где-то сохраняться естественно до передачи.

Чем оно отличается от вызова функции collecor.log(soleLog); во всех местах где это нужно? Во всех обработчиках событий, в функции которая перехватывает роутинг, в функции которая перехватывает вызовы к АПИ, или же просто рядом с каждым конкретном вызовом вызывать данную функцию.

Тем , что решение универсальное (вызывается откуда угодно, как угодно и логирует что угодно). Полностью соответствует вашему KISS, так как для описания его мне потребовалось всего пара предложений, куда уж проще и к тому же он лежит в обсуждаемой концепции MVVM. Попробуйте гипотетически придумать ситуацию, в которой оно не сработает или будет не простым.

Действительно, пример с логером элементарный, он один и он логирует там где это только необходимо.
В случае с eventListener не все так однозначно, он тупо логирует абсолютно все клики и в том числе на тексте - везде. В данном случае в handler нам придется сделать switch-case и разделять контент отправляемый в логгер относительно event.target. Замечу, что данный switch-case будет срабатывать при каждом клике. (я надеюсь не стоит разбирать ситуацию, в которой мы в надежде избавиться от switch-case создаем N eventListener которые крутятся в реалтайме и вызывают проблемы с производительностью).

Каждый раз погружаясь все глубже, вы все больше будете обрастать костылями в этом решении, и это только simple logger.

Какая формулировка "задачи" (никакая) такое и решение. Я не знаю как у вас задумка обработки кликов, вообще всех подряд(в любом месте как в яндекс.метрика на пример) или только конкретных. Это разумеется вы не сказали. Если конкретных, то опять же все элементарно, в обработчике клика вы вызываете функцию логгера с конкретным набором данных присущих конкретной кнопке.

При неопределенности бизнес требований обычно два варианта, вы либо разрабатываете универсальное решение, либо уточняете требования. Аналитики и бизнес - не разработчики, они не видят всех потенциальных возможных проблем, а мы видим - это наша работа. Logger is just a logger, nothing more. в данном случае.
Разработчики React не пишут по бизнес-требованиям, а разрабатывают универсальное решение решающее конкретные задачи в конкретном контексе.

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

И модульные окна с оверлеями? Вы там в работе с хистори роутера не умерли? ?

шуточное решение или нет, масштабируемость этого решения крайне низкая.
В данном контексте мы рассматриваем только MVVM, там нет 40 слоев, а всего лишь 3 - Model.View.ViewModel.
Если говорить о решении в рамках большого энтерпрайз приложения которое разрабатывает большое количество разработчиков, то это другая тема, не обсуждаемая здесь.

P.S.: На всякий случай - это не я Вам минусы ставлю.

Мне на секунду показалось, что вы меня опытом хотите задавить, ладно я не буду тригериться и на это, просто скажу что занимаюсь разработкой я с 2003 года, так что опустим эти токсичные выпады на которые я могу лишь равнодушно улыбнуться.

1) в задании предложено реализовать самый обычный логгер (стандартный до не могу). И кто вам сказал про завершающую стадию? Рассматривайте это как бизнес-требование на этапе разработки архитектуры.

2) Проблемы в вашем решении:
- не консистентность, а именно в одном случае мы пишем хендлер, в другом мы делаем обертку. если какое либо дейсвие еще понадобиться залогировать, к примеру ошибки на разных уровнях приложения - наверное создадим еще обертку? или 20 оберток.
- Судя по решению, вы предлагаете в хендлере создать большую лапшу из того что надо записать в лог относительно клика? и каждый раз обрабатывая click - мы столкнемся с тем что эту портянку из ифов надо обработать - производительное ли это решение?
- popstate - срабатывает только на хистори, но в приложениях не все переходы пишутся в хистори
- вы не реализовали в вашем описании отправку логов по достижению N элементов.

Вот именно по этому мы и используем готовые архитектурные решения (даже если они нам кажутся избыточными, урезать их не стоит, так как дорабатывать потом - себе дороже) + если в решении MVVM используется модель - мы используем модель. И нам легче общаться между собой, так как используя этот термин, мы подразумеваем четкую концепцию. Мы абсолютно точно знаем, что ВМ в только поставляет данные и никак иначе, потому что так написано. Внедряя зависимости, мы получаем гибкость, консистентность решений и хорошую документированность. Потому как нам не надо описывать что в таком случае мы делаем так, в таком так. У нас одно решение на все случаи.

Модель не только хранит бизнес данные, но и имеет методы для их изменения и обработки (Вообще, по хорошему, бизнес данные у нас хранятся в entity, а модель - это набор методов для сущности. но я специально это опустил что бы не погружаться и не запутать от основной концепции).

Модель (англ. Model) (так же, как в классической MVC) представляет собой логику работы с данными и описание фундаментальных данных, необходимых для работы приложения.


Бизнес требования в сложных системах могут быть очень разными и это наиболее простое из того что может быть. Это по сути дела, обычный, самый стандартный логгер. Мы не логируем вызов любого метода VM, мы логируем действия пользователя. Решение через middleware конечно имеет право на жизнь, но я не спроста указал что в логи мы можем писать что угодно в зависимости от ситуации (someLog). И если это не сущности MVVM, то как мы их классифицируем и куда положим? А будет ли это универсальным решением? как нам это использовать например в роутинге что бы залогировать переход?

К сожалению, на практике "Это так же элементарно, понятное дело все рутинные и однообразные действия завернуты в какие-то функции обертки/вспомогательные классы, в них добавляете свою чудо логику и вуаля." превращается в огромную не документированную и не консистентную помойку.

Чуть ниже я описал пример реализации. Вы можете с ним ознакомиться, а так же предложить решение для предложенного примера в рамках вашего понимания элементарности ☺️. Код не обязательно, просто опишите, как должно работать.

ну в небольших системах, в которых разрабатывают 1-2 разработчика - наверное нет. Если система большая и разрабатывается большой группой, либо приложение имеет много фичей - определенно да.


Для примера приведу пример ?: Мы хотим логировать каждое действие пользователя (клики, вызов эндпоинтов, переход по роутингу) складывать это в какое-либо хранилище и отсылать на сервер когда накопилось N количество данных.
Решение:
во всех VM мы внедряем модель "LogCollectorModel" и просто на каждом методе VM мы вызываем метод this.logCollectorModel.addToLog(someLog). В методе модели addToLog, мы проверяем, скопилось ли достаточное количество данных и если да, то отправляем, если нет, то добавляем в хранилище.

Как часто нужен такой подход? Ну на вскидку: Взаимодействие с пользователями, ролевыми моделями, авторизацией, доступом, логированием, выводом ошибок, интернационализацией, словари, фичатоглы, общие параметры приложения, списочные модели и т.д и т.п

А как бы вы решили данную задачу при описанном подходе?

Понятие чистой архитектуры - это всегда условная вещь. 

Как раз эта вещь не условная, а набор правил и рекомендаций по созданию гибкой системы. Данный подход широко применяем в мобильной и десктопной разработке, там, где вы создаете пользовательский интерфейс.
Вообще, в принципе, фронтенд разработка уже давно вышла за рамки гипертекста и мы разрабатываем больше целые приложения.

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

Я как раз подсветил как раз этот момент в минусах, но как только человек разбирается в базовых принципах, процесс работы над фичей происходит гораздо быстрее и гибче. Разработчики используют один и тот же подход на уровне всего приложения и если посадить разработчика на фичу, которую делал другой разраб - у него не возникает "Да #@$@, кто это писал" и ему нет необходимости тратить время что бы понять как оно работает, а так же у него не возникает вопросов "А как мне это написать". Он четко знает, что маппинг - тут, бизнес данные храним здесь, если мне что-то нужно оттуда - я возьму это оттуда.

Я ни в коем случае не пытаюсь сказать что вот подход - использовать его можно так и никак иначе, но скажем есть автомобиль, есть тип автомобиля - седан, вы же не называете все автомобили седанами, а только те, которые соответствуют каким-то критериям. Вы же не называете кабриолет джипом, лишь потому что они схожи концептуально, тут тоже самое, так как тем, кто читает статью не приходиться додумывать "А что хотел сказать автор?" или например если статью будет читать тот, кто не разбирается в вопросе, ведь тем самым он может использовать это за референс и абсолютно наивно полагать, что MVVM строится именно таким образом. Ни в коем случае не критика в Ваш адрес, а просто небольшое замечание, вы в любом случае большой молодец, что ресерчите это направление.

Не viewModel.field, а viewModel.model.field

касаемо этого:
Посредством DI вы внедряете зависимости в VM. К примеру:

// Model.ts
@injectable()
export class SomeModel implements ISomeModel {
  id = '';
  serviceDesc = '';
  serviceName = '';
  systemName = '';

  constructor() {
    makeAutoObservable(this);
  }

  fillModel(): void {
    this.id = '1';
    this.serviceDesc = 'Some description';
    this.serviceName = 'someService';
    this.systemName = 'someSystem';
  }

  dispose(): void {
   this.id = '';
   this.serviceDesc = '';
   this.serviceName = '';
   this.systemName = '';
  }
}



//ViewModel.ts
@injectable()
export class SomeVM implements ISomeVM  {
  loading = false;
  
  get item(): ISomeModel {
    return this.someModel;
  }

  constructor(
    @inject('someModel')
    protected someModel: ISomeModel
  ) {
    makeObservable<ISomeVM>(this, {
      loading: observable,
      item: observable,
      init: action.bound,
      dispose: action.bound
    });
  }

  init(): void {
    this.loading = true;

    try {
      this.someModel.fillModel();
    } finally {
      this.loading = false;
    }
  }
  
  dispose(): void {
    this.loading = false;
    this.someModel.dispose();
  }
}



//ui.tsx
const SomePage: FC = () => {

  // кастомный хук который вытягивает нужную VM из контейнера
  const myVM = useViewModel<ISomeVM>('SomeVM');
  
  if(myVM.loading) {
    return (<>Loading...</>)
  }
  
  return (
    <>
      <div>{myVM.item.id}</div>
      <div>{myVM.item.serviceDesc}</div>
      <div>{myVM.item.serviceName}</div>
      <div>{myVM.item.systemName}</div>

      <button onClick={myVM.init} > Загрузить </button>
      <button onClick={myVM.dispose} > Очистить </button>
    </>
  );
};

export default observer(SomePage);
// observer - функция из mobx-react-lite которая обсервит состояние и ререндерит компонент.

Маленький пример внедрения зависимостей, эту же модель вы можете внедрить и в какой-либо другой VM в которой она вам понадобиться. А так же, эту VM вы можете использовать в любом компоненте, в котором она понадобиться. Что означает переиспользование. Мы не кладем все яйца в корзину, а разделяем так, что бы можно было переиспользовать.
Бонусом ко всему - без проблемное тестирование любого участка кода.
Касаемо хранения VM и моделей в памяти, это копейки, в основном память кушают бизнес данные, которые мы выгружаем методами dispose. Можно очищать к примеру при выходе с роута, а при входе - дергать init метод из VM (Да, описываем это в конфиге роута, желательно использовать агностик, к примеру router5).

Думаю пример выше ответит на большинство вопросов, но если что-то не ясно, я с радостью объясню.

Каждый занимается своим делом

Утро. опечатался. конечно же "это стул - на нем сидят"

Это стол - за ним едят, это вилка - ей едят, это стул - за ним сидят. VM конечно поставляет методы для работы через которые ui взаимодействует с моделью, но если VM будет и хранить в себе данные и заниматься вообще всем (в том числе и натягиванием совы на глобус), то тогда зачем выносить что-то в VM? храните все в компоненте на 2000-3000 строк.

Архитектурные решения для того и создаются, что бы иметь консистентный подход при разработке фичей и разработчик четко понимал, на каком уровне что происходит. Для примера: если мне потребуется в разных частях приложения делать какие-либо действия (например пускай это будет запись и обновление в IndexedDB каких либо данных, или вызов эндпоинта), то в моем случае я из VM просто вызову соответствующий useCase (а в более крупном представлении метод из модели), в вашем же случае, я надеюсь не стоит пояснять, сколько раз вы задублируете код и какие проблемы это потянет если вы захотите изменить логику того или иного флоу.

То что я советую в виде View->ViewModel->Model - это MVVM как странно бы это не звучало, и эти четыре буковочки значатся в заголовке статьи и лейтмотивом бегут через весь текст. Прошу заметить, что в минусах, описанных мной, не значатся архитектурные проблемы, так как данный подход используется много где в отличии от веба, и он обкатан годами, а только лишь конкретные проблемы в используемых решениях.

Не очень согласен с данной концепцией в виду того, что VIewModel является поставщиком данных, но никак не стором. Описанное решение в рамках VVM - да, но MVVM предусматривает еще и модель. Нет необходимости устраивать стор из VM при наличии di контейнера.

Каждая вьюмодель должна быть привязана ко вью и, следовательно, при удалении вью из разметки вьюмодель должна "умирать";

Абсолютно не обязательно, если VM поставляет исключительно бизнес данные. пускай себе синглтоном валяется, а вот модель должна очищаться. View-модель — это абстракция представления.

Каждая вьюмодель может (и зачастую будет) являться стором;

максимум состояние лоадинга

Этот стор может использоваться не только в компоненте, который создал вьюмодель (т.е. внутри вью), но и во всех дочерних компонентах вью;

можно воспользоваться mobx-react-lite и через обсерв ререндерить компоненты. Концепция в принципе должна предполагать, что если вам завтра захочется переписать на Vue, то вы просто перерисуете компоненты

Вью и вьюмодели знают о существовании друг друга

а зачем ? точнее не так, зачем VM знать о view ?


К несчастью, я являюсь человеком живущим с этим в проме (CRM система), если в двух словах, то реализация должна выглядеть следующим образом:

Репозитории, ЮзКейсы, Сущности (или модель сущности), и Вьюмодель могут быть извлечены из DI контейнера
Репозитории, ЮзКейсы, Сущности (или модель сущности), и Вьюмодель могут быть извлечены из DI контейнера

В данном архитектурном решении разрабатывает N команд и вот основные минусы этого подхода:

  • Долгий вход нового разработчика, даже с хорошей документацией, так как новый человек должен разобраться во многих концепциях, с которыми он как фронтед разработчик не сталкивался.

  • Если вы живете в монолите, все хорошо, и даже успешно можно реализовать модульный подход, но стоит вам попытаться разъехаться на микрофронтенд для независимого релизного цикла - добро пожаловать в театр боли и страданий.

  • Боль и страдания уготованы вам так же, если вы изменяете данные в наблюдаемых объектах mobx через создание нового объекта (к примеру через спред оператор). Как говориться вызывайте спасателей, мы ищем где потекла память.

  • tsyringe - более-менее ведет себя в монолите, но чуть больше (например модульность) - пиши пропало. Связывание контейнеров очень увлекательная игра в которой Вы - не выиграете :) Более-менее ведет себя inversify.

  • Вернемся к mobx, допустим у Вас есть большая структура бизнес данных, которую необходимо обсервить. И тут будет ждать не ожиданость, Что-то изменили на N уровне структуры - а компонент не ререндериться, вы берете бубен и идете плясать. toJS в геттере конечно помогает, но батенька это надо еще понять, почему оно не ререндериться.

И это только верхушка айсберга. Можно наверное и жить в виде View->ViewModel->Model->Entity, но в сложных решениях необходимо более мелкое разделение что бы была возможность переиспользования.

Есть конечно и плюсы, но боли тоже много. Советую почитать о чистой архитектуре, раз уж вы пожаловали к нам на дно %)

логика: 3 горизонтальных полоски как визуальный эквивалент списочному меню.
1) абсолютно не согласен с этим утверждением. Если следовать логике (а я надеюсь ваша логика в том что карты из майнинга подвергаются перегреву) то тогда оно относиться ко всем БУ картам не зависимо от способа их использования.
2) за цену посредственной водянки никакая воздушка не сможет обеспечить тишину и стабильную работу без перегрева в случаях двух видеокарт. так что в этой части совет водяки — оправдан.

Но если вдруг — вот вам виртуальные 30 тысяч рублей на охлаждение — удивите меня.
ну меня так же зацепила эта больная тема и стандартный рыночный взгляд, по этому я тоже не прочь был порассуждать с вами в данном направлении. Возможно автор найдет для себя вещи на «задуматься».

Пока мы сами не начнем менять мнение и отношение к этому, все останется на кругах своя еще на 10 лет.
Пока мы сами не сформулируем критерии, качества, а так же суть сущности специалиста — все останется на кругах своя еще на 20 лет.
Или же вы прикрываясь рынком и просто не хотите платить реальную стоимость специалиста превращая разницу в прибыль компании(возможно) или же занижая цены рынка на услугу за счет этой разницы(возможно)?
Вы возможно усомнитесь в том что бывают такие руководители или компании, которые выплачивают столько, сколько по мнению компании или руководителя (а не рынка) стоит специалист? Но они есть и как правило держат специалистов высокой квалификации способных работать на проектах высокой сложности и когда к этому специалисту обращаются компании с предложением о работе, естественным образом он их отвергает, так как компания изначально не понимает ценность данного человека и те трудности, через которые ему пришлось пройти что бы стать им.
Давайте для начала поговорим о сотрудниках начального уровня, о тех самых девочках которые прошли курс за 15.000 рублей и которые хотят претендовать на з\п в 30.000р. Как мы знаем — все познается в сравнении и раз уж вы начали использовать рынок в призме HH, то взглянем на профессии которые доступны в этой же ценовой категории и которым надо так же уделить 1.5 месяца на обучение:
  • Водитель такси
  • Горничная
  • Курьер
  • Уборщица
  • и т.д.

и после этого 30К кажется очень приятной цифрой, а если мы еще рассмотрим среднестатистические расходы в виде оплаты жилья\проезда\еды, то цифра кажется вообще в притык и по минимуму. Так что рассуждая таким образом, с чего вы взяли что эта девочка способна полностью погрузиться в изучение проф области, если вы не можете закрыть даже базовые потребности предлагаемой зарплатой и возвращаясь из этого тезиса к
с успехом конкурируют с дизайнерами с высшим образованием и опытом в 5 лет

не кажется ли Вам, что в данной формуле, недооцененным является именно специалист с 5и летнем стажем? а так же система оценки ценностей самой компании, которая говорит ему — «Чувак, твой потолок 80К, не нравиться — дверь в том направлении, так как это рынок». И «чувак» — уходит, потому что ему конечно не нравится и у компании появляется текучка и они начинают хейтить людей даже за попытки насытить им профобласть.
Я бы мог и дальше развернуть ответ затронув темы KPI, обучения специалитета и т.д., но это будет слишком много букАф.

Данный опус ни в коем случае не попытка хейта в сторону Вас или компании, а просто альтернативная точка зрения на проблематику.

т.е. вы серьезно полагаете что хороший специалист, который потратил не один год на обучение и вкладывал в себя стоит 1130 евро в месяц?

Вот могу сказать что 80.000 — это почти средний менеджер по продажам, а 60.000 — начинающий.(это фиксированная часть без премий)
А теперь объясните мне почему человек должен потратить кучу времени на обучение, а порой даже и денег и получать на 20-40 тысяч больше профессии, которой можно обучиться за месяц и при этом еще зашиваться с переработками(исходя из текста)?

— а прайс на услуги компании так же занижаются?

Информация

В рейтинге
Не участвует
Откуда
Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность