小编Ken*_*ran的帖子

遗产代码梦魇

我继承了一个项目,其中类图非常像一盘意大利面上的蜘蛛网.在过去的两个月里,我写了大约300个单元测试,给自己一个覆盖主要可执行文件的安全网.

在任何特定时刻,我都可以访问我的敏捷开发书籍库:

  • 有效地使用遗留代码
  • 重构
  • 代码完成
  • C#中的敏捷原则模式和实践
  • 等等

问题是我触摸的一切似乎打破了别的东西.UI类混合了业务逻辑和数据库代码.许多类之间存在相互依赖关系.每次我改变任何其他课程时,都会有几个神课程.还有一个带有大约一半实例方法和半静态方法的突变单例/实用程序类(虽然具有讽刺意味的是静态方法依赖于实例而实例方法却没有).

我的前任甚至认为向后使用所有数据集会很聪明.每个数据库更新都作为存储过程中的参数直接发送到数据库服务器,然后手动刷新数据集,以便UI显示最新的更改.

我有时候会想到他们在处理代码之前会使用某种形式的弱混淆来保证工作安全或作为最后的告别.

是否有任何好的资源来解决这个烂摊子?我所拥有的书籍很有用,但似乎只涵盖了我遇到的一半场景.

refactoring legacy-code

25
推荐指数
3
解决办法
3115
查看次数

在Delphi中使用接口是否需要GUID?

官方文档说它们是可选的.我知道COM interop需要每个接口的唯一标识符,但我看到的每个接口示例都有一个GUID,无论它是否与COM一起使用?如果GUID不能与COM一起使用,是否有任何好处?

delphi guid interface

19
推荐指数
2
解决办法
5411
查看次数

IoC容器和域驱动设计

我一直在寻找在域驱动设计中使用IoC容器的指导.不幸的是,埃文的书没有触及这个主题.我能在互联网上找到的唯一重要指导方针就在这里.

马洛维奇的许多观点都是常识,但我担心其中的一些.他建议IoC容器应保留用于仅解析服务,并且使用IoC容器来解析域依赖性是一个坏主意.但是,他没有用任何例子来支持这个断言.他简单地说它是事实.

然后他继续说混合IoC容器和工厂是没有意义的.这似乎与他的第一点相矛盾.事实上,如果IoC容器不能解析域依赖关系,那么它们应该如何解决呢?埃文的书清楚地指出工厂是合乎逻辑的选择.

我很感激您对此事的任何意见.对于DDD和IoC,我都是新手.我正在努力掌握IoC和DDD如何协同工作.

domain-driven-design dependency-injection ioc-container

15
推荐指数
1
解决办法
3136
查看次数

正常化一个人的名字走得太远了吗?

您通常会规范化数据库以避免数据冗余.在一个充满名称的表格中很容易看到有足够的冗余.如果你的目标是创建一个地球上每个人的名字目录(祝你好运),我可以看到规范化名称是如何有益的.但在平均业务数据库的背景下是否过度杀伤?

(当然我知道你可以采取任何极端的事情......如果你将音节标准化为音节......或者甚至是相邻的角色对.我看不到这么远的好处)

更新:

一个可能的理由是随机名称生成器.这就是我能想到的一切.

database normalization

14
推荐指数
4
解决办法
7034
查看次数

NHibernate SchemaUpdate在生产代码中是否安全?

为简单起见.我在运行时使用Fluent NHibernate的Automapping和NHibernate的SchemaUpdate.在每次运行时,Automapper为所有实体类创建映射,SchemaUpdate将模式应用于现有数据库.我惊喜地发现它对空数据库也能正常工作.到目前为止,它在开发环境中运行良好,并且让我能够快速响应错误.

我的问题是它是否足够可靠留在生产代码中.显然,每次程序在生产环境中启动时都不需要运行,但它对增量产品更新很有用(尽管我不打算在产品发布后对域进行任何重大更改).

(也许我真正的问题应该是结合使用这两个工具有多安全?)

更新

该应用程序有两个版本:独立桌面和多用户客户端/服务器.此外,由于业务领域(税务软件)的性质,我每年都有一个干净的数据库.

nhibernate fluent-nhibernate production-environment

14
推荐指数
3
解决办法
3729
查看次数

Delphi类引用... aka metaclasses ...何时使用它们

我已经阅读了官方文档,我理解了哪些类引用,但我没有看到它们何时以及为什么它们是替代品的最佳解决方案.

文档中引用的示例是TCollection,可以使用TCollectionItem的任何后代进行实例化.使用类引用的理由是它允许您在编译时调用类型未知的类方法(我假设这是TCollection的编译时).我只是没有看到使用TCollectionItemClass作为参数如何优于使用TCollectionItem.TCollection仍然能够保存TCollectionItem的任何后代,并且仍然能够调用TCollectionItem中声明的任何方法.不是吗?

