Closed zerkalica closed 5 years ago
Ну, идеально было бы что-то типа такого:
@ $mol_mem
todos( patch? : Todo[] ) {
return this.$.$mol_http.resource( '/api/todos' ).json( patch ) as Todo[]
}
С оптимистичным интерфейсом тут есть проблема - как идентифицировать задачу. Ведь пока она не сохранена у неё нет серверного идентификатора. Лучше всего генерировать идентификатор на клиенте и на сервер слать уже по этому идентификатору api/todo/123
.
По замыслу, у меня uuid генерится на клиенте, а сервер свой подставляет после сохранения. Т.к. id может от базы зависеть.
Не всегда логику сохранения можно упрятать в todos, т.к. от контекста может зависеть.
Например, в случае редактирования другая логика сохранения на сервер:
class Service {
saveTodo(todo: Todo) {
this.$.todos = this.todos.map(
(t: ITodo) => t.id === todo.id
? new TodoModel(todo, this)
: t
)
fetch(`/api/todo/${todo.id}`, {
method: 'POST',
body: JSON.stringify(todo)
})
.then(toJson)
.then((updatedTodo: Todo) => {
this.$.todos = this.todos.map(
(t: ITodo) => t.id === todo.id
? new TodoModel(updatedTodo, this)
: t
)
})
}
}
У вас анемичная модель, что не очень удобно. Удобнее иметь умную модель:
class $my_domain extends $mol_object {
@ $mol_mem_key
todo( id : string ) {
return $my_todo.make({ id : ()=> id , domain : ()=> this })
}
@ $mol_mem_key
user( id : string ) {
return $my_user.make({ id : ()=> id , domain : ()=> this })
}
}
class $my_todo extends $mol_object {
@ $mol_mem
domain() {
return $my_domain.make()
}
@ $mol_mem
data( next? : any ) {
return this.$.$mol_http.resoutce( `/api/todo/${ this.id() }` ).json( next )
}
title( next? : string ) {
return this.data( next !== undefined ? { title : next } : undefined )
}
author() {
return this.domain().user( this.data().author )
}
}
$my_domain.make().todo(123).author().todos()[0].title( 'Do it!' )
В идеальном приложении норм, но хотелось бы и для анемичной. Если говно-апи уже готовое, не подразумевает сохранение одного todo и ничего с этим не сделать? А сохраняется там черт в ступе, помимо todo.
Контекстов может быть много и пихать их всех в модель это странно весьма. Должны быть инструменты для декомпозиции, а в rich-модели все в кучу.
Так для того и нужна умная модель, чтобы приложение не зависело от апи, а предоставляло единый и единообразный интерфейс.
Ваш domain похож на Repository, только модель ar. Потом не хотелось бы все сводить к ActiveRecord, в нем есть свои плюсы и минусы. Нарушить SRP и изгадить апи при поддержке проще.
Способов сохранить модель может быть много. На стороне апи может сохраняться только мешанина из моделей. Получается все эти случаи сохранения модели и знания о других моделях надо пихать в нее.
Что будет, если todo сохраняется только вместе с user, например.
PS: А не могли бы вы привести пример полноценного рабочего CRUD с коллекцией, по этому примеру сложно понять. И как ваш пример решает проблему с id, когда надо после сохранения с сервера его взять и заменить в коллекции.
И как ваш пример решает проблему с id, когда надо после сохранения с сервера его взять и заменить в коллекции.
Как я говорил, с "призрачными моделями" куча проблем, поэтому либо генерим айдишники на клиенте и тогда новые модели ничем не отличаются от загруженных, либо не кладём новые модели в одну пачку с существующими - храним их во вью в отдельной коллекции, а после сохранения они прибиваются и появляются в "загруженной коллекции".
А что там в круде не понятно? Вообще, да, давно пора запилить $mol_model с типовой реализацией.
Атомы накладывают определенные ограничения и вовсе не очевидно, как на них правильно CRUD сделать. Есть много нюансов, чтоб правильно работала реактивность.
Непонятно с тем же opCount из примера выше. Когда надо во время операций писать Saving... или Updating... в компоненте. Как сделать оптимистичное, неблокирующее сохранение. Можно ли работать в анемичном стиле с моделями без колбэков. А если работать в ActiveRecord стиле из самой коллекции todos, тогда как различать новый todo и старый todo, как понять что именно в коллекции обновилось.
Насколько я понимаю, атомы навязывают определенный архитектурный стиль, который может быть не всегда удобен для конкретной задачи или даже непригоден для использования с плохими бэкенд апи.
Поэтому хочется увидеть каноничный CRUD для атомов, хотя бы с некоторыми их этих кейсов, а дальше уже дискуссию от него строить.
Пример ограничения, создаем новый todo, createTodo - сработает по onClick.
class TodoRepository {
todos: Todo[]
createTodo(title: string) {
const todo = new Todo({title})
http.response('/api/todo').json({
method: 'PUT',
body: JSON.stringify(todo)
})
this.todos = this.todos.concat([todo])
}
}
Здесь this.todos = this.todos.concat([todo])
не выполнится никогда. А из кода это не очевидно. Т.е. этот стиль плохо живет с атомами.
А как в http правильно делать постобработку полученных данных? fetch -> нормализация -> запись в свойство. Ведь как только я вызываю .json(), выполнение прерывается.
Прерывается, а потом перезапускается, но уже не прерывается.
Я сейчас прорабатываю модель для работы с github api. Думаю оно отлично пойдёт как референсный CRUD. Пока без домена - вместо него потом будут контексты.
А что за контексты?
Который реестр для IoC. this.$
- вот это всё.
Запилил круд для дикого REST-API: https://github.com/eigenmethod/mol/tree/master/github
Много всего, а приложение готовое есть? Может лучше запилить простой, но эталонный пример, что б сравнить с тем же реактом? Тот же todomvc можно было на круде.
Очепятка? github/auth.ts
static token_uri() { return 'http://cors.hyoo.ru/https://github.com/login/oauth/access_token' }
В каком месте?
Откуда строка я знаю, где в ней опечатка?
два адреса подряд
Нет, это CORS Proxy.
Круто
А зачем scopes нужен?
habhub - не CRUD, примитивно слишком, todomvc лучше. Еще кстати, Tour of heroes, вполне каноничное приложение.
Чтобы запрашивать больше прав при необходимости.
Комментарии сейчас можно получать и добавлять, скоро добавлю, чтобы можно было редактировать (через модель уже сейчас можно, но я хочу в $mol_text добавить поддержку редактирования) и удалять - будет полный круд. Для todomvc пилить бэк не хочется.
Зачем полноценный бэк, mock какой-нить влепить на localStorage, вроде такого на fetch-mock.
Не люблю писать бесполезный код :-) Вот комментарии - полезная штука и можно увидеть как оно работает в бою, а не на моках. Я их потом сервисом сделаю типа Disqus, чтобы можно было любую страницу комментировать через гитхаб.
Что такого, что б мок написать в 150 строк. Он полезный, это ваш текущий todomvc бесполезный, т.к. в реальном приложении есть fetch и асинхронное сохранение через него с обработкой статусов, ошибок, retry и прочей фигней. Это важнее всего, а не то, что там реактивно обновляются свойства, это и mobx может не хуже.
Да и суть в том, что б сравнить с каким-то известным примером, а не с выдуманными вами задачами.
Какая разница, моки там реализуют бэкенд или не моки, код приложения одинаковый будет.
todomvc не мой, это http://todomvc.com/
Лента комментариев - вполне распространённый кейс.
В реальном приложении будет ещё CORS, авторизация, несколько десятков ошибок, задержки, кеширование. Всё это можно, конечно, сэмулировать, но всё-равно есть риск, что что-то не учтёшь. С реальным бэкендом все больные места видны сразу.
todomvc.com весьма общая спецификация, ваша реализация разве что для бенчей годится, но для демонстрации PoC - нет.
Все эти навороченные приложения с CORS ом, авторизацией должны быть, но это уже не простой вариант. Нужен minimal CRUD и хорошо, если он будет похож на привычный многим todomvc или toh.
Лента комментариев - вполне распространённый кейс.
Ну ок, а можно тогда глянуть аналоги из реакта, ангулара и вуя? Вот toh, например, есть на всех фреймворках: react, vue, angular2
toh, на мой взгляд, вообще непонятная хрень. Что это и зачем - не ясно. Вместо дизайна - каша-малаша. Я за понятные, реалистичные и полезные примеры. Чем комменты-то не устраивают?
Тем, что не сравнить с другими фреймворками, нет похожих реализаций. Когда архитектурный стиль сильно отличается, мне бы это помогло какие-то аналогии строить.
Может подкинуть им идею реализовать что-то полезное, а не заниматься ерундой? :-)
Я могу на mobx и react запилить, было бы тз. Можно еще запилить статью на хабр про полезность такой каноничной приложухи с тз, наверняка найдутся, кто в своем болоте запилит.
Ок, я запилю ТЗ, когда буду писать статью про $mol_chat.
Главное обосновать, что этих кейсов достаточно хотя бы для 70% задач, ведь toh тоже много кейсов показывает, хоть и пример искусственный.
Там есть:
CRUD на основе ActiveRecord это хорошо, но все-таки у вас нет соображений, как реализовать удобный CRUD с анемик подходом?
Когда не "земля копайся", а "экскаватор копай землю", это обычно проще для понимания, хоть и многословнее.
Так тоже самое же, только модель будет сервисом-синглтоном, а свойства будут принимать идентификаторы в качестве ключа.
У вас нет примеров, как в mol сделать такое без колбэков? Модуль http вроде как не поможет.