我有一段解决了非常简单的问题的代码--它形成了两个日期,以便在网页上看起来更好看。看起来是这样的:
function formatDateRange(
days: { firstDay: string, lastDay: string }
): string {
let first, last;
first = dayjs(days.firstDay); //dayjs parses string that formatted like this "YYYY-MM-DD"
last = dayjs(days.lastDay); //and returns a wrapper for Date object
if (first.isSame(last, "date")) {
first = first.format("DD MMMM, YYYY")
last = ""
} else if (first.isSame(last, "month")) {
first = first.format("DD") + " ... "
last = last.format("DD, MMMM YYYY")
} else if (first.isSame(last, "year")) {
first = first.format("DD MMM") + " ... "
last = last.format("DD MMM, YYYY")
} else {
first = first.format("DD MMM, YYYY") + " ... "
last = last.format("DD MMM, YYYY")
}
return first + last
}我决定重构它,我得到了这个:
//adapter that allows to use objects and arrays in function-composition
//EDIT: was called "callable"
function pluckFrom<T extends {}>(obj: T) {
return (key: keyof T) => obj[key]
}
// a function for function-composition
// (same as compose from redux but order is reversed)
function pipe(...funcs: Function[]) {
return funcs.reduce((f1, f2) => (...args: any) => f2(f1(...args)))
}
//provides an interface to apply array of functions to array of data
function apply<A>(maps: Array<(a: A) => any>) {
return {to: (arr: A[]) => arr.map((item, index) => maps[index](item))}
}
//takes array of dates, wrapped in Dayjs object and returns
//true if they're all the same in terms of unit of time
function isSame([day1, ...rest]: Dayjs[]) {
return (unit: UnitType) => rest.every(day => day.isSame(day1, unit))
}
interface DateRange {
firstDay: string;
lastDay: string;
}
//EDIT: removed redundant "same_" prefix
const case_to_format_map = {
"date": ["DD MMMM, YYYY", " "],
"month": ["DD ...", "DD, MMMM YYYY"],
"year": ["DD MMM ... ", "DD MMM, YYYY"],
" ": ["DD MMM, YYYY ... ", "DD MMM, YYYY"]
}
type Case = keyof typeof case_to_format_map
//EDIT: slightly refactored
function formatDateRange({firstDay, lastDay}: DateRange): string {
const
getCase = (days: Dayjs[]) => (
(["date", "month", "year", " "] as UnitType[])
.filter(isSame(days))[0]
) as Case
,
makeFormatter = (f: string) => (d: Dayjs) => d.format(f)
,
getFormatters = pipe(
getCase,
pluckFrom(case_to_format_map),
formats => formats.map(makeFormatter)
)
,
days = [firstDay, lastDay].map(dayjs)
return apply(getFormatters(days)).to(days).join(" ")
}这是更多的代码,但我喜欢它,因为现在我有了4个额外的实用程序函数,它对我来说更易读。除此之外,我不确定我做得更好还是更糟。所以我有这样的问题:
你能读懂吗?
它是否与功能风格和最佳实践相一致?
我不确定是否需要扩展这段代码,但是如何使它更可扩展呢?
发布于 2021-05-13 00:19:33
我个人更喜欢第一个,但这是非常主观的。从第一次阅读代码的人,我可以浏览第一个版本,并对代码的内容有一个很好的了解。对于第二个版本,我看到了一堆抽象函数,需要更长的时间才能看到代码的实际功能。
虽然第二个版本有一些优点,但我不认为在这种情况下,它是值得的,除非你知道这段代码的未来,而我不知道。我想我想指出的一点是,只有在有充分理由的情况下,你才应该重新格式化你的代码。例如,您希望能够在运行时或从代码库的不同部分调用函数行为的某些部分。
https://codereview.stackexchange.com/questions/260674
复制相似问题