将其与通用集合进行比较.TObjectList似乎提供与TCollection大致相同的功能,并具有类型安全性的额外好处.您无需继承TCollectionItem以存储对象类型,您可以根据需要将集合设置为特定类型.如果您需要从集合中访问项目的成员,则可以使用通用约束.除了在Delphi 2009之前程序员可以使用类引用这一事实之外还有其他令人信服的理由将它们用于通用容器吗?

文档中给出的另一个示例是将类引用传递给充当对象工厂的函数.在这种情况下,工厂用于创建TControl类型的对象.它不是很明显,但我假设TControl工厂正在调用传递给它的后代类型的构造函数而不是TControl的构造函数.如果是这种情况,那么我开始至少看到使用类引用的一些原因.

所以我想我真正想要了解的是什么时候和哪些类引用最合适,他们了什么开发人员?

delphi metaclass class-reference

14
推荐指数
3
解决办法
4429
查看次数

如何重构具有10000行而没有文档的Delphi单元?

我被分配了重构Delphi单元的任务.哇.10000行代码,无文档,大量复制和粘贴代码.

这是复制和粘贴的许多方法,可以重构,无论如何我在所有这些线路中丢失,我有接口部分,我可以"找到我的方式",但一般来说,yuo建议如何处理这种任务?

谢谢.

delphi refactoring

13
推荐指数
3
解决办法
3469
查看次数

在Delphi中查找未使用的(又名"死")代码

是否有任何工具可以确定是否使用了函数/过程/方法/整个类?

我已经看到了可以帮助知识渊博的开发人员追踪未使用的代码片段的工具(大多数用于Delphi以外的语言),但大多数都有陡峭的学习曲线和/或需要大量挖掘来确定是否使用了代码片段.

Delphi的智能链接器据称可以减少最终可执行文件的大小.不幸的是,在智能链接器上给出的信息很少并不表示检索从hurd中剔除的内容的方法.

不可否认,即使有可能找出智能链接器正在消除它的东西,它的剔除也可能非常保守.

delphi dead-code

12
推荐指数
1
解决办法
4463
查看次数

当参数类型是Char的数组打开时,是否允许动态数组Char?

我在看Delphi:Char和TCharArray数组"不兼容的类型"并开始尝试.我发现的很有趣.

procedure Clear(AArray: array of Integer);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := 0;
end;

var
  MyArray: array of Integer;
begin
  Clear(MyArray);
end.
Run Code Online (Sandbox Code Playgroud)

这个简单的小例子展示了如何使用Open Array参数将动态数组传递给过程.它编译和运行完全符合预期.

procedure Clear(AArray: array of Char);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

var
  MyArray: array of Char;
begin
  Clear(MyArray);
end.
Run Code Online (Sandbox Code Playgroud)

这是几乎完全相同的代码唯一的区别是它使用的是数组Char而不是Integer.它不编译.相反,编译器吐出:

 E2010 Incompatible types: 'Array' and 'Dynamic array'
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

在搜索了一段时间后,我发现了这个 QC报告.我正在运行Delphi 2009,它仍然在发生.

delphi dynamic-arrays open-array-parameters

11
推荐指数
1
解决办法
2363
查看次数

Delphi接口继承:为什么我不能访问祖先接口的成员?

假设您有以下内容:

//Note the original example I posted didn't reproduce the problem so
//I created an clean example  
  type
    IParent = interface(IInterface)
    ['{85A340FA-D5E5-4F37-ABDD-A75A7B3B494C}']
      procedure DoSomething;
    end;

    IChild = interface(IParent)
    ['{15927C56-8CDA-4122-8ECB-920948027015}']
      procedure DoSomethingElse;
    end;

    TGrandParent = class(TInterfacedObject)
    end;

    TParent = class(TGrandParent)
    end;

    TChild = class(TParent, IChild)
    private
      FChildDelegate: IChild;
    public
      property ChildDelegate:IChild read FChildDelegate implements IChild;
    end;

    TChildDelegate = class(TInterfacedObject, IChild)
    public
      procedure DoSomething;
      procedure DoSomethingElse;
    end;
Run Code Online (Sandbox Code Playgroud)

我认为这可以让你打电话,DoSomething但似乎并非如此:

procedure CallDoSomething(Parent: TParent);
begin
  if Parent is TChild then
    TChild(Parent).DoSomething;
end;
Run Code Online (Sandbox Code Playgroud)

很明显,编译器正在强制执行接口继承,因为除非实现了成员,否则这两个类都不会编译 …

delphi inheritance interface delphi-2009

11
推荐指数
2
解决办法
5590
查看次数