LINUX.ORG.RU

Хранение состояния приложения

 


2

8

Ковыряю потихоньку Rust в свободное время, и возник вопрос. Как в расте принято хранить глобальное состояние приложения? Например, те же настройки.

Будет хорошо, если ткнете в пример кода, где можно посмотреть.

★★★★★
Ответ на: комментарий от deep-purple

Когда XML прочитан в DOMDocument, этот дом «оккупируют» модельки

Здесь ты меня потерял.

Нет:

Да. Я не понял ни процитированной фразы, ни дальнейшего.

Твой «main» знает о всех «модельках» на критичных уровнях

Нет. Он знает только компоненты верхнего уровня и поддеревья кофига, которые нужны этим компонентам. Что у компонентов внутри, main не заботится.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Почему «лишним»? Он просто вызывает конструктор и передает туда поддерево. Но это и всё.

Потому что перед тем как передать поддерево, он должен знать как его извлечь.

То есть все компоненты получают ссылку на весь конфиг, а используют только его часть. Вот это - отсутствие изоляции.

Прямой связи нет. Допустим у тебя доступ к поддереву по секретному имени, которое не реально подобрать. Тогда говорить про отсутствие изоляции нельзя.

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

Vit ★★★★★
()
Ответ на: комментарий от Vit

Я имел в виду, что если main должен обладать лишним знанием о компоненте, то это потенциальные проблемы с изоляцией

Почему «лишним»?

Потому что перед тем как передать поддерево, он должен знать как его извлечь.

Знание о том, как извлечь поддерево - это не знание о компоненте.

А я подразумевал скорее целостность и самодостаточность кода.

Я подразумевал модульность и отсутствие избыточности.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Он знает только компоненты верхнего уровня и поддеревья кофига, которые нужны этим компонентам

В моем варианте он знает только один компонент (для rootNode), только его удаляет, только ему передает верхушку конфига и не думает ни о каких поддеревьях и прочих компонентах. Это же хорошо и правильно?

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

В моем варианте он знает только один компонент (для rootNode), только его удаляет, только ему передает верхушку конфига и не думает ни о каких поддеревьях и прочих компонентах. Это же хорошо и правильно?

Ты просто передвинул всю сложность в «один компонент» (который, наверное, создает другие компоненты).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Ты просто передвинул всю сложность в «один компонент»

Но к этому и надо стремиться. Разделяй и властвуй.

который, наверное, создает другие компоненты

Я так и писал:

Все модельки от одного базового класса, + каждая умеет в свою специфичную задачу — создает новые вложенные модельки...

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Ты просто передвинул всю сложность в «один компонент»

Но к этому и надо стремиться. Разделяй и властвуй.

Ты ничего не разделил - у тебя компоненты (кроме корневого) всё равно создаются в одном месте. Я не вижу никаких отличий твоего «одного компонента» даже от моего main.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Знание о том, как извлечь поддерево - это не знание о компоненте.

Хм... спорное утверждение. Если это можно засунуть в компонент и не знать, то оно для main явно лишнее.

Я подразумевал модульность и отсутствие избыточности.

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

Vit ★★★★★
()
Ответ на: комментарий от Virtuos86

Что ж, уже неплохо. Для иммутабельных конфигов должно быть удобно.

Теперь нужно обеспечить возможность изменения конфига внутри самой программы. Ведь не руками же править JSON/XML файл с настройками, скажем, какой-нибудь игры. Изменение конфига будет делаться только в одном модуле (модуле настроек), а доступен на чтение он должен быть изо всех. Какое решение здесь предлагает Rust?

UPD: А, ну одно решение я знаю. Делать перезапуск программы после изменения настроек.

Crocodoom ★★★★★
()
Последнее исправление: Crocodoom (всего исправлений: 1)
Ответ на: комментарий от tailgunner

у тебя компоненты (кроме корневого) всё равно создаются в одном месте

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

Я не вижу никаких отличий твоего «одного компонента» даже от моего main

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

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

В одном, если разматывать цепочку вложенных конструкторов.

О чем и речь.

И не в одном, если смотреть с точки зрения делегирования задач разным классам.

Это какой-то маркетспик.

а мои компоненты только обслуживанием структуры стейта.

Они выполняют для этого больше работы, которая у меня вынесена в main.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

О чем и речь ... маркетспик

Мастер подмены ))

Они выполняют для этого больше работы, которая у меня вынесена в main

Таким образом твой main не может быть использован с другими компонентами, т.к. внутри него часть их работы. А мой может.

deep-purple ★★★★★
()
Ответ на: комментарий от Vit

Знание о том, как извлечь поддерево - это не знание о компоненте.

Хм... спорное утверждение. Если это можно засунуть в компонент и не знать, то оно для main явно лишнее.

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

Попробуй мысленный эксперимент: сможешь ли ты использовать свой компонент в другой программе, не меняя его? С толстым конфигом - нет.

Я подразумевал модульность и отсутствие избыточности.

А в чем проблема?

С твоим подходом компонент получает данные, которые ему не нужны. Это избыточность. Насчет модульности - см. мысленный эксперимент выше.

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

Таким образом юнит-тест тоже знает, какое поддерево кому нужно.

