Я ищу мнения о том, как лучше всего достичь следующего. Его цель - от бэкэнда получить набор пользовательских данных, а затем на основе этих данных сконфигурировать объект текстов, который будет использоваться во внешнем интерфейсе. Я хочу, чтобы интерфейс был тупым и просто знал, что он должен отображать text.string
. Backend будет содержать логику c определения того, что показано.
Я начал с объекта, подобного этому:
const someData = {
hasBirthday: true,
subscriptionFee: 100
}
const text = {
welcome: (someData.hasBirthday) ? 'Happy birthday and welcome' : 'Welcome',
cost: (someData.subscriptionFee > 0) ? `Your subscription fee is ${someData.subscriptionFee}` : `Enjoy your free stuff`
}
Довольно просто, однако затем были введены некоторые дополнительные логи c. который требовал вложенных тернарных операторов, вот так:
const someData = {
hasBirthday: true,
subscriptionFee: 100
}
const text = {
welcome: (someData.hasBirthday)
? 'Happy birthday and welcome'
: (someData.subscriptionFee > 0)
? 'Welcome'
: 'Welcome, some custom message about your account being free',
cost: (someData.subscriptionFee > 0)
? `Your subscription fee is ${someData.subscriptionFee}`
: (someData.hasBirthday)
? `Enjoy your free stuff, you'll get a present on your birthday as well`
: 'You only get free stuff, we do not know when your birthday is'
}
Заметьте, что это лишь подмножество примера, конечно, я мог бы сделать if else
утверждений. Текст в значительной степени не имеет значения, но он служит цель в том, что она существенно отличается для каждой комбинации сравнений данных.
Теперь это довольно быстро запуталось, поэтому мне было интересно, если у кого-нибудь были мысли по поводу следующего предложения, чтобы сделать вещи немного чище:
const texts = {
welcome: [
{
comparator: (data) => data.hasBirthday,
value: () => 'Happy birthday and welcome'
},
{
comparator: (data) => !data.hasBirthday && someData.subscriptionFee > 0,
value: () => 'Welcome'
},
{
comparator: (data) => !data.hasBirthday && someData.subscriptionFee <= 0,
value: () => 'Welcome, some custom message about your account being free'
},
{
comparator: (data) => true,
value: () => 'This could act like an else conditional'
},
],
cost: [
{
comparator: (data) => data.subscriptionFee > 0,
value: (data) => `Your subscription fee is ${data.subscriptionFee}`
},
{
comparator: (data) => data.subscriptionFee <= 0 && someData.hasBirthday,
value: () => `Enjoy your free stuff, you'll get a present on your birthday as well`
},
{
comparator: (data) => data.subscriptionFee <= 0 && !someData.hasBirthday,
value: () => 'You only get free stuff, we do not know when your birthday is'
},
]
}
// using lodash
_.mapValues(texts, (text) => {
const matched = _.find(text, (t) => t.comparator(someData));
return (_.isFunction(_.get(matched, 'value'))) ? matched.value(someData) : null;
}),
Итак, теперь каждое значение имеет функцию компаратора, которая может иметь различные логики c, чтобы определить, должно ли оно отображаться. _.find будет искать рекурсивно по порядку, поэтому мы знаем, что приоритет отдается первому-последнему.
В любом случае, ищите критику в отношении вышеизложенного, если у кого-то есть какие-либо идеи. Спасибо.
Обновлено: Реализация шаблона Builder
Я не собираю другой экземпляр класса, просто возвращаю объект, но все та же идея:
class Builder {
constructor(data) {
this._data = data;
}
setWelcome() {
if (this._data.hasBirthday) {
this.welcome = 'Happy birthday and welcome'
} else if (this._data.subscriptionFee > 0) {
this.welcome = 'Welcome'
} else {
this.welcome = 'Welcome, some custom message about your account being free'
}
return this;
}
setCost () {
if (this._data.subscriptionFee > 0) {
this.cost = `Your subscription fee is ${this._data.subscriptionFee}`
} else if (this._data.hasBirthday) {
this.cost = `Enjoy your free stuff, you'll get a present on your birthday as well`
} else {
this.cost = 'You only get free stuff, we do not know when your birthday is'
}
return this;
}
create() {
return _.omit(this
.setWelcome()
.setCost(), '_data')
}
}
const object = new Builder({
hasBirthday: true,
subscriptionFee: 100
}).create();