我已经构建了一个开源应用程序,我很想知道其他人如何处理客户特定的请求。保持应用程序简单对我来说很重要;我不是要为所有人创造一切。应用程序可能变得臃肿,复杂,并且几乎无法使用。但是,有一些客户特定的选项会很好(它不适用于所有客户)。例如......
假设我们有一个名为Server的域名实体。在UI中,我们让客户从服务器列表中进行选择。对于一家公司,按位置过滤服务器很有帮助(美国,德国,法国等)。添加像这样的服务器属性是很容易的:
public class Server
{
public Location Location { get; set; }
// other properties here
}
我担心的是,随着时间的推移,服务器可能会变得臃肿。即使我只添加位置,也不是所有客户都会关心该属性。
一种选择是允许用户定义的字段:
public class Server
{
public string UserField1 { get; set; }
public string UserField2 { get; set; }
public string UserField3 { get; set; }
// etc...
// other properties here
}
这是处理此问题的最佳方法吗?我不喜欢通过将所有东西都变成字符串来消除类型安全的事实。还有其他/更好的方法让人们处理这样的问题吗?是否有这样的设计模式?
答案 0 :(得分:2)
在我看来,这样的好设计模式是在数据库级别使用模式,然后在类级别使用基本继承。
CREATE TABLE dbo.A (
ColumnA INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
ColumnB VARCHAR(50),
ColumnC INT,
etc.
)
现在我们有一个客户需要一些特定的功能,所以让我们在不同的模式中创建这个表的扩展:
CREATE TABLE CustomerA.A (
ColumnA INT NOT NULL PRIMARY KEY,
Location VARCHAR(50)
)
但是现在我们有另一个客户需要以不同方式扩展它:
CREATE TABLE CustomerB.B (
ColumnA INT NOT NULL PRIMARY KEY,
DataCenterID INT
)
虽然字段可能不相关,但您明白了,所以现在我们需要在此构建客户特定的域模型:
public abstract class A
{
public int ColumnA { get; set; }
public string ColumnB { get; set; }
public int ColumnC { get; set; }
}
public class CustomerA_A : A
{
public string Location { get; set; }
}
public class CustomerB_A : A
{
public int DataCenterID { get; set; }
}
现在,当我们需要为客户A构建一些东西时,我们将构建他们的子类,并为他们的客户B构建,等等。
现在,仅供参考,这是一个非常动态的系统的开始。我之所以这么说是因为缺少的那部分,那还不是动态的,就是用户界面。有很多方法可以实现,但超出了这个问题的范围。这是你必须考虑的事情。我这样说是因为你管理界面的方式将决定你甚至知道如何构建哪个子类。
我希望这有所帮助。
答案 1 :(得分:1)
早期的常用方法是使用配置XML文件进行此类操作。但针对客户特定需求的编程需要围绕您的编程方式进行整体思考。有关类似问题,请参阅this answer。
答案 2 :(得分:1)
当然,它总是取决于您想要允许的自定义程度。在我们的产品中,我们使用户能够完全定义他们自己的实体,其中包含属性和关系。基本上,每个EntityObject,就像我们称之为实体一样,最终由一个值集合和一个描述其中值的元模型的引用组成。我们设计了自己的查询语言,允许我们查询数据库并使用可翻译为任何目标语言的表达式(尽管我们目前只执行SQL和.net)。
游戏不会在那里结束,你很快发现验证规则,权限,默认值等等必须具备。当然,所有这些都需要UI支持,至少对于元模型的执行而言。
所以它实际上取决于最终用户应该能够执行的调整量。我想在大多数情况下,如您所述,简单的用户字段就足够了。在这种情况下,我将提供单个字段并在其中存储JSON文本。在UI中,您可以提供至少一个允许结构和可扩展性的半体面的UI。
答案 3 :(得分:1)
选项1:说“不”。 : - )
虽然我开玩笑说(一半),但有一些道理。很多时候,开发人员通过允许一个或两个自定义功能开启自己的自定义功能,设置雪球运动。
当然,这必须是平衡的,听起来你可能在某种程度上这样做。但是如果你真的想保持你的应用程序简单,那么保持简单,避免添加这样的自定义。
选项2:继承。
如果您确实需要添加自定义,我将倾向于使用所有“标准”选项构建基类,然后构建包含客户特定优化的客户特定类。
例如:
public class Server
{
// all standard properties here
}
然后对于Joe's Pizza,你可以:
public class JoesPizzaServer : Server
{
public Location Location { get; set; }
}
这样做的另一个好处是,它允许您根据客户特定(或基础)模型建立您的演示文稿视图。
例如,在MVC中,您可以设置这样的视图模型,然后您可以为每个客户提供特定的视图。
例如,Bob's Burgers在基础模型上有自己的观点:
@model MyApp.Server
@* implement the base form *@
Joe's Pizza的观点将使用自定义模型:
@model MyApp.JoesPizza
@* implement the base form -- a partial view -- with addtional custom fields
MVC在支持这种模式方面做得非常好。如果您没有使用MVC(可能是WPF或Web窗体),仍然有办法利用部分“视图”文件来完成类似的事情。
当然,您的数据库可以(也可能应该)支持类似的继承模型。实体框架甚至支持这样的各种继承模型。
答案 4 :(得分:1)
我可能在这里错了,但看起来您希望使用相同的代码库处理不同版本的软件。我可以想到两种方法:
答案 5 :(得分:0)
我从Python接近我认为可以很好地工作听到的是字典。关键是你的字段名称,值是,errrrr ... value;)
在数据库中表示也很简单。