tailgunner ★★★★★
()
Ответ на: комментарий от deep-purple

маркетспик

Мастер подмены ))

Попробуй выражаться яснее.

Таким образом твой main не может быть использован с другими компонентами

Конечно. На то он и main.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Попробуй выражаться яснее

Ты указал «О чем и речь» на то, что не важно, т.к. делегирование задач (отвязка компонентов) важнее. Тем самым подменил важность одного и другого. Не пойму зачем.

На то он и main

Но он всего лишь пишет и читает стейт. Он не верхушка цепи. И я легко могу завести хоть тыщу таких «main"ов (с разными компонентами внутри), если понадобится. Да, уточним — мой „main“, в кавычках, чтобы было понятно, что это не Ъ main, о котором ты. Однако, его можно использовать и в том месте, о котором ты.

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от tailgunner

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

Давай для простоты считать, что в конфиге данные типа JSON, и нет потребности заморачиваться над кастомными типами. Для конфига это вполне разумное упрощение.

В твоем случае «толщина» заключается только в наличии префикса. От этого не должно быть особых проблем.

Что касается «компонент должен уметь извлекать» - нет, не должен. Предоставь с конфигом стандартные методы извлечения листа. Компоненту останется только их дернуть, передав префикс.

Попробуй мысленный эксперимент: сможешь ли ты использовать свой компонент в другой программе, не меняя его? С толстым конфигом - нет.

Это плохой эксперимент. Во-первых это не надо :). Во-вторых там где надо - это уже не компонент, а библиотека, где расклад совсем другой. Если у тебя библиотечный модуль должен сохранять стейты, то скорее всего что-то пошло совсем не так.

С твоим подходом компонент получает данные, которые ему не нужны. Это избыточность. Насчет модульности - см. мысленный эксперимент выше.

Он получает только класс конфига, не зная что внутри, и методы извлечения нужных данных. Тут нет избыточности.

Таким образом юнит-тест тоже знает, какое поддерево кому нужно.

Это к делу не относится. Что реально важно для юнит тестов - он не зависит от других данных, и для запуска не надо заполнять другие листья и глобальные переменные.

Vit ★★★★★
()
Последнее исправление: Vit (всего исправлений: 1)
Ответ на: комментарий от Vit

Дядь, а я у тебя не в игноре так случаем?

Хвостострел прав. И ты прав. Каждый по своему. Вы только никак не можете услышать друг друга.

deep-purple ★★★★★
()
Ответ на: комментарий от Vit

Давай для простоты считать, что в конфиге данные типа JSON, и нет потребности заморачиваться над кастомными типами. Для конфига это вполне разумное упрощение.

Это мало что меняет.

Попробуй мысленный эксперимент: сможешь ли ты использовать свой компонент в другой программе, не меняя его? С толстым конфигом - нет.

Это плохой эксперимент. Во-первых это не надо :).

Это тест на модульность. Если оно не надо - окей.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Это тест на модульность. Если оно не надо - окей.

Главное не путать модульность и нездоровую тягу к библиотекостроительству. На практике вбиваться в переносимость между приложениями - реально перебор, если ты не лепишь именно библиотеки.

Собственно, меня потому и интересовало, как организовывать «конфиги», чтобы не надорваться.

Vit ★★★★★
()
Ответ на: комментарий от deep-purple

что это за конфиг, где появляются новые поля?

Пользователь настраивает интерфейс под себя, создавая окна, в которые перетаскивает нужные вьюхи.

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

static mut VIEWS: Option<Vec<View>> = None;
...
unsafe { VIEWS = vec![Some(View::default(), View::default())] };
Выглядит так себе, но над этим можно поработать.

А если конфиг предполагает появление новых, непредусмотренных заранее, сущностей, то это сценарий, а не конфиг.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

предполагает появление ... то это сценарий, а не конфиг

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

deep-purple ★★★★★
()
Ответ на: комментарий от Vit

Собственно, меня потому и интересовало, как организовывать «конфиги», чтобы не надорваться.

Организовывать надо код. Организация конфига из этого вытекает.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Ты сказал ту же мысль другими словами, это не ответ на вопрос.

Vit ★★★★★
()

Срач дискуссия «Rust vs Python» таки началась...

ArkaDOSik ★★
()
Ответ на: комментарий от Crocodoom

Изменение конфига будет делаться только в одном модуле (модуле настроек), а доступен на чтение он должен быть изо всех. Какое решение здесь предлагает Rust?

Ты хочешь, чтобы конфиг был доступен на запись только из модуля настроек, а из других модулей только на чтение? Или что? Или модуль настроек и есть модуль с конфигом?

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Я хочу понять, можно ли решение с lazy_static! адаптировать к изменяемому конфигу. При этом можно считать, что есть только какое-то одно место, откуда конфиг могут изменять (однопоточно). Это и проще архитектурно, и безопаснее.

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

Crocodoom ★★★★★
()

Просто сделай реализацию некоего App и в нем храни состояния апрликухи. Или ты там упоролся по функциональщине?

deterok ★★★★★
()
Ответ на: комментарий от Crocodoom

Здесь поломаны возможности тестирования и переиспользования кода. Такие проблемы должны решаться при помощи инверсии зависимостей.

Nexmean
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.