浅谈模块化架构
什么是模块化架构?让我们通过一个例子来了解它不是什么,并且
我们将努力改变它。到最后你可能会相信它
优点或这是对时间的巨大浪费。
这是我在工作中经历的一个成长心态的真实场景。姓名和详细信息
虽然是匿名的,但一个常见概念的现实世界示例应该很有趣
如果没有别的的话,通过。
要求以及如何找到它们
我们的网站有一个位于网站标题中的按钮。它显示有多少
用户已经离开了 V-Bucks,但也融入了一些业务逻辑:
- 如果这是他们第一次访问该网站,请打开一个弹出窗口来欢迎他们 并展示他们可以用 V-Bucks 做些什么
- 如果他们有
- 如果他们是基本用户,则显示一种样式的按钮;如果是 SuperDuper 用户,则显示 另一个更漂亮的按钮
等等。我们的产品经理和项目经理这样的例子还有很多
设计经理和 V-Bucks 集团董事梦想着我们需要
手柄。
实习生 Jimbo 的任务是实现这个,因为这只是一个
按钮!
他筛选了 Figma 设计的 15 种相互冲突的迭代。他发现
有多少个 PM,就在多少个单独的 Word 文档中包含这些要求。他组织并
与七个团队一起进行七次知识转移会议,以揭开
古老的专有知识知道哪些服务将提供他所需的数据
用于用户类型和 V-Bucks 数量。内容团队向他保证
所有字符串的最终版本将在年底获得法律和营销部门的批准
一周,这样,他就准备好构建这个按钮了。
黑客方法
这是他的 V-Bucks 按钮、弹出窗口和相关内容的第一次迭代
业务逻辑。
Jimbo 对他提出的简单目录结构感到满意:
/v-bucks-button ├── button.tsx ├── index.ts └── /v-bucks-popover │ ├── popover.tsx
所以他开始构建这个按钮,而且一开始很天真。
export const VBucksButton: React.FC<vbbprops> = ({ ... }) => { // Set up state const authConfig = { ... } const { user } = useAuth({ ...authConfig }) const { vBucks } = useGetVBucks({ user }) const { telemetry } = useTelemetry() const { t } = useTranslation('vBucksButton.content') const styles = useButtonStyles() // Derive some state via business logic const handleClick = () => { ... } const buttonText = vBucks === ERROR ? '--' : vBucks.toString(); // About 25 more lines of various button state, error handling, // conditional rendering, with comments throughout explaining // why we're showing or hiding something or other const popoverProps = { // About 200 lines of typical popover handling, // telemetry, business logic, content to display, etc } const tooltipProps = { // Another 100 lines of the same for tooltip } return ( <vbuckspopover trigger="{"> <button arialabel="{t('ariaLabel')}" classname="{`" about seven-hundred classnames for responsive design accessibility conditional premium styles et cetera onclick="{handleClick}"> {buttonText} </button> } /> ) } </vbuckspopover></vbbprops>
他已经实现了第一次尝试。 VBucksPopover 也有类似的复杂
业务逻辑、错误处理、状态管理、样式和注释
以运输名义的技术债务。
这个按钮只有不到 400 行,非常简单。即使弹出窗口是
另外500行意大利面条。真的是“清理”还是分裂
以任何方式使我们或我们的用户受益?这取决于。如果这就是我们所需要的
这个按钮,谁在乎呢。让我们继续前进吧!
但是两个月过去了,另一个产品团队的PM和设计师爱上了
您的按钮并希望将其放在应用程序的标题中。他们有一个简单列表,没有
来自他们的压力,他们希望你适应一些改变,如果
您可以在当天结束前给出 LT 的预计到达时间,那就太好了,谢谢:
- 更新按钮的样式并根据其显示的应用程序显示文本
- 每个应用程序显示一组完全不同的弹出窗口
- 当用户用完 V-Bucks 时,打开一个新的全公司范围内的标准追加销售模式, 但仅限于某些地区,并且仅限 16 岁的用户,并且仅限于 实验A组
Jimbo 能否将所有这些新功能塞进同一个组件中?
是的。拆分或重构会给用户带来好处还是给你的经理留下深刻印象?
不。但是在这种复杂程度上,重构有一些强有力的论据:
- 开发理智
- 当 Jimbo 因不重构而被 PIP 时取代他的开发人员的理智
- 更多次数,让你下次从一开始就做得更好
- 稍后写博客的内容
模块化架构方法
清洁守则倡导者和其他了解足够知识的肛门类型的道德
定期在 Stack Overflow 上回答,甚至你的祖父母也会看一些东西
像这样:
- KISS、DRY 和其他缩写毯子
- 关注点分离
- 原子性!脱钩!拟声词!
这些都很棒,有助于为 Jimbo 的下一次尝试提供信息。
之后他就没有被画中画了
所有,而且实际上还得到了提前交付和分享的促销
这么多的会议和文件。
但他现在更聪明了,学会了一种很酷的方法来实践这些格言。看起来
像这样的东西:
/v-bucks-button ├── button.tsx ├── index.ts └── /v-bucks-popover │ ├── popover.tsx
看起来像大量按钮和弹出框的样板。为什么会这样
更好吗?
这取决于。以下是 Jimbo 的简要概述及其基本原理:
- 将每个组件拆分为容器和渲染器
- 将状态和业务逻辑移入钩子
- 容器使用钩子并将任何道具传递给渲染器
- 渲染器只关心渲染它所提供的内容
- 通用功能、业务逻辑或常量可以存在于 utils 中
- 不同类型的单独文件;它们往往被导入到多个文件中并且 成为你无论如何都需要提取的循环依赖
- 提取的 TailwindCSS - 下面有更多内容
它无限可扩展!这些构建块不会被
分解
任意规则,例如代码行或“复杂性”。它们被分解为
目的:每个概念边界都有一个目的。
PM 要你制作 10 个新的爆米花?没问题——Jimbo 的架构可以
处理一下。
领导层希望在某些应用程序中获得更好的销售指标,但其他团队则不然
有资金建立遥测技术来支持这一点。伟大的!我们有
我们可以水平扩展以满足各种变化的遥测实用程序
要求。
彻底的重新设计意味着每个弹出窗口都需要显示不同的内容,
根据不同的条件。现在,通常要简单得多,因为所有
我们渲染的东西,以及我们用来渲染它的所有逻辑,都存在于明确定义的
中
块。它们不再混杂在一大堆冲突和逻辑中
链长 20 行。
这是此容器/渲染器模式的示例:
/v-bucks-button ├── button.tsx ├── index.ts └── /v-bucks-popover │ ├── popover.tsx
export const VBucksButton: React.FC<vbbprops> = ({ ... }) => { // Set up state const authConfig = { ... } const { user } = useAuth({ ...authConfig }) const { vBucks } = useGetVBucks({ user }) const { telemetry } = useTelemetry() const { t } = useTranslation('vBucksButton.content') const styles = useButtonStyles() // Derive some state via business logic const handleClick = () => { ... } const buttonText = vBucks === ERROR ? '--' : vBucks.toString(); // About 25 more lines of various button state, error handling, // conditional rendering, with comments throughout explaining // why we're showing or hiding something or other const popoverProps = { // About 200 lines of typical popover handling, // telemetry, business logic, content to display, etc } const tooltipProps = { // Another 100 lines of the same for tooltip } return ( <vbuckspopover trigger="{"> <button arialabel="{t('ariaLabel')}" classname="{`" about seven-hundred classnames for responsive design accessibility conditional premium styles et cetera onclick="{handleClick}"> {buttonText} </button> } /> ) } </vbuckspopover></vbbprops>
/vBucksButton ├── /hooks │ ├── index.ts │ └── useButtonState.hook.ts ├── /vBucksPopover │ ├── /app1Popover │ │ ├── /hooks │ │ │ ├── index.ts │ │ │ └── usePopoverState.hook.ts │ │ ├── ... │ ├── /app2Popover │ ├── index.ts │ ├── popover.renderer.tsx │ ├── popover.styles.ts │ ├── popover.tsx │ └── popover.types.ts ├── /utils │ ├── experimentation.util.ts │ ├── store.util.ts │ ├── telemetry.util.ts │ └── vBucks.businessLogic.util.ts ├── button.renderer.tsx ├── button.styles.ts ├── button.tsx ├── button.types.ts └── index.ts
旁白:TailwindCSS 文档明确建议不要使用 @apply 来提取这样的公共类。这导致包大小几乎为零差异,除了“你必须想出类名”之外没有其他差异。生产级 CSS 几乎总是有几十行那么长,乘以给定组件中需要样式化的元素数量。这种权衡在 90% 的情况下似乎都是值得的。
其余现有的和新的业务逻辑位于钩子和实用程序中!
这种新架构满足了狂热者的需求,并使事情更容易扩展或
删除或移动。
编写单元测试变得不那么痛苦,因为你已经有了明确的定义
边界。您的渲染器不再需要模拟十种不同的服务来
验证它是否在给定一些输入的情况下显示了一组闪光。你的钩子可以
单独测试它们是否符合您预期的业务逻辑。
你的整个状态层刚刚改变了吗?如果您的
中的代码那就太可惜了
钩子与使用它的代码紧密耦合,但现在它更简单
更改,您的渲染器仍然只是等待一些输入。
最后的想法
这种模块化架构添加了大量样板,最终可以提供
零利益。
如果您正在从事一个充满激情的项目或
,我实际上无法推荐它
优先考虑运输和提供价值。如果你有
的东西
似乎它的范围可能会随着时间的推移而扩大,或者您可能想要
在 POC 后进行彻底检修,有时可以减少技术债务。
您可以使用 Plop 等工具来生成此样板。
那么我从 Jimbo 的工作和模块化架构中真正学到了什么?
我们在学校和世界各地的 Well Ackshuallys 中学习的干净代码和缩写词
是一系列的一端。将功能性意大利面条代码组合在一起是另一回事
结束,并且通常效果很好,因为最终所有代码都是技术债。
最佳解决方案存在于某种量子态或这些末端的组合中,并且
我们选择的路径可能取决于:
- 我们有多关心我们正在构建的东西
- 管理层要求更新和预计到达时间的频率
- 读到这样的东西,一种方法恰好出现在你的 当你构建下一个东西时的意识
- 沮丧、痛苦
- 意大利面变成了性能瓶颈,你不得不重写它
- 样板文件变得如此枯燥,以至于你不得不偷工减料
以上是模块化 React 架构的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

简单JavaScript函数用于检查日期是否有效。 function isValidDate(s) { var bits = s.split('/'); var d = new Date(bits[2] '/' bits[1] '/' bits[0]); return !!(d && (d.getMonth() 1) == bits[1] && d.getDate() == Number(bits[0])); } //测试 var

本文探讨如何使用 jQuery 获取和设置 DOM 元素的内边距和外边距值,特别是元素外边距和内边距的具体位置。虽然可以使用 CSS 设置元素的内边距和外边距,但获取准确的值可能会比较棘手。 // 设置 $("div.header").css("margin","10px"); $("div.header").css("padding","10px"); 你可能会认为这段代码很

本文探讨了十个特殊的jQuery选项卡和手风琴。 选项卡和手风琴之间的关键区别在于其内容面板的显示和隐藏方式。让我们深入研究这十个示例。 相关文章:10个jQuery选项卡插件

发现十个杰出的jQuery插件,以提升您的网站的活力和视觉吸引力!这个精选的收藏品提供了不同的功能,从图像动画到交互式画廊。让我们探索这些强大的工具: 相关文章: 1

HTTP-Console是一个节点模块,可为您提供用于执行HTTP命令的命令行接口。不管您是否针对Web服务器,Web Serv

本教程向您展示了如何将自定义的Google搜索API集成到您的博客或网站中,提供了比标准WordPress主题搜索功能更精致的搜索体验。 令人惊讶的是简单!您将能够将搜索限制为Y

当div内容超出容器元素区域时,以下jQuery代码片段可用于添加滚动条。 (无演示,请直接复制到Firebug中) //D = document //W = window //$ = jQuery var contentArea = $(this), wintop = contentArea.scrollTop(), docheight = $(D).height(), winheight = $(W).height(), divheight = $('#c


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3汉化版
中文版,非常好用

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

Dreamweaver CS6
视觉化网页开发工具

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中