小编Leo*_*Hat的帖子

您如何平衡向后兼容性和创新的冲突需求?

我在一个具有GUI(图形)和API(脚本)接口的应用程序上工作.我们的产品具有非常大的安装基础.许多客户在编写使用我们产品的脚本上投入了大量的时间和精力.

在我们的所有设计和实现中,我们(可以理解)对保持100%向后兼容性有非常严格的要求.当我们引入新的软件版本时,之前运行的脚本必须以完全相同的方式继续运行,无需任何修改.

不幸的是,这种要求有时会牵扯到我们的背后,因为它确实限制了我们的创新能力,并提出了新的更好的做事方式.

例如,我们可能会提出一种更好(更有用)的方法来实现已经可能的任务.我们希望以更好的方式使用默认方式,但我们不能这样做,因为它可能具有向后兼容性含义.因此,我们坚持将新的(更好的)方式作为一种模式,用户必须在其可用之前"打开".除非他们阅读文档或在线帮助(许多客户不这样做),否则这项新功能将永远隐藏起来.

我知道Windows Vista在第一次出现时会让很多人感到恼火,因为所有软件和外围设备都没有用,即使他们在XP上工作也是如此.由于这个原因,它收到了非常糟糕的接待.但是你可以看到,微软也成功地在Vista中进行了一些伟大的创新,但却牺牲了许多用户的向后兼容性.他们冒了风险.它得到了回报吗?他们做出了正确的决定吗?我想只有时间会证明.

您是否发现自己在平衡创新和向后兼容性的冲突需求?你如何处理杂耍行为?

backwards-compatibility innovation

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

在Win32调试版本中,什么可以导致VTable指针为0xdddddddd?

我正在调试一个缺陷,并将其缩小到对象的vtable指针0xdddddddd. 这个答案表明Win32调试版本通常会将死记忆或已删除的内存设置为此特殊值.

需要注意的是指针本身看起来有效,它只是虚函数表指针0xdddddddd.

这是一段代码:

std::list<IMyObject*>::const_iterator it;
for (it = myObjects.begin(); it != myObjects.end(); ++it)
{
    IMyObject* pMyObject = *it;
    if (pMyObject == 0)
        continue;

    pMyObject->someMethod(); // Access violation     
}
Run Code Online (Sandbox Code Playgroud)

如果我在访问冲突的行中断并观察pMyObject,我可以看到它pMyObject本身有一个有效的地址(0x08ede388)但该__vfptr成员是无效的(0xdddddddd).

一些说明:

  • 它是一个单线程应用程序,因此很可能不是竞争条件或互斥问题.
  • 似乎没有任何明显的问题,比如在访问对象之前将对象进一步向上删除.
  • 此问题似乎只能在Windows 2008服务器上重现,但不能在Windows 7上重现.

有关如何进一步调试的任何建议?

c++ debugging vtable

10
推荐指数
1
解决办法
1万
查看次数

如何实现顶级异常处理?

我最近不得不为同事开发的现有服务开发一个额外的模块.他在主要工作函数中放置了一个try/catch块,用于捕获冒泡到这个级别的所有未处理异常,将它们与堆栈跟踪信息一起记录下来:

try
{
    // do main work
}
catch(Exception ex)
{
    // log exception info
}
Run Code Online (Sandbox Code Playgroud)

虽然这使程序非常稳定(如'不太可能崩溃'),但我讨厌它,因为当我测试我的代码时,我没有看到由它引起的异常.当然,我可以查看异常日志并查看是否有新条目,但我非常喜欢在抛出异常时获得异常的直接反馈(请将光标放在代码的右侧).

我至少在编码和测试的时候删除了这个顶级的try/catch.但是现在我的任务已经完成,我必须决定是否将其重新用于发布,或者不是.我认为我应该这样做,因为它使服务更稳定,而且它的全部意义在于它在后台运行而无需任何监督.另一方面,我已经读过一个应该只调用特定的异常(如IoException),而不是一般Exception.

你对这个问题有什么建议?

顺便说一句,该项目是用C#编写的,但我也对非.NET语言的答案感兴趣.

exception-handling

9
推荐指数
1
解决办法
7205
查看次数

COM IDL定义中[in,out]和[out,retval]之间的差异

在我工作的一些IDL中,我注意到在方法中有两种用于标记返回值的约定 - [in, out][out, retval].

似乎[in, out]在有多个返回值时使用,例如:

HRESULT MyMethod(
    [in] long InputParam, 
    [in, out] long* OutputParam1, 
    [in, out] long* OutputParam2
);
Run Code Online (Sandbox Code Playgroud)

似乎[out, retval]只有一个返回值时使用,例如:

HRESULT MyMethod2(
    [in] long InputParam, 
    [out, retval] long* OutputParam1
);
Run Code Online (Sandbox Code Playgroud)

这是一个COM IDL约定还是我正在使用的代码中的约定?

从2个符号生成的代码是否存在功能差异,或者它们是否完全可互换?

com idl notation

8
推荐指数
1
解决办法
1万
查看次数

您如何处理预期在开发过程中失败的单元/回归测试?

在软件开发过程中,代码库中可能存在已知问题的错误.如果测试编写良好,这些错误将导致回归/单元测试失败.

