C# 如何编写易于理解(/可维护)的搜索函数?也许是以模块化的方式?
每次我看到一个搜索函数,它背后的代码都是一团糟。几百行,意大利面代码,几乎总是作为一个巨大的方法。一种编程语言(Java/C#/PHP/etc)被用来构造一个大型SQL查询。很多,很多如果其他的 一定有比这更优雅的方法吗?或者这就是使用RMDBS而不是平面数据结构时得到的结果 我愿意更多地了解这个话题,甚至买本书/亚当使用。如果可以,也可以使用ORM,这将使事情变得更容易。 实施细节取决于您的平台和体系结构,但以下是一些示例:C# 如何编写易于理解(/可维护)的搜索函数?也许是以模块化的方式?,c#,java,C#,Java,每次我看到一个搜索函数,它背后的代码都是一团糟。几百行,意大利面代码,几乎总是作为一个巨大的方法。一种编程语言(Java/C#/PHP/etc)被用来构造一个大型SQL查询。很多,很多如果其他的 一定有比这更优雅的方法吗?或者这就是使用RMDBS而不是平面数据结构时得到的结果 我愿意更多地了解这个话题,甚至买本书/亚当使用。如果可以,也可以使用ORM,这将使事情变得更容易。 实施细节取决于您的平台和体系结构,但以下是一些示例: 在我当前的项目中,我们使用了mausch提到的查询对象模式的简
CustomerCollection customers=CustomerController.Find(新的搜索条件(“名称”),“”);
如果需要多个搜索条件,则可以传递集合。在finder函数中,代码将在集合上循环,将当前值映射到SqlCommand对象中的适当参数
这种方法对我们来说效果相当好
*)“可配置实现”意味着我们已经创建了一个架构,当搜索对象被定义为抽象类时,这些抽象类只会定义接口,并包含一些通用的验证前和验证后。实际的搜索代码在单独的Decent类中实现;这使得我们能够快速创建一个“假数据层”,用于模拟一些单元测试的数据库。您看过Lucene项目()了吗?它的设计正是为了这个目的。其思想是您构建并维护一组易于搜索的索引。生命周期的工作原理如下:
SQL.select("column1", "column2")
.from("relation")
.where().valueEquals("column1", "hello")
.and().valueIsLargerThan("column2", 3)
.toSQL();
- 编写一组sql语句,对数据库的所有可搜索区域进行索引
- 对完整数据库运行它们,以创建数据的初始索引
- 每次数据更改时,更新这些索引
在hibernate工具套件中有一个名为hibernate search()的伟大项目,如果您使用hibernate作为ORM,它可以为您维护索引。我已经对这个想法做了一些修改(因为我之前确实必须实现类似的东西)我得出的结论是,有两种方法可以让它既能工作又特别容易维护。但在讨论这些之前,先来看看历史 1.为什么这个问题会存在 大多数搜索功能都基于从数据库中派生的算法和技术。SQL最初是在20世纪70年代早期开发的(),当时的编程是一种完全不同于今天的怪兽,因为每一个字节计数,每一个额外的函数调用都会在出色的性能和破产之间产生差异,代码是由在汇编中思考的人编写的……好吧,你明白了 问题在于,这些技术最初大部分都是在没有改变它们的情况下被带到现代世界的(为什么它们应该被改变,而不是修复一些未被破坏的东西),这意味着旧的范式也在悄然蔓延。还有一些情况下,原始算法由于某种原因被曲解了,你最终得到了你现在拥有的,比如。不过,这里需要强调一下,技术本身并不坏,通常只是遗留范例而已 2.问题的解决办法 我最终使用的解决方案是一个混合了和(已经由mausch链接)的系统。举个例子,如果我要创建一个实用的系统来构建SQL查询,它将如下所示:
SQL.select("column1", "column2")
.from("relation")
.where().valueEquals("column1", "hello")
.and().valueIsLargerThan("column2", 3)
.toSQL();
这样做的明显缺点是构建器模式有点过于冗长。好处是每个构建步骤(=方法)本质上都很小,例如.valueIsLargerThan(“a”,x)
可能只是返回columnName+“>=”+x代码>。这意味着它们很容易进行单元测试,最大的优点之一是它们可以很容易地从外部源(如XML/whatnot)生成,最值得注意的是,创建从SQL查询到Lucene查询的转换器相当容易(Lucene已经实现了自动化,这只是一个示例)
我宁愿使用但真正避免的第二种方法是,当构建器在运行时,它不是顺序安全的(除非您花费大量时间创建元数据帮助器类)。写一个例子比详细说明我的意思更容易,因此:
import static com.org.whatever.SQL.*;
query(select("column1", "column2"),
from("relation"),
where(valueEquals("column1", "hello"),
valueIsLargerThan("column2", 3)));
我确实认为静态导入是一个缺点,但除此之外,这似乎是我真正想要使用的东西。这是一个时代的问题!同意。NHibernate的ICriteria API让这一切变得简单(relat