MVC-подобные подходы. Зачем mutable Model?

6yrop

Вот есть всякие MVC, MVVM, MVP, MVW. Тут возник вопрос, а зачем вообще mutable Model? 90 процентов изменяемого состояния по-любому находится в UI элементах. Остальные 10% можно тоже хранить где-нибудь рядом с UI элементами. Осталось написать функции, которые работают с этим состоянием, и приложение готово. Эти функции не должны добавлять изменяемого состояния.
Часто Model это нечто, которое добавляет своё изменяемое состояние. Зачем? Известно же, что изменяемое состояние часто усложняет разработку и развитие софта. Хотелось бы услышать убедительное обоснование зачем мы вот так просто вводим дополнительное изменяемое состояние в систему?
 

... gives you a lot of flexibility to nicely separate presentation logic from business logic and presentation state. Please use it fuel your productivity and application maintainability rather than heated discussions about things that at the end of the day don't matter that much.
 

Что такое "presentation logic" и "business logic"? И как это помогает повысить "maintainability"?
Начнем с maintainability. Maintainability это когда заказчик говорит, вот, да, сейчас это запрограммировано вот так, а теперь нам надо вот так. При этом обсуждения с заказчиком идет в терминах типа: эти данные должны браться отсюда, рассчитываться вот так, валидироваться вот так, отображаться и редактироваться вот так, здесь должно быть подсвечено красным, здесь должен стоять крестик. Где здесь "business logic", а где "presentation logic"? И как разделение множества требований на два подмножества business logic и presentation logic поможет сделать код более maintainability? Если напрямую записать требования в коде, почему у такого кода будет хуже maintainability?

Dasar

