Size: a a a

2021 February 17

к

кана in Haskell
Vlad 0xd728c4a7cd55d8db
кстати, а как прод хаскелисты делают feature flags которые хотелось бы хранить во внешнем сторадже? много же сигнатур придется менять? а желательно по минимуму, неинвазивно, чтобы потом так же быстро подчистить. есть где примеры?
в глобальный ридер всего аппа добавить все флаги
источник

к

кана in Haskell
сигнатуры менять не нужно будет нигде
источник

V0

Vlad 0xd728c4a7cd55d... in Haskell
кана
в глобальный ридер всего аппа добавить все флаги
это значит оно будет читаться 1 раз при старте только? а если не хочется рестартовать?
источник

к

кана in Haskell
я так понимаю основной подход сейчас это

newtype App a = App (ReaderT AppEnv IO a)

а потом отдельные классы с проекциями на нужные куски, чтобы весь код в App не писать явно

и в AppEnv добавить все флаги, а потом удалить
источник

к

кана in Haskell
Vlad 0xd728c4a7cd55d8db
это значит оно будет читаться 1 раз при старте только? а если не хочется рестартовать?
ну тогда добавить функций, которые читают из внешнего стора, в ридере хранить хендлер стора, а потом удалить функции

сигнатуры в любом случае менять не нужно будет
источник

V0

Vlad 0xd728c4a7cd55d... in Haskell
кана
я так понимаю основной подход сейчас это

newtype App a = App (ReaderT AppEnv IO a)

а потом отдельные классы с проекциями на нужные куски, чтобы весь код в App не писать явно

и в AppEnv добавить все флаги, а потом удалить
ну я понимаю, что AppEnv это в стиле 12 факторов - что io, что окружение - забрать раз и все - вроде правильно, но надо рестартовать
источник

V0

Vlad 0xd728c4a7cd55d... in Haskell
кана
ну тогда добавить функций, которые читают из внешнего стора, в ридере хранить хендлер стора, а потом удалить функции

сигнатуры в любом случае менять не нужно будет
> ридере хранить хендлер стора
я не очень сварщик, где нибудь есть real world app с похожим?
источник

к

кана in Haskell
newtype App a = App (ReaderT AppEnv IO a)

data AppEnv = AppEnv
 { storageHandle :: DBConnectin
 , loggerHandle :: LoggerHandle
 }

getFromStorage :: DBConnection -> FeatureFlag -> IO Bool
log _ :: LoggerHandle -> String -> IO ()

data FeatureFlag = A | B | ...

class HasFeatureFlag m where
 getFlag :: FeatureFlag -> m Bool

class HasLog m where
 log :: String -> m ()

instance HasFeatureFlag App where
 getFlag flag = do
   handle <- asks storageHandle
   liftIO $ getFromStorage handle flag

instance HasLog App where
 log message = do
   handle <- asks loggerHandle
   liftIO $ log_ loggerHandle message

f :: (HasFeatureFlag m, HasLog m) => m ()
f = do
 a <- getFlag A
 when a do
   log "a"
источник

к

кана in Haskell
не уверен на самом деле что это актуальный подход, но насколько я вижу в чатике, так и есть
источник

V0

Vlad 0xd728c4a7cd55d... in Haskell
мм, спасибо за пример 👍, но тут как раз в сигнатуре f оно появляется. но если концептуализировать, то мне кажется этого не избежать, по сути некоторые куски изначально не делали io в рантайме, а тут внезапно начали делать
источник

к

кана in Haskell
ну в f тут общий класс для всех флагов, а не для каждого по классу
источник

к

кана in Haskell
и внутри HasFeatureFlag инстанса уже можно решать, какие-то флаги брать из дб, какие-то из ридера, какие-то из файла
источник

к

кана in Haskell
флаг не нужен - удаляется из FeatureFlag, удаляется в f getFlag и все, удалять HasFeatureFlag уже не обязательно (может там другие флаги еще нужны)
источник

к

кана in Haskell
вместо ReaderT IO можно взять RIO наверное, без понятия какое к нему отношение
источник

V0

Vlad 0xd728c4a7cd55d... in Haskell
я понимаю, что это работает на любое количество флагов, но тут вопрос в прецеденте, когда появляется первый - выходит надо закладывать или оставлять HasFeatureFlag на постоянку?
источник

к

кана in Haskell
ну, можно просто весь код писать в App, тогда не нужно
источник

V0

Vlad 0xd728c4a7cd55d... in Haskell
т.е. вроде звучит логично - код не делал io в рантайме некоторого участка, а тут начал, как тут иначе, другое дело, что подход в том, что на входах во все "чистые" участки надо ставить ридеры "на всякий"
источник

к

кана in Haskell
профит от этих всех HasDB/MonadDB в том, чтобы функция требовала только минимально необходимое число вещей, и можно было бы легко замокать только их, чтобы протестировать, а не весь App

так что очевидно когда добавляется какой-то эффект типа чтения флагов, он добавляется и убывает из сигнатуры
источник

V0

Vlad 0xd728c4a7cd55d... in Haskell
или даже так, что вы думаете про подход когда в даже самые чистые функции мы всегда прокидываем некий AppContext (почти всегда пустой, но если вдруг - там окажется что-то вычитанное из io из ближайшего по стеку ридера, где уже есть IO)
источник

к

кана in Haskell
в чистые функции наверное можно пробросить и явно аргументом, просто поднимая проверку на фичи выше в код, который точно в IO
источник