最近有人告诉我,一个正确的RESTful API应该为它接受和返回的资源表示定义一个模式.例如,XSD for XML和JSON Schema for JSON.
然而,在所有关于REST的书籍和文章中我都经历过,这似乎从未像现在这样突出,甚至提到过.
有人可以提供一些权威资源,以澄清我们是否应该在开发RESTful API时提供架构?
我正在寻找一个相当现代的项目,重点是单元测试.按照古老的格言"面向对象编程中的每个问题都可以通过引入新的间接层来解决"这个项目是多层间接的.副作用是相当数量的代码如下所示:
public bool IsOverdraft)
{
balanceProvider.IsOverdraft();
}
Run Code Online (Sandbox Code Playgroud)
现在,由于单元测试的重点和维护高代码覆盖率,每一段代码都有针对它编写的单元测试.因此,这个小方法将有三个单元测试.那些会检查:
更糟糕的是,使用的模拟框架(NMock2)接受了方法名称作为字符串文字,如下所示:
NMock2.Expect.Once.On(mockBalanceProvider)
.Method("IsOverdraft")
.Will(NMock2.Return.Value(false));
Run Code Online (Sandbox Code Playgroud)
这显然使"红色,绿色,重构"规则变为"红色,绿色,重构,重新测试,重新测试,重新测试".使用不同的模拟框架(如Moq)将有助于重构,但它需要扫描所有现有的单元测试.
处理这种情况的理想方法是什么?
A)保持较小级别的层,以便不再发生这些转发呼叫.
B)不要测试那些转发方法,因为它们不包含业务逻辑.出于覆盖的目的,使用ExcludeFromCodeCoverage属性标记它们.
C)仅在调用适当的方法时进行测试,而不检查返回值,异常等.
D)把它吸干,并继续写那些测试;)
查看MVC代码时,您经常会遇到如下代码片段:
return RedirectToAction("Index");
<li>@Html.ActionLink("Books", "Index", "Books")</li>
Run Code Online (Sandbox Code Playgroud)
其中控制器名称,控制器动作名称或视图名称作为硬编码字符串提供.这是一种常见的做法,但这是一种好习惯吗?毕竟,如果重命名控制器,并忘记重命名许多引用之一,您将得到运行时错误,而不是更优选的编译时错误.
您可以通过向BaseController添加静态Name属性来缓解该问题,然后使用如下代码(操作名称稍微难以完成).
<li>@Html.ActionLink("Books", "Index", BooksController.Name)</li>
Run Code Online (Sandbox Code Playgroud)
这个硬编码的东西应该被认为是一个较小的邪恶(不使用MVC).还是人们开发了一些实践来解决它?
无论何时使用EF代码创建应用程序,您都可以看到添加了以下web.config键:
<add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" />
Run Code Online (Sandbox Code Playgroud)
您可以很容易地看到它不包含特定于应用程序的信息.更改这些值不会影响应用程序的运行方式,因此我认为它必定是某种不必要的EF工件,可能是设计人员需要的.但是,如果完全删除此键,应用程序将在启动时抛出ConfigurationError.这把钥匙的真正目的是什么?
我经常使用WCF测试客户端.遗憾的是,此工具不按字母顺序排序,也不按"出现顺序"排序(在服务合同类中声明操作的顺序).如果有很多,这使得找到具体操作变得非常困难.
有没有办法强制WCF测试客户端,按字母顺序排序操作?默认排序来自哪里?
在我最近工作的一个项目中,注意到一些接受属于层次结构的类的方法具有类似于以下的代码:
public void Process(Animal animal) {
if(animal.GetType() == typeof(Dog)) {
Console.WriteLine("We have a dog");
}
else {
Console.WriteLine("not a dog");
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,这让我感到公然违反了LSP,因为现在如果你使用狗的子类,无论是在生产代码,单元测试模拟,还是作为依赖注入拦截器的一部分,这个代码将不会以相同的方式工作.我相信通过将条件更改为:可以轻松修复此特定方案:
if (animal is Dog)
Run Code Online (Sandbox Code Playgroud)
这让我想到了:
是否有任何其他缺陷可以破坏客户端代码中的LSP?
UPDATE
只是为了澄清,我正在寻找在层次结构中使用类的代码中可能存在的缺陷.我知道并且我不是在寻找严重受限制的层次结构的问题 - (例如矩形 - 方形问题).我试图找出要查找的内容,以确保代码将支持动态模拟,拦截器,装饰类(例如LoggingDog),就像处理原始类一样.
通过答案和链接到目前为止,我可以看到唯一的缺陷是直接使用类的类型 - 即GetType()
直接使用方法或通过其他技术.尽管这里有一些注释is
和as
运算符,甚至在这种情况下转换为基类型也不会破坏LSP,因为子类将以与原始类相同的方式进行评估.
.net c# types dependency-injection liskov-substitution-principle
所以我正在使用 autofac 在 ASP.NET MVC 4 中编写一个高级单元测试。
所以我有一个示例控制器:
public class SomeController
{
[SomeFilter]
public ActionResult SomeAction()
{
SomeCode();
}
}
Run Code Online (Sandbox Code Playgroud)
我可以编写一个示例测试:
[Test]
public void Test()
{
var controller = new SomeController();
var result = controller.SomeAction();
// Asserts go here
}
Run Code Online (Sandbox Code Playgroud)
如果我伪造了所有外部依赖项,那么一切都很好。但是,还有一些通过 filter 属性附加的代码我想运行(这对这个测试很重要,我不想单独测试它)。
此代码将在应用程序中运行时执行,但如果在测试中运行则不会执行。我是否手动新建控制器或使用 DependencyResolver 检索它并不重要:
var someController = DependencyResolver.Current.GetService<SomeController>();
Run Code Online (Sandbox Code Playgroud)
这显然是因为在正常运行时框架会正确创建和附加这些过滤器。
所以问题是 - 我如何在测试中复制这种行为并执行这些动作过滤器?
我是这项技术的新手,我很难找到这个基本问题的答案.是否广泛采用了键集,列族和列名的命名约定,例如
我正在看的项目是使用alllowercase,所以我想知道它背后是否有原因.
有时在处理应用程序时,特别是在尝试遵循正确的OOD和DDD模式时,我们最终会使用域类,例如Customer
.然后我们有一些存储库将加载这个对象,一切都很好,干净.
然后应用程序变得越来越复杂,我们开始优化性能.我们经常发现自己处于这样的情况,我们并不真正需要加载完整Customer
对象的列表,但可能只是ID和名称,或者一小部分属性(例如,在网格中显示)
我经常看到的解决方案包括:
欠载域对象,所以基本上我们仍然会使用Customer
类,但是我们将使用单独的存储库方法来加载那些,并且该存储库方法将从数据库仅加载必需的字段,并填充对象中的相应属性.剩余的Customer
字段将保持默认值.这是一个简单的解决方案,但如果开发人员(或现有代码)希望加载某些属性,则可能导致许多错误.
目的,分级,我们创建类,如CustomerIdName
,CustomerInfo
,CustomerHeader
只包含我们需要的属性.这种方法可以创建大量的类,但仔细的子类化是可行的.但它似乎从无处不在的领域语言概念中解脱出来.
那么在DDD世界中是否有一些普遍认同的惯例来处理这些问题?我试图谷歌这个,但无法找到任何权威.
或者它可能只是传统DDD方法的一个众所周知的限制,而CQRS或其他方法在这些情况下会更好?
根据JSON API规范网站上的建议,我们应该使用JSON中用连字符分隔的所有小写成员名称:
URL安全命名成员的允许和推荐字符以规范格式定义.为了标准化成员名称,建议使用以下(更严格的)规则:
成员名称应该以字符"az"开头和结尾(U + 0061到U + 007A)成员名称应该只包含字符"az"(U + 0061到U + 007A),"0-9"(U + 0030)到U + 0039),连字符减去(U + 002D HYPHEN-MINUS," - ")作为多个单词之间的分隔符.
基本上,我们应该像这样使用JSON:
{
"first-name": "Jason",
"last-name": "Tough"
}
Run Code Online (Sandbox Code Playgroud)
难道不会让在JavaScript中访问这些属性变得很麻烦吗?或者任何其他编程语言,特别是如果我们想从JSON Schema生成类?
这个建议背后的动机是什么?
c# ×6
.net ×3
jsonschema ×2
rest ×2
unit-testing ×2
asp.net-mvc ×1
autofac ×1
bdd ×1
cassandra ×1
javascript ×1
json ×1
liskov-substitution-principle ×1
mocking ×1
oop ×1
schema ×1
tdd ×1
types ×1
wcf ×1
xsd ×1