文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

解读荷兰DigiD应用程序非常高效的代码重构

2024-11-30 20:47

关注

今天我在看到一个程序员发布了一个非常有趣的代码片段(非常高效的代码)。

这段代码像病毒一样传播开来,你可能已经在不同的平台上看到过它。

关于这个话题有许多争论。一些人认为有更短(也许也更好)的版本来做同样的工作。

例如,我请求ChatGPT重写一个更短的版本,得到如下结果:

是不是越短越好?

说实话,我对原版的反应是,什么鬼?我暗自发笑,认为我可以在5分钟内使用map或类似的巧妙技术对其进行重构。然而,喝了杯咖啡后,我又看了看代码片段。我发现意图非常明确,讽刺的是,map版本需要更多的时间阅读。

对于经验丰富的开发人员来说,较短的版本可能需要几秒钟才能弄清楚发生了什么。如果代码是几周前编写的,嗯,可能需要多花几分钟时间才能理解。

原始代码有什么问题?

尽管第一个版本的代码看起来简单明了,但它有一个缺点,就是不能将表示和业务逻辑结合起来。软件被设计为具有灵活性和适应性,这个版本的代码使得将来更难进行更改。

说它混合了表现和逻辑,我的意思是,如果明天我们想显示一个红点(而不是蓝色的),我们必须修改相当多的地方。

除此之外,我想先解决一个与逻辑泄漏有关的小问题。你可能已经注意到,它多次重复precentage> x &&precentage<= y,我将提取一个函数,使其更具可读性:

const isPercentageInRange = (number: number, low: number, high: number) =>
number > low && number <= high;

如果我将百分比检查分成两个函数,并将蓝色和白色的点画在两个函数中,并将结果安排在新的getPercentageRounds中,代码将如下所示:

const getBandByPercentage = (percentage: number) => {
if (percentage === 0) return 0;

if (isPercentageInRange(percentage, 0.0, 0.1)) return 1;
if (isPercentageInRange(percentage, 0.1, 0.2)) return 2;
if (isPercentageInRange(percentage, 0.2, 0.3)) return 3;
if (isPercentageInRange(percentage, 0.3, 0.4)) return 4;
if (isPercentageInRange(percentage, 0.4, 0.5)) return 5;
if (isPercentageInRange(percentage, 0.5, 0.6)) return 6;
if (isPercentageInRange(percentage, 0.6, 0.7)) return 7;
if (isPercentageInRange(percentage, 0.7, 0.8)) return 8;
if (isPercentageInRange(percentage, 0.8, 0.9)) return 9;
return 10;
};

const drawProgress = (percentage: number) => {
const band = getBandByPercentage(percentage);
return new Array(10).fill("", 0, band).fill("⚪", band, 10);
};

const getPercentageRounds = (percentage: number) => {
return drawProgress(percentage).join("")
}

函数getBandByPercentage将百分比映射到一个范围(或级别),而drawProgress根据范围绘制圆点。

让演示更加灵活。

我们可以提取蓝白色的点作为参数,让进度条更加灵活。此外,为了保持当前行为,我们可以使用当前值作为默认值:

const drawProgress = (
percentage: number,
done: string = "",
doing: string = "⚪"
) => {
const band = getBandByPercentage(percentage);
return new Array(10).fill(done, 0, band).fill(doing, band, 10);
};

然后可以在命令行中创建一个进度条,如下所示:

const getPercentageRounds = (percentage: number) => {
return drawProgress(0.3, '#', '=').join("")
}

如果想让进度条变宽,可以传入一个较长的版本字符串,表示“完成”和“正在做”:

const getPercentageRounds = (percentage: number) => {
return drawProgress(0.3, '##', '==').join("")
}

所以我们可以有不同的进度条,短的和长的,蓝色和红色的。

代码配置

重构之后,表示和逻辑被拆分。我不喜欢使用这么大的if-else语句块:

const getBandByPercentage = (percentage: number) => {
if (percentage === 0) return 0;

if (isPercentageInRange(percentage, 0.0, 0.1)) return 1;
if (isPercentageInRange(percentage, 0.1, 0.2)) return 2;
if (isPercentageInRange(percentage, 0.2, 0.3)) return 3;
if (isPercentageInRange(percentage, 0.3, 0.4)) return 4;
if (isPercentageInRange(percentage, 0.4, 0.5)) return 5;
if (isPercentageInRange(percentage, 0.5, 0.6)) return 6;
if (isPercentageInRange(percentage, 0.6, 0.7)) return 7;
if (isPercentageInRange(percentage, 0.7, 0.8)) return 8;
if (isPercentageInRange(percentage, 0.8, 0.9)) return 9;

return 10;
};

正如Martin Fowler的文章所讨论的,在某些情况下,将“代码”拆分到配置文件中是有益的。

我们可以将这个百分比移动到band mapping中,比如(甚至可以将bandConfig移动到JSON文件中):

const bandConfig: BandConfig[] = [
{
range: [-Infinity, 0.0],
band: 0,
},
{
range: [0.0, 0.1],
band: 1,
},
//...
];

然后getBandByPercentage可以简化为

const getBandByPercentage = (percentage: number) => {
const config = bandConfig.find((c) => {
const [low, high] = c.range;
return isPercentageInRange(percentage, low, high)
});

return config?.band;
};

随着复杂性转移到配置文件,getBandByPercentage函数只剩下几行了。

重用逻辑?

让我再演示一个用例来展示拆分可以带来什么。现在假设我们想在Web UI中使用进度条——例如ProgressBar组件。

导入drawProgress函数非常容易:

const ProgressBar = ({
percentage,
}: {
percentage: number;
done?: string;
doing?: string;
}) => {
return (
<>
{drawProgress(percentage).map((character) => (
<span>{character}span>
))}

);
};

在页面上,我们可以看到这样的内容:

我们可以轻松地更改组件中的句点字符,并使进度条更容易适应新的UI需求。

总结

最终的结果可能没有原始结果那么“高效”。尽管如此,通过明确的关注点分离(表示和业务逻辑,以及逻辑和配置),它可以对新需求做出更积极的响应。

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