我们的团队一直在争论如何管理失败的测试:

  1. 使用REVISIT或TODO注释评论失败的测试用例.

    • 优势:我们将始终知道何时引入了缺陷,而不是我们已经知道的缺陷.
    • 缺点:可能忘记重新评估已注释掉的测试用例,这意味着缺陷可能会漏掉.
  2. 让测试用例失败.

    • 优点:不会忘记修复缺陷,因为脚本失败会不断提醒您存在缺陷.
    • 缺点:由于故障噪声,很难检测何时引入缺陷.

我想探讨一下这方面的最佳实践.就个人而言,我认为三态解决方案最适合确定脚本是否正在通过.例如,当您运行脚本时,您可以看到以下内容:

  • 通过率:75%
  • 失败百分比(预期):20%
  • 失败百分比(意外):5%

您基本上可以使用某些元数据标记您希望失败的测试用例(由于某些缺陷).这可以确保您在测试结束时仍然可以看到失败结果,但会立即知道是否有新的结果您不期望故障.这似乎采取了上述两个提案中最好的部分.

有没有人有任何最佳实践来管理这个?

automated-tests

7
推荐指数
2
解决办法
1184
查看次数

允许成员为const,同时仍然在类上支持operator =

我班上有几个成员,const因此只能通过初始化列表进行初始化,如下所示:

class MyItemT
{
public:
    MyItemT(const MyPacketT& aMyPacket, const MyInfoT& aMyInfo)
        : mMyPacket(aMyPacket),
          mMyInfo(aMyInfo)
    {
    }

private:
    const MyPacketT mMyPacket;
    const MyInfoT mMyInfo;
};
Run Code Online (Sandbox Code Playgroud)

我的类可以在我们的一些内部定义的容器类(例如向量)中使用,并且这些容器需要operator=在类中定义.

当然,我operator=需要做这样的事情:

MyItemT&
MyItemT::operator=(const MyItemT& other)
{
    mMyPacket = other.mPacket;
    mMyInfo = other.mMyInfo;
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

这当然不起作用,因为mMyPacket并且mMyInfoconst成员.

除了让这些成员不是const(我不想做),关于如何解决这个问题的任何想法?

c++ const operators

6
推荐指数
1
解决办法
206
查看次数

使用System.IO.Packaging创建大型ZIP文件时出现OutOfMemoryException

我正在尝试调试使用OutOfMemoryException时创建相当大的ZIP文件时发生的情况System.IO.Packaging.ZipPackage.

代码遍历大型对象列表,为每个对象执行以下操作.

  1. 将对象数据序列化为临时文件.
  2. PackagePart为文件创建一个.
  3. 从源复制System.IO.Stream到另一个:
    • 来源流: FileStream
    • 目标流:PackagePart::GetStream()=>MS.Internal.IO.Zip.ZipIOModeEnforcingStream

最后它调用Package::Close()保存文件.

我遇到的问题是,对于一个特别大的对象列表,我看到了OutOfMemoryException(x86进程大小增加到大约1.2GB).

我正在考虑将对象数据划分为块,所以我每个循环只处理一个较小的量(即上面的步骤1-3).我的想法是,我将n在一个临时目录中创建ZIP文件,然后找到一种方法将它们组合成一个存档.

这可能用System.IO.Packaging吗?我会用什么来组合这些部件?

或者有更好的方法来解决这个问题吗?

c# packaging out-of-memory

6
推荐指数
1
解决办法
2741
查看次数

有没有办法从TortoiseSVN Explorer图标装饰中排除{ignore-on-commit}更改?

TortoiseSVN在Windows资源管理器中显示图标装饰,显示特定目录树中是否存在任何未提交的更改.例如:

TortoiseSVN图标装饰

上图显示目录树中某处Trunk有更改的文件.

但是,我经常使用ignore-on-commit更改列表来保存我从未想要提交的Web.config更改- 例如,与连接字符串相关的更改.

我不能依靠图标装饰让我知道我是否有变化,因为它们也会出现红色(!),即使只有Web.config变化.这会给Explorer带来不必要的噪音.

有没有办法改变这个,以便只有我想要提交的更改被标记为资源管理器中的更改?

svn explorer tortoisesvn

6
推荐指数
1
解决办法
789
查看次数

虚拟内存

大多数关于虚拟内存的文献都指出,作为一名应用程序开发人员,了解虚拟内存可以帮助我利用其强大的功能.我曾经参与过在Linux上开发应用程序,但在编写代码时并不关心虚拟内存的复杂性.我错过了什么吗?如果是这样,请详细说明我如何利用虚拟内存的工作原理.如果我对这个问题没有意义,请告诉我!

memory virtual memory-management

5
推荐指数
1
解决办法
1968
查看次数

ATL简单对象向导 - "对象Xxx已存在"错误

我试图使用Visual Studio 2005中的ATL简单对象向导在我的DLL中创建一个新的COM对象.

我输入对象的短名称,并导出所有其他字段.

但是,当我在向导中单击" 下一步 "时,会出现以下错误消息:

Object 'IXxxInterfaceName' already exists
Run Code Online (Sandbox Code Playgroud)

我已经搜索了我的整个解决方案,以获取对IXxxInterfaceName的所有引用,并且无法在任何地方看到它的定义.

向导如何确定它已经存在?

c++ com atl visual-studio-2005 visual-studio

5
推荐指数
1
解决办法
2942
查看次数