我想知道是否有一种软件设计模式可以解决我面临的挑战。我有一个web应用程序,可以处理几种不同的用户角色类型,如SuperAdmin
、Admin
、Reseller
、Dealer
、Customer
、Volunteer
等
我们的React代码中充斥着if语句,这些语句检查一个人的角色以及决定";什么类型的ui组件;以呈现它们。这里有一个非常简单的例子:
// Container.js
<div>
<h1>Something</h1>
{['SuperAdmin', 'Admin'].includes(user.role) && (<input type="text" value="{record.first_name}" />)}
{['Reseller', 'Dealer'].includes(user.role) && (<span className="border-2">{record.first_name}</span>)}
{['Customer', 'Volunteer'].includes(user.role) && process.env.NETWORK_MODE === 'intranet' && (
<div className="bg-grey">
<span>Created at {record.create_at}</span>
<span>This customer wants to be anonymous</span>
</div>
)}
{['Reseller'].includes(user.role) && user.accountBalance > 0 && user.statementDate > (new Date()) && (
<div>Please pay your bills</div>
)}
</div>
上面的例子对我们来说很难管理,因为有100多个组件。当我们需要更改角色类型的访问权限或添加其他条件时,我们必须遍历每个组件并查找任何偏离的if语句。我们曾考虑过编写一些自动化测试,但觉得在实现之前,我们需要重构UI代码。
是否有一些软件工程设计模式与我的情况相关?如果是的话,只要说出名字,我就会读出来。
现在,我正在考虑这样一种方法:
// Container.js
<div>
<h1>Something</h1>
<Customer user={user} />
<BillNotice user={user} />
</div>
// Customer.js
const Customer = ({user}) => {
if(['Admin', 'SuperAdmin'].includes(user.role)) return <CustomerVersion1 />;
if(['Role', 'Role'].includes(user.role) && condition1 && condition2 ...etc...) return <CustomerVersion2 />;
if(['Role', 'Role'].includes(user.role) && condition1 && condition2 ...etc...) return <CustomerVersion3 />;
...etc...
}
const CustomerVersion1 = () => <Component />;
const CustomerVersion2 = () => <Component />;
const CustomerVersion3 = () => <Component />;
...etc...
// BillNotice.js
const BillNotice = ({user}) => {
if(['Admin', 'SuperAdmin'].includes(user.role)) return <BillNotice1 />;
if(['Role', 'Role'].includes(user.role) && condition1 && condition2 ...etc...) return <BillNotice2 />;
if(['Role', 'Role'].includes(user.role) && condition1 && condition2 ...etc...) return <BillNotice3 />;
...etc...
}
const BillNotice1 = () => <Component />;
const BillNotice2 = () => <Component />;
const BillNotice3 = () => <Component />;
基本上,我让每个组件负责决定它应该如何表现自己。然后,我可以通过模拟用户参数为每个组件编写单元测试,并查看是否返回了适当的组件。如果这种方法真的有名字的话,那就太好了,我可以在上面读到更多!
根据我的经验,对于如此多的条件,没有银弹,毕竟它是存在的,我们需要在某个地方实现它们,然而,如果IMO.设计得当,我们只能写一次(在一个地方管理(
对于这种情况,使用钩子可能是一种很好的做法。
- /挂钩
// control the logic in one place
const useAuthControl = (userRole, conditions) => {
// return as demand, maybe a more nested structure in the real world case
return {
isAdmin: ['Admin', 'SuperAdmin'].includes(userRole),
isRole: ['Role', 'Role'].includes(userRole) && condition1 && condition2 ...etc...,
isAnotherRole: ['Role', 'Role'].includes(userRole) && condition1 && condition2 ...etc...,
}
}
- /组件
// pass the condition dependencies if necessary
const { isAdmin, isRole, isAnotherRole, ... } = useAuthControl(userRole, ...condition);
// use for different components with a simpler method to write everywhere
return (
<>
{isAdmin && ...}
{isRole && ...}
{isAnotehrRole && ...}
</>
)
// other components as well
return (
<>
{isAdmin && ...}
{isRole && ...}
{isAnotehrRole && ...}
</>
)