90 процентов изменяемого состояния по-любому находится в UI элементах.
При редактировании небольшого набора данных так и есть.
И на таких задачах бОльшая часть состояния (или вообще всё) напрямую хранится во view. Например, состояние нового элемента, которые еще не добавлен к модели, очень часто хранится только во view (в полях контролов).
90 процентов изменяемого состояния по-любому находится в UI элементах.
Для списков от 1000 элементов, ситуация обычно обратная.
10% элементов "материализовано" в виде View, а остальные 90% храняться только в виде модели.
Осталось написать функции, которые работают с этим состоянием, и приложение готово. Эти функции не должны добавлять изменяемого состояния.
Есть куча сервисных функций (проверка на согласованность значений полей, проверка на уникальность, генерация списка для выбора и т.д. которые неудобно формулировать в терминах View. Громоздкость и необходимость частого переписывания появляется из-за того, что View содержит кучу вспомогательных часто меняющихся решений (группировка на экране, вспомогательные визуальные компоненты, анимация, "хаки" для обхода устройства вывода и т.д.)
Где здесь "business logic", а где "presentation logic"?
Разделение на business logic и presentation logic появляется из-за того, что разные требования обладают разной критичностью.
Допущенная ошибка в реализации business logic приводит к отказу всей системы.
Допущенная ошибка в реализации presentation logic приводит к локальному неудобству отдельного пользователя на время использования.
Например, есть два требования:
 - логин должен быть уникальным,
 - выбор неуникального логина должен подсвечиваться красным при вводе.
Нарушение первого требования ломает всю систему и обладает куммулятивным эффектом: добавление дубля логина ломает то, что до этого работало без сбоев.
Нарушение второго требования доставляет неудобство отдельному пользователю и только на одной операции.
Записывание первого требования в виде операций над моделью позволяет:
во-первых, уменьшить вероятность того, что реализация этого требования будет нарушена при очередном изменении отображения
во-вторых, предоставляет простой способ контроля того, что требование реализовано - как через вычитку кода, так и через тесты.

6yrop

Для списков от 1000 элементов, ситуация обычно обратная.
10% элементов "материализовано" в виде View, а остальные 90% храняться только в виде модели.
а списки из 10^9 хранятся в базе. И что? Под моделью всё же подразумевается не хранилище. Конечно, для целей оптимизации может потребоваться кеширование данных в памяти и возможно на клиенте, но это совсем другая история, и сейчас не об этом совсем. К тому же это та самая преждевременная оптимизация, которая корень всех зол. Реально она требуется редко.
 

Есть куча сервисных функций (проверка на согласованность значений полей, проверка на уникальность, генерация списка для выбора и т.д. которые неудобно формулировать в терминах View. Громоздкость и необходимость частого переписывания появляется из-за того, что View содержит кучу вспомогательных часто меняющихся решений (группировка на экране, вспомогательные визуальные компоненты, анимация, "хаки" для обхода устройства вывода и т.д.)
Где здесь "business logic", а где "presentation logic"?
Разделение на business logic и presentation logic появляется из-за того, что разные требования обладают разной критичностью.
Допущенная ошибка в реализации business logic приводит к отказу всей системы.
Допущенная ошибка в реализации presentation logic приводит к локальному неудобству отдельного пользователя на время использования.
Например, есть два требования:
 - логин должен быть уникальным,
 - выбор неуникального логина должен подсвечиваться красным при вводе.
Нарушение первого требования ломает всю систему и обладает куммулятивным эффектом: добавление дубля логина ломает то, что до этого работало без сбоев.
Нарушение второго требования доставляет неудобство отдельному пользователю и только на одной операции.
Записывание первого требования в виде операций над моделью позволяет:
во-первых, уменьшить вероятность того, что реализация этого требования будет нарушена при очередном изменении отображения
во-вторых, предоставляет простой способ контроля того, что требование реализовано - как через вычитку кода, так и через тесты.
 

Это ты всё про модульность. Для модульности дополнительное mutable состояние не нужно. Модульность прекрасно делается без добавления mutable состояния.
Собственно вот ответ Хельсберга по поводу ООП:
 

Does the object-oriented paradigm create problems?
Anders: You know, it depends on what you group under the object-oriented paradigm. Polymorphism and encapsulation and inheritance are as such not a problem, although functional languages typically have a different view of how you do polymorphism with their algebraic data types. Aside from that, I think the biggest problem typically with object-oriented programming is that people do their object-oriented programming in a very imperative manner where objects encapsulate mutable state and you call methods or send messages to objects that cause them to modify themselves unbeknownst to other people that are referencing these objects. Now you end up with side effects that surprise you that you can't analyze.
In that sense object-oriented programming is a problem, but you could do object-oriented programming with immutable objects. Then you wouldn't have these same problems. That's kind of what functional programming languages are doing, for example.
http://broadcast.oreilly.com/2009/04/an-interview-with-ander...
 

6yrop

Для списков от 1000 элементов, ситуация обычно обратная.
10% элементов "материализовано" в виде View, а остальные 90% храняться только в виде модели.
Можешь продемонстрировать на примере?
Вот тут 1000 элементов, можешь показать лучшую производительность?

6yrop

О модели часто говорят как о single source of truth [1, 2]. Если быть честным, то для пользователя источник истины это экран и устройства ввода, с которыми пользователь взаимодействует. Браузер это представляет в виде DOM элементов. Поэтому более честно источник истины это DOM элементы. Всё остальное это всего лишь приемы, которые нацелены на упрощение написания и развития кода.
Отсюда получаем, если язык позволяет создавать мощные инструменты для обработки кода, то многие приемы программирования становятся неактуальными.

luna89

Тут возник вопрос, а зачем вообще mutable Model? 90 процентов изменяемого состояния по-любому находится в UI элементах.
UI элементы с состоянием - зло. UI элемент должен быть просто функцией данные -> картинка, соответственно дерево UI элементов - деревом вызовов функций.

SCIF32

При любом выборе технологий стоит плясать от задачи, а не от абстрактных рассуждений.
Такое ощущение, что ты хочешь не понять, что такое MVC и в каких ситуация его хорошо использовать, а доказываешь, что MVC - говно в абстрактном понимании.
Кажется, если зафиксировать задачу, то всё встанет на свои места.
Например, написание форума.
Профит отделения controller от mv в том, что ты получаешь свободу в клепании представлений и модульность в этом месте - берешь и левой пяткой делаешь 10 режимов просмотра форума - и лайт и супер-лайт и обычный и под мобилки и xml для упоротых.
Профит отделения model от view начинается там, где суть задачи лежит в изменяемом состоянии. Если на мнгновение остановить все транзакции, то очевидно, что состояние форума определяется данными, а не тем, как они сейчас отображены на экранах юрезов. То есть первая инстанция правды - это таки база, плюс висящие транзакции (опять же база) плюс механизмы синхронизации данных, кеширования и т.п. - это и есть model. Ее удобно отделять чисто инструментально как минимум (субд + memcached + dom).
Всё что лежит между моделью и представлением - логика обработки. Её отделение тоже удобно, поскольку содержит много однотипных действий - дернули что-то из базы, записали в структурку, передали в представление. Получили данные из формы, прочекали поля, обработали как-нибудь, снова дернули из базы, снова предали в представление.
Это сложно описать как в абстрактном стиле (в котором пишешь ты) так и в стиле фигак-фигак (в котором попытался написать я. Проще взять несколько простых mvc- проектов, типа форума, или любого другого сайта с несложной бизнес-логикой.

SCIF32

Условно говоря, если долго приводить примеры в которых хорош MVC тебе придется этот MVC и переизобрести.
Еще ты не рассматриваешь проблему разделения труда при большом количестве простых заказов. Разрабобтка model - одна задача, близкая к субд.
Controller - верстка и в зависимости от сложности js + немного логики на языке шалонов.
А view в простейшем случае - примитивное кодерство.

6yrop

такое ощущение, что ты позавчерашний студент, не разработал ни одного промышленного проекта, и выучил одну фразу "in dependence", которая обладает нулевой информативностью, как и весь твой пост

6yrop

UI элементы с состоянием - зло.
Зло или нет, но это API браузера. Это реальность. Пару лет назад я писал о том, что было бы не плохо иметь UI каркас без состояния, но на сегодняшний день API браузера такое какое есть. И судя по неспешным темпам развития, в ближайшее десятилетие мало что поменяется.
 
данные -> картинка
Да, именно это и делает браузер. Переводит данные (представленные DOM-ом) в изображение на экране и сигналы от устройств ввода.
Зачем еще высасывать из пальца еще какие-то "данные" под названием Model?
Кстати, DOM это же Document Object Model зачем высасывать из пальца еще какую-то Model? А потом для новой модели выстроим еще Model2 и так для удобства программирования сделаем M1..Mn моделей, и будет нам счастье. :smirk:

6yrop

Еще ты не рассматриваешь проблему разделения труда при большом количестве простых заказов. Разрабобтка model - одна задача, близкая к субд.
Controller - верстка и в зависимости от сложности js + немного логики на языке шалонов.
А view в простейшем случае - примитивное кодерство.
Я работал и с вертикальным и с горизонтальным разделением труда, и могу сравнить эффективность обеих схем. Горизонтальная схема проигрывает в разы. Такая неэффективность по карману только жирным компаниям, которым плевать на эффективность.

Anna551

такое ощущение, что ты позавчерашний студент, не разработал ни одного промышленного проекта
А ты не допускаешь мысли, что ты разрабатываешь несколько однотипные "промышленные" проекты и на основе этого оцениваешь всю программную разработку?
Разработка сайтика и мобильного приложеньица, конечно не то же самое, что разработка и интеграция солидного банковского софта, но я бы не стал утверждать, что подходы, используемые в одном - православные, а в другом - неправославные.
Все эти MVC возникали из-за специфики решаемых им задач - как правило, основанных на высочайшей изменчивости требований. Основным достоинством MVC-основанных подходов (навроде того же самого PureMVC) является то, что можно десятком программистов совершенно различной квалификации срать в код на протяжении пары лет и у тебя останется возможность не слишком болезненно, когда ты заработаешь своим кодом денег, переделать все на хорошо.

6yrop

PureMVC
можно точную ссылку, гугл много разного выдает

luna89

Зло или нет, но это API браузера. Это реальность. Пару лет назад я писал о том, что было бы не плохо иметь UI каркас без состояния, но на сегодняшний день API браузера такое какое есть.
Я сейчас использую react.js, он позволяет кодить как будто retained DOM не существует. Конечно, лишний слой абстракции, но на практике работает хорошо, API простой - основа штук 5 функций, производительность получается даже лучше чем если руками DOM ковырять.

Anna551

краткое вики-описание вполне описывает происходящее. Это несколько большее дробление от MVC на пять уровней
Model Entities - Proxies - Commands - Mediators - View Objets
в Proxy - собственно и реализуется Mutable Model, если в контексте данного разговора.
Подход неплохой, хотя и не лишенный довольно страшных недостатков, но свои задачи решает на отлично.

6yrop

как будто retained DOM не существует
Здесь ты обманываешь, выдаешь желаемое за действительное. Вот манипулирование DOM-ом напрямую http://github.com/tastejs/todomvc/blob/master/examples/reac...

6yrop

 
... introduces a Publish/subscribe-style Observer notification scheme. This allows asynchronous, event-driven communications between the actors of the system, and also promotes a loose coupling between those actors, since the subscriber never needs to have direct knowledge of the publisher.

Выкинул я как-то такую херотень из проекта, жизнь на проекте стала проще.

luna89

Вот манипулирование DOM-ом напрямую http://github.com/tastejs/todomvc/blob/master/examples/reac...
Надо использовать атрибут autofocus:
http://jsfiddle.net/4tL94jju/

6yrop

Надо использовать атрибут autofocus:
Ты демонстрируешь, что код на React.js читается не очень хорошо. Ты не понял, что делает строчка, на которую я дал ссылку. Эта строчка в обработчике двойного клика мышки по элементу todo листа. А там autofocus не к месту. При чтении кода на TypeScript+Razor такую ошибку не сделаешь — нажимаешь горячие клавиши для go to definition и find usages и всё элементарно читается.

luna89

Эта строчка в обработчике двойного клика мышки по элементу todo листа. А там autofocus не к месту.
Я подумал, что там по клику появляется инпут, и при его появлении на него должен сразу фокус ставиться. Для этого атрибут autofocus нужен. Что я неправильно понял?

6yrop

PureMVC
Посмотрел пример на C#+WPF http://github.com/PureMVC/puremvc-csharp-demo-wpf-employeea...
Это же просто классика архитектурного говна.
120 строк кода:
 
  
\View\Components\UserList.xaml
<ListView ... SelectionChanged="userList_SelectionChanged"

\View\Components\UserList.xaml.cs
private void userList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
UpdateButtons;
SetSelectUser;
}

/// <summary>
///
/// </summary>
protected virtual void SetSelectUser
{
OnSelectUser(new EventArgs;
}

/// <summary>
/// The select user event
/// </summary>
public event EventHandler SelectUser;

/// <summary>
/// Fires the select user event
/// </summary>
/// <param name="args">The arguments for the event</param>
protected virtual void OnSelectUser(EventArgs args)
{
if (SelectUser != null) SelectUser(this, args);
}

\View\UserListMediator.cs
public UserListMediator(UserList userList)
: base(NAME, userList)
{
userList.NewUser += new EventHandler(userList_NewUser);
userList.DeleteUser += new EventHandler(userList_DeleteUser);
userList.SelectUser += new EventHandler(userList_SelectUser);
}

private UserList UserList
{
get { return (UserList) ViewComponent; }
}

void userList_SelectUser(object sender, EventArgs e)
{
SendNotification(ApplicationFacade.USER_SELECTED, UserList.SelectedUser);
}

\View\UserFormMediator.cs
public override IList<string> ListNotificationInterests
{
IList<string> list = new List<string>
list.Add(ApplicationFacade.NEW_USER);
list.Add(ApplicationFacade.USER_DELETED);
list.Add(ApplicationFacade.USER_SELECTED);
return list;
}

private UserForm UserForm
{
get { return (UserForm) ViewComponent; }
}

public override void HandleNotification(INotification note)
{
UserVO user;

switch (note.Name)
{
case ApplicationFacade.NEW_USER:
user = (UserVO) note.Body;
UserForm.ShowUser(user, UserFormMode.ADD);
break;

case ApplicationFacade.USER_DELETED:
UserForm.ClearForm;
break;

case ApplicationFacade.USER_SELECTED:
user = (UserVO) note.Body;
UserForm.ShowUser(user, UserFormMode.EDIT);
break;

}
}

\View\Components\UserForm.xaml.cs
public void ShowUser(UserVO user, UserFormMode mode)
{
if (!CheckAccess
{
Dispatcher.BeginInvoke(new ShowUserDelegate(ShowUser new object[] { user, mode });
return;
}

m_mode = mode;

if (user == null)
{
ClearForm;
}
else
{
m_user = user;
formGrid.DataContext = user;
firstName.Text = user.FirstName;
lastName.Text = user.LastName;
email.Text = user.Email;
userName.Text = user.UserName;
password.Password = confirmPassword.Password = user != null ? user.Password : "";
department.SelectedItem = user.Department;
firstName.Focus;
UpdateButtons;
}
}
private delegate void ShowUserDelegate(UserVO user, UserFormMode mode);

разбросаны по 5 файлам.
Зачем мне продераться через эти строчки, чтобы добраться до реальной бизнес логики, которая содержится в паре десятков строк кода:
 
 
<ListView ... SelectionChanged="userList_SelectionChanged"

if (user == null)
{
ClearForm;
}
else
{
m_user = user;
formGrid.DataContext = user;
firstName.Text = user.FirstName;
lastName.Text = user.LastName;
email.Text = user.Email;
userName.Text = user.UserName;
password.Password = confirmPassword.Password = user != null ? user.Password : "";
department.SelectedItem = user.Department;
firstName.Focus;
UpdateButtons;
}

Заказчик мне платит за реализацию бизнес-логики, а не за архитектурный кал.
P.S. И эти ужасные касты, буэээ....

6yrop

Я подумал, что там по клику появляется инпут, и при его появлении на него должен сразу фокус ставиться. Для этого атрибут autofocus нужен. Что я неправильно понял?
на странице уже есть другое поле с autofocus http://github.com/tastejs/todomvc/blob/master/examples/reac...

SCIF32

Я работал и с вертикальным и с горизонтальным разделением труда, и могу сравнить эффективность обеих схем. Горизонтальная схема проигрывает в разы. Такая неэффективность по карману только жирным компаниям, которым плевать на эффективность.
Конвеер - очевидно эффективный метод построения производственного процесса для большого количества бизнес-задач.
То, что ты пишешь лишь характеризует твою работу и тебя. А ты почему-то делаешь выводы про методы в целом, не желая взглянуть на всю картину.
Собственно та же история и с MVC.
Если у тебя не получается понять зачем это всё надо исходя из своего опыта, то значит тебе это пока всё и не нужно.

luna89

на странице уже есть другое поле с autofocus
Работает же все:
http://jsfiddle.net/4tL94jju/2/
Если считаешь, что это undefined behaviour, которое может сломаться в следующих версиях реакта, то напиши функцию focusOnRender и делай так:
 
 
render: ->
div {},
focusOnRender input placeholder: 'What need to be done?'

Императивная работа с DOM будет заключена в маленькой универсальной функции.

luna89

разбросаны по 5 файлам.

На js так не пишут кстати, потому что надоедает ходить по десяткам файлов без IDE. В результате ценится чтобы отдельный модуль был в одном файле, в идеале вмещался в один экран.

6yrop

Конвеер - очевидно эффективный метод построения производственного процесса для большого количества бизнес-задач.
О :D . Дейкстра о таких как ты написал еще в 85 году:

Пока менеджеры рассматривают разработку программ как производственный процесс — так они и делают! — и выражают «производительность программиста» в «количестве строк кода в день» — так они и делают! — их интеллектуальные категории действительно неадекватны. На моих лекциях для программистов по программированию самой частой реакцией было «Какая жалость, что этого не слышит наш менеджер!»
http://www.beroal.in.ua/article/dijkstra/ewd920.html

6yrop

Императивная работа с DOM будет заключена в маленькой универсальной функции.
В этом мало хорошего. Кто ж будет помнить и передавать новобранцам подобные функции? Для DOM-а такой проблемы нет, поскольку производители браузеров и комьюнити уже хорошо наполнили Интернет инфой по API браузеров. Это как, лучше писать на SQL, чем на убогом HibernateQL.

luna89

В этом мало хорошего. Кто ж будет помнить и передавать новобранцам подобные функции? Для DOM-а такой проблемы нет, поскольку производители браузеров и комьюнити уже хорошо наполнили Интернет инфой по API браузеров.
Это все мелочи. Я считаю, что с появлением реакта написание простого GUI стало принципиально решенной задачей. Все, что раньше было в мейнстримном GUI - унылое имеративное говно, типа приведенного кода на WPF, где надо вызывать функцию UpdateButtons.

6yrop

что раньше было в мейнстримном GUI - унылое имеративное говно, типа приведенного кода на WPF, где надо вызывать функцию UpdateButtons.
Декларативщина есть во многих GUI каркасах, в том же WPF. Но реальные сценарии часто плохо ложатся в рамки декларативных каркасов.
В чем проблема вызвать UpdateXxx? Декларативные GUI каркасы реализуют Dataflow принцип, но на современном API браузеров преимущества этого принципа не такие значительные. Как правило, экран можно разбить на небольшое количество таких функций UpdateXxx. Код этих функций состоит из такого:
 
 
Y1 = F1(X1, ..., Xn);
Y2 = F2(X1, ..., Xn);

Потом чисто формально смотрим на этот код и идем в обработчики, которые срабатывают при изменении X1, ..., Xn и проставляем UpdateY1Y2. Это что большая проблема? Внесение новой или удаление формулы тоже не проблема, если есть точная навигация.

Anna551

Выкинул я как-то такую херотень из проекта, жизнь на проекте стала проще.

Мы ее тоже с удовольствием выкинули. Но Если бы ее там не было - проект бы просто не дожил до этапа, когда у нас появились ресурсы на такие удовольствия.

6yrop

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

Anna551

Без нее проект потребляет меньше девелоперских ресурсов.
На основе какого периода времени собрана статистика? Как это оценивалось?

6yrop

Чуть меньше года. Мнение разработчиков и отзывы заказчиков.

Anna551

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

6yrop

В результате ценится чтобы отдельный модуль был в одном файле, в идеале вмещался в один экран.
что есть модуль?

luna89

Как правило, экран можно разбить на небольшое количество таких функций UpdateXxx. Код этих функций состоит из такого:
...
Потом чисто формально смотрим на этот код и идем в обработчики, которые срабатывают при изменении X1, ..., Xn и проставляем UpdateY1Y2. Это что большая проблема?
Если это не считается проблемой, то что тогда вообще можно считать проблемой? Для кодирования каких-нибудь формочек, которым люди занимаются лет уже 30-40, это чудовищный уровень лишней сложности.
В реакте не нужны никакие функции UpdateXXX, при этом не используется никакой dataflow, frp и нет никакой магии, все тупо и процедурно.
Например, есть задача, что отображается список, по клику на кнопку какие-то элементы добавляются в список, другие удаляются, а остальные пересортировываются. Тебе с твоим подходом придется закодировать функцию, которая этим занимается. В реакте такая функция уже реализована, в самом общем виде.

6yrop

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

6yrop

Если это не считается проблемой, то что тогда вообще можно считать проблемой? Для кодирования каких-нибудь формочек, которым люди занимаются лет уже 30-40, это чудовищный уровень лишней сложности.
Настоящей проблемой является неоправданный рост сложности реализации очередных изменений. Часто системы делаются постепенно. И когда с точки зрения заказчика надо внести очередное не очень сложное изменение, а девелоперы выкатывают на это огромные оценки, вот это действительно проблема. Понятно, что заказчик часто отвлекается от реальных связей между элементами системы, и часто занижает сложность. Девелопер должен либо иметь большую голову, либо иметь возможность восстанавливать связи по коду.
React.js конечно же реализует dataflow, просто по определению dataflow.
Чудовищного уровня сложности в UpdateXxx конечно же нет. Там всё линейно. Усилия разработчика растут линейно по отношению к количеству связей. Неоправданный рост это когда нелинейный рост, часто, экспоненциальный.

luna89

Чудовищного уровня сложности в UpdateXxx конечно же нет. Там всё линейно.
Во-первых, тебе надо закодировать не только updateXxx, но и renderXxx. В реакте достаточно только renderXxx.
Во-вторых сложность кодирования функции renderXxx зависит от количества состояний линейно, а функция updateXxx - квадратично, так как она должна уметь переводить из любого состояния X в любое состояние Y.

Anna551

Чудовищного уровня сложности в UpdateXxx конечно же нет. Там всё линейно. Усилия разработчика растут линейно по отношению к количеству связей. Неоправданный рост это когда нелинейный рост, часто, экспоненциальный.
Твой опыт говорит тебе, что MVC-подобные подходы дают этот самый экспоненциальный рост.
Может быть дело в том, что вы неправильно его готовили? Потому что это в общем-то и есть основная цель таких подходов, оправдываемая, например, моим опытом - сохранение сходного темпа внесения изменений сходной сложности.
А какие паттерны построения решений используете вы? (Не говори, что не используете - потому что это будет значит, что не имея систематизации задач - вы не можете давать доверительные оценки на их реализацию)

kokoc88

90 процентов изменяемого состояния по-любому находится в UI элементах.
Я правильно понимаю, что в тредике предлагается парсить содержимое text box из редактируемой таблицы, чтобы подсчитать какой-нибудь total sum?

6yrop

Я правильно понимаю, что в тредике предлагается парсить содержимое text box из редактируемой таблицы, чтобы подсчитать какой-нибудь total sum?
Если есть способ посчитать total sum без парсинга, то можно и не парсить. Другими словами, парсить или нет к треду не имеет прямого отношения.
Чем функция парсинга такая особенная?

kokoc88

Если есть способ посчитать total sum без парсинга, то можно и не парсить. Другими словами, парсить или нет к треду не имеет прямого отношения.
Чем функция парсинга такая особенная?
Ещё раз. У меня таблица, в которой я редактирую цифры. При изменении цифры я пересчитываю сумму внизу таблицы. Ты предлагаешь для вычисления суммы парсить текст из всех ячеек этой таблицы?

6yrop

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

khachin

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

6yrop

а как можно НЕ парсить? арифметику на тексте реализовывать?

marat7256

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

6yrop

т.е. как я написал двумя постами выше, вопрос в кэше. А тут всё как обычно, преждевременную оптимизацию не делаем, если есть смысл, то делаем кэш.

6yrop

Во-первых, тебе надо закодировать не только updateXxx, но и renderXxx. В реакте достаточно только renderXxx.
Нет, и то и другое реализовывать не надо. Логика реализовывается в updateXxx. Методов renderXxx нет в том смысле, в котором они есть в реакте.
Во-вторых сложность кодирования функции renderXxx зависит от количества состояний линейно, а функция updateXxx - квадратично, так как она должна уметь переводить из любого состояния X в любое состояние Y.
Это сказки, такого нет. updateXxx линейны по количеству связей, как и renderXxx в реакте.
По большому счету единственное преимущество реакта в том, что надо вручную проставлять вызовы методов updateXxx. Подчеркну, что речь идет только о проставлении вызовов, сами методы ничуть не сложнее в реализации. Проставить вызовы не большая проблема. Не очень приятная, и ошибки дополнительные могут быть, но тем не менее проблема не большая, зато остаемся с родным DOM-ом.

khachin

а как можно НЕ парсить?

Например, иметь изначально массив слагаемых, а при изменении значения в одной ячейке исправлять один элемент массива и запускать пересчет. Возможность изменения значений предполагает наличие чего-то input-подобного.
Тут же и валидатор удобно применить. Всего к одному новому/изменяемому элементу.

6yrop

Поскольку речь идет о mutable данных (см. subj то text box-ы есть для каждого элемента, т.е. пользователь может менять любой элемент. И то что ты описываешь это и есть кэш для функции парсинга.

6yrop

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

6yrop

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

marat7256

В данном случае не делать подобную "оптимизацию" глупо. Не зависимо от количества элементов, кстати.

luna89

Табличка с суммой на реакте, если кому интересно:
http://jsfiddle.net/53ew71ee/
Разве это не прекрасно?

luna89

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

kokoc88

Табличка с суммой на реакте, если кому интересно:
Разве это не прекрасно?
Суммы без поддержки копеек? Прекрасно.

kokoc88

т.е. как я написал двумя постами выше, вопрос в кэше. А тут всё как обычно, преждевременную оптимизацию не делаем, если есть смысл, то делаем кэш.
Я правильно понимаю, что если та же таблица будет отображена в режиме read only, то мы пишем другой код суммирования, потому что предыдущий работает с text editor, а новый должен с text label?

luna89

Суммы без поддержки копеек? Прекрасно.
Это в валюте страны Джаваскриптии, там копеек нет, а NaN - валидное значение для суммы денег.

luna89

Я правильно понимаю, что если та же таблица будет отображена в режиме read only, то мы пишем другой код суммирования, потому что предыдущий работает с text editor, а новый должен с text label?
Нет, у тебя есть функция getProducts, которая возвращает данные - список продуктов с названиями и ценами. Бизнес-логика работает с данными через эту функцию. Эта функция будет реализована по-разному в readonly и не readonly режиме.
Это мне кажется больше похожим на FRP-стиль. В FRP input моделировался бы как Stream<String> - ленивый список строк. Ты можешь превратить Stream<String> в Stream<Integer> (точнее Stream<Optional<Integer>>>). Затем тебе надо превратить List<Stream<Integer>> в Stream<List<Integer>>. Это важный этап - на мой взгляд модель в MVC - это в большой степени бойлерплейт для ручной реализации такого рода комбинаторов. Затем ты превращаешь Stream<List<Integer>> в Stream<Integer> - сумму, и говоришь своей frp библиотеке, чтобы этот поток выводился в label с суммой.
По большому счету, MVC подход возник, когда в языках не было GC и функциональных фич, сейчас это фактически кэширование данных вручную.

kokoc88

Нет, у тебя есть функция getProducts, которая возвращает данные - список продуктов с названиями и ценами. Бизнес-логика работает с данными через эту функцию. Эта функция будет реализована по-разному в readonly и не readonly режиме.
Вопрос не к тебе, у тебя-то mutable model.

luna89

Вопрос не к тебе
Я понял, ответил за Шурика.

6yrop

В данном случае не делать подобную "оптимизацию" глупо. Не зависимо от количества элементов, кстати.
Обычно глупостью называют когда делают то, что можно не делать. А у тебя какое-то своё странное определение глупости. Вообще, прям печально такой догматизм читать в постах якобы ученого. :( Стыдно за российскую науку.

6yrop

Я правильно понимаю, что если та же таблица будет отображена в режиме read only, то мы пишем другой код суммирования, потому что предыдущий работает с text editor, а новый должен с text label?
Общий код выносится. В чём вопрос?
P.S. откуда данные то берутся в read only режиме?

6yrop

Я правильно понимаю, что если та же таблица будет отображена в режиме read only, то мы пишем другой код суммирования, потому что предыдущий работает с text editor, а новый должен с text label?
Интересна твоя логика, ты хочешь сказать, что шаринг кода между двумя сценариями text editor и text label неминуемо должен повлечь за собой использование mutable состояния?

Dasar

Вот тут 1000 элементов, можешь показать лучшую производительность?
Сделай, пожалуйста, пример, которые ближе к реальности.
Пусть он будет такой же сложный по отображению, как, например, список сообщений на форуме.
Требования:
каждое сообщение из двух ячеек
Одна ячейка фиксированного размера, другая - резиновая.
Впервой есть картинка фиксированного размера и несколько строк текста небольшого размера.
Во второй ячейке - рич-текст произвольной длины (используются изменения стиля текста и изображения произвольного размера, иногда небольшие таблички)

luna89

Facebook анонсировал React Native - библиотеку для написания нативных Android и IOS приложений на react.js.
http://www.progville.com/javascript/react-native-apps-react...
Как я понял, приложения пишутся на js. Js код возвращает дерево обычных джаваскриптовых объектов, у которых свойства соответствуют свойствам нативных виджетов. Дальше реакт делает diff старого дерева и нового, и применяет diff, вызывая API нативных виджетов.
Что думаете?

Ivan8209

> Facebook анонсировал React Native
...
> Что думаете?
Судя по названию, это ещё одна симуляция FRP.
---
"Прогресс науки обратно пропорционален числу выходящих журналов."

luna89

Судя по названию, это ещё одна симуляция FRP.
Нет, к FRP это отношения не имеет.

6yrop

Нет, к FRP это отношения не имеет.
Связь следующая. Reat.js это частный случай Dataflow. FRP тоже является частным случаем Dataflow.

6yrop

Оказывается то, о чем я написал в этом треде, описано даже wikipedia.
2, parseInt таки вызывается, да.

6yrop

Табличка с суммой на реакте, если кому интересно:http://jsfiddle.net/53ew71ee/Разве это не прекрасно?
Добавь еще Quantity и Subtotal=Quantity*Price в каждой строке. Интересно как у тебя будет выглядеть метод getTotal.
Будет ли выполнятся умножение Quantity*Price каждый раз для всех строк? Или будет оптимизация для этого?

luna89

Умножал бы каждый раз.

6yrop

реакт делает diff старого дерева и нового,
почему для этого нужен React.js, почему это не делает сам Chrome (и остальные)?

6yrop

почему для этого нужен React.js, почему это не делает сам Chrome (и остальные)?
подозреваю, что в общем случае алгоритм с diff-ами не прост. Поэтому его не встраивают в Chrome. Соответственно, Reat.js ждет такая же судьба как и других надстроек — дырявые абстракции начинают течь на реально более менее сложном проекте.

luna89

подозреваю, что в общем случае алгоритм с diff-ами не прост
В реакте используется абсолютно тупой алгоритм:
http://facebook.github.io/react/docs/reconciliation.html
почему для этого нужен React.js, почему это не делает сам Chrome (и остальные)?
Потому что это будет уже не html dom, а другое несовместимое API.

luna89

Reat.js ждет такая же судьба как и других надстроек — дырявые абстракции начинают течь на реально более менее сложном проекте.
Ты, кстати, в своей реализации todomvc использовал jquery - намного более дырявую и тормозную абстракцию чем react.

Dasar

Соответственно, Reat.js ждет такая же судьба как и других надстроек
sql, html, c#/java и т.д. - это же тоже всё настройки с дырявыми абстракциями. Но их же используют всё больше, а не всё меньше.
Оставить комментарий
Имя или ник:
Комментарий: