提问人:Rusurano 提问时间:7/26/2023 更新时间:7/28/2023 访问量:25
如何在ViewModel中遵循DRY原则?
How to follow the DRY principle in a ViewModel?
问:
在 MVVM 应用程序中,通常可以看到以下类型的 ViewModel:
import { nanoid } from 'nanoid';
import dayjs from 'dayjs';
export default function(entry) {
return {
id: entry.id,
title: entry.title,
slug: entry.slug,
category: entry.category,
summary: entry.summary,
content: entry.body,
type: entry.type,
video: entry.video,
duration: {
hours: entry.duration === null ? null : Math.floor(entry.duration / 60),
minutes: entry.duration === null ? null : entry.duration % 60
},
createdAt: dayjs(entry.createdAt),
updatedAt: dayjs(entry.updatedAt),
isHidden: entry.isHidden,
isDeleted: entry.isDeleted,
notes: entry.notes.map(item => ({ key: nanoid(), value: item.body })),
steps: entry.steps.map(item => ({ key: nanoid(), value: item.body, image: item.image })),
keywords: entry.keywords.map(item => ({ key: nanoid(), value: item.body })),
covers: entry.covers
}
}
如果未提供给此函数,我想返回默认(回退)值。当然,也可以将它们列在一个单独的对象中,并在不同情况下返回不同的对象:entry
import { nanoid } from 'nanoid';
import dayjs from 'dayjs';
export default function(entry) {
if(entry) {
return {
id: entry.id,
type: 0,
title: entry.title,
slug: entry.slug,
category: entry.category,
summary: entry.summary,
content: entry.body,
video: entry.video,
duration: {
hours: entry.duration === null ? null : Math.floor(entry.duration / 60),
minutes: entry.duration === null ? null : entry.duration % 60
},
createdAt: dayjs(entry.createdAt),
updatedAt: dayjs(entry.updatedAt),
isHidden: entry.isHidden,
isDeleted: entry.isDeleted,
notes: entry.notes.map(item => ({ key: nanoid(), value: item.body })),
steps: entry.steps.map(item => ({ key: nanoid(), value: item.body, image: item.image })),
keywords: entry.keywords.map(item => ({ key: nanoid(), value: item.body })),
covers: entry.covers
}
}
return {
id: null,
type: 0,
title: null,
slug: null,
category: null,
summary: null,
content: null,
type: null,
video: null,
duration: {
hours: null,
minutes: null
},
createdAt: dayjs(),
updatedAt: dayjs(),
isHidden: false,
isDeleted: false,
notes: [],
steps: [],
keywords: [],
covers: []
}
}
但是这样一来,我列出了两次所有键,这并不是真正的 DRY。
在这种情况下,保持 DRY 的清洁方法是什么?
答:
1赞
kca
7/28/2023
#1
从某种意义上说,您的代码是 DRY,因为您不会重复 type 的相同值。{ id, type, title, ... }
键存在重复,但对象的值不同。
不同类型
如果函数的返回类型是 ,那么你可以这样写:string | null
if( typeof entry === 'string' ){
return entry;
}
return null;
这是一个一致的返回类型 (),但该类型的 2 个不同值。这不是“重复”,即这是“DRY”。string | null
您的类型是 ,并且返回两个不同的值:{ id, type, title, ... }
{
id: 1,
type: 0,
title: 'first value'
}
的值与以下值不同:
{
id: 0,
type: 0,
title: null
}
因此,除了为该对象的每个单独属性设置正确的值外,别无他法。
但是,您可以做的是根据您必须定义的规则“生成”或“构造”这些单个属性的值。所以。。。
“细粒度”代码复制
如果对象变得如此之大,则避免代码重复是有意义的,这样,如有必要,不必在太多地方对对象结构进行更改。
但另一方面,以这种方式创建的对象可能会变得难以阅读,因此应仔细考虑这一点。
例如,以这种方式创建的对象可以消除很多重复,但很难理解:
{
id: 1,
...staticProperties(),
...flags(),
duration: createDuration().
}
你必须找到一个好的折衷方案。
静态空对象
无论如何,我假设您可能还需要在其他地方创建一个空对象。 我建议在某个地方创建一个空对象或空对象构造函数,并在需要时使用它,例如:
const emptyObject = {
id: null,
type: 0,
title: null,
// ...
steps: [],
keywords: [],
covers: []
};
并像这样使用它:
if(entry) {
return {
id: entry.id,
type: 0,
// ...
};
}
return {
...emptyObject,
createdAt: dayjs(),
updatedAt: dayjs(),
};
// or:
return createEmptyObject();
评论