标签: interface-design

是否有用于初始化通过DI容器创建的对象的模式

我试图让Unity管理我的对象的创建,我希望有一些在运行时才知道的初始化参数:

目前,我能想到的方法是在接口上使用Init方法.

interface IMyIntf {
  void Initialize(string runTimeParam);
  string RunTimeParam { get; }
}
Run Code Online (Sandbox Code Playgroud)

然后使用它(在Unity中)我会这样做:

var IMyIntf = unityContainer.Resolve<IMyIntf>();
IMyIntf.Initialize("somevalue");
Run Code Online (Sandbox Code Playgroud)

在这种情况下,runTimeParamparam是在运行时根据用户输入确定的.这里的简单案例只返回值,runTimeParam但实际上参数将类似于文件名,初始化方法将对文件执行某些操作.

这会产生许多问题,即该Initialize方法在界面上可用并且可以多次调用.在实现中设置一个标志并在重复调用时抛出异常Initialize似乎很笨重.

在解析我的界面时,我不想知道有关实现的任何信息IMyIntf.但是,我想要的是知道这个接口需要一定的一次初始化参数.有没有办法以某种方式注释(属性?)具有此信息的接口,并在创建对象时将它们传递给框架?

编辑:更多地描述了界面.

interface-design dependency-injection ioc-container inversion-of-control unity-container

145
推荐指数
3
解决办法
7万
查看次数

开发更大的JavaScript应用程序的最佳实践

拥有Java/C++的强大背景我想知道是否有可能开发一个更大的JavaScript应用程序而不必削减质量.

任何提示都受到赞赏:

  • 发展环境
  • 调试技术
  • 单元测试
  • 剖析
  • 仪表
  • 系统设计
  • 界面设计
  • 代码设计

我也很好奇JavaScript PC模拟器JavaScript游戏引擎等项目是如何处理这些问题的,以防有些人知道.

javascript ide interface-design unit-testing system-design

61
推荐指数
5
解决办法
7397
查看次数

设计Python API:Fluent接口或参数

我正在玩一个简单的Protovis API 端口到Python.

在Javascript中考虑简单的条形图示例:

var vis = new pv.Panel()
    .width(150)
    .height(150);

vis.add(pv.Bar)
    .data([1, 1.2, 1.7, 1.5, .7, .3])
    .width(20)
    .height(function(d) d * 80)
    .bottom(0)
    .left(function() this.index * 25);

vis.render();
Run Code Online (Sandbox Code Playgroud)

我在争论是否继续使用这种流畅的界面风格API或使用命名参数.使用命名参数我们可以写:

vis = pv.Panel(width=150,
               height=150)

vis = vis + pv.Bar(data=[1, 1.2],
                   width=20,
                   height=lambda d: d * 80,
                   bottom=0,
                   left=lambda: self.index * 25)
vis.render()
Run Code Online (Sandbox Code Playgroud)

是否有首选的Python风格?

python interface-design

22
推荐指数
1
解决办法
5534
查看次数

接口/抽象类中的静态方法

首先,我理解接口或抽象类(在.NET/C#术语中)不能具有抽象静态方法的原因.我的问题更侧重于最佳设计解决方案.

我想要的是一组"辅助"类,它们都有自己的静态方法,这样如果我从第三方供应商那里得到对象A,B和C,我可以使用诸如

AHelper.RetrieveByID(string id);
AHelper.RetrieveByName(string name);
AHelper.DumpToDatabase();

由于我的AHelper,BHelper和CHelper类都基本上都有相同的方法,因此将这些方法移动到这些类随后派生的接口似乎是有意义的.但是,希望这些方法是静态的,使我无法使用通用接口或抽象类来导出所有这些方法.

我总是可以使这些方法非静态,然后首先实例化对象,如

AHelper a = new AHelper();
a.DumpToDatabase();

但是,这段代码对我来说似乎并不直观.你有什么建议?我应该完全放弃使用接口或抽象类(我现在的情况)还是可以重构这些以完成我正在寻找的设计?

.net interface-design abstract-class static-methods

10
推荐指数
2
解决办法
8899
查看次数

图像编辑工具的高级设计模式

我最近开始创建一个图像编辑工具,以满足非常具体的需求.对于那些打算使用它的人来说,这同样适合我自己的娱乐.然而,我在早期遇到了一些建筑障碍.

与任何图像编辑器一样,用户将使用"工具"来绘制和操纵图像.我的第一次尝试包括一个简单的界面:

public interface IDrawingTool
{
    void DrawEffect( Graphics g );
    // other stuff
}
Run Code Online (Sandbox Code Playgroud)

这(我认为)会很好,干净,便于维护和扩展.只需添加接口对象并在运行时调用所选接口对象的DrawEffect方法即可.

这种方法的问题在于不同的绘图工具不能干净地粘附到单个界面上.例如,钢笔工具只需知道要绘制的点即可工作.然而,矩形需要点击第一个点,以及当前位置.多边形工具需要跟踪多次鼠标点击.

我无法想出一个实现这个的好方法.我现在能想到的最好的方法是涉及每个工具的switch语句和case,这意味着绘图逻辑将在Canvas类中,而不是由Tool类型对象封装.因为这是练习,我想以正确的方式做到这一点.在此先感谢您的帮助.

oop interface-design design-patterns

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

.NET 应用程序的插件设计

我正在考虑用 C#(当前遗留的 VB6 代码)重写我们应用程序的一部分。我开始使用的模块负责将数据从各种系统导入我们的数据库。每年大约有 5-6 次,一个新客户要求我们为他们使用的系统编写一个新的导入。目前,这要求我们为添加到应用程序的每个新导入选项发布新版本的软件。

重写的目标之一是使应用程序支持插件。每个新的导入都可以成为一个单独的程序集,宿主应用程序将识别该程序集并允许最终用户与之交互。这有望在一定程度上简化生活,因为我们可以简单地将新程序集放入目录中,并让主(主机)应用程序识别和使用它。

我正在努力解决的问题之一与我们目前支持的导入选项之间的差异有关。在某些情况下,我们实际上让用户指向一个目录并将目录中的所有文件读入我们的系统。在其他情况下,我们允许它们指向单个文件并导入其内容。此外,某些导入具有用户应用的日期范围限制,而其他导入则没有。

我的问题是,我如何设计应用程序,以便在我们构建和支持的导入之间具有一定的灵活性,同时实现一个通用接口,使主机应用程序能够轻松识别插件和选项每个都暴露给用户?

.net interface-design plugins

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

C++ DAL - 返回引用或填充参考传递

[编辑1 - 添加第三个指针语法(谢谢Alex)]

您更喜欢DAL的哪种方法以及为什么出于以下原因:

Car& DAL::loadCar(int id) {}
bool DAL::loadCar(int id, Car& car) {}
Car* DAL::loadCar(int id) {}
Run Code Online (Sandbox Code Playgroud)

如果无法找到汽车第一个方法返回null,则第二个方法返回false.

第二种方法是在堆上创建一个Car对象,并使用从数据库中查询的数据进行填充.据推测(我的C++非常生疏),这意味着代码如下:

Car& DAL::loadCar(int id)
{
    Car *carPtr = new Car();
    Car &car= *carPtr;
    car.setModel(/* value from database */);
    car.setEngineSize(/* value from database */);
    // etc
    return car;
}
Run Code Online (Sandbox Code Playgroud)

谢谢

c++ interface-design reference pass-by-reference

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

如何设计我的C#jQuery API,使其不会混淆使用?

我正在为C#制作一个jquery克隆.现在我已经设置好了,所以每个方法都是一个扩展方法,IEnumerable<HtmlNode>所以它适用于已经使用的现有项目HtmlAgilityPack.我以为我可以在不保留状态的情况下离开...然而,我注意到jQuery有两种方法.andSelf,.end它们会从内部堆栈"弹出"最近匹配的元素.如果我改变我的类以便它总是在SharpQuery对象上运行而不是枚举,我可以模仿这个功能,但是仍然存在问题.

使用JavaScript,您可以自动获得Html文档,但在使用C#时,您必须明确加载它,如果需要,您可以使用多个文档.看来,当你打电话给$('xxx')你时,你实际上是在创建一个新的jQuery对象,并以空堆栈开始.在C#中,您不希望这样做,因为您不想从Web重新加载/重新获取文档.因此,您只需将其加载到SharpQuery对象中,或加载到HtmlNodes列表中(您只需要开始使用DocumentNode).

在jQuery文档中,他们给出了这个例子

$('ul.first').find('.foo')
  .css('background-color', 'red')
.end().find('.bar')
  .css('background-color', 'green')
.end();
Run Code Online (Sandbox Code Playgroud)

我没有初始化方法因为我不能重载()运算符,所以你只需要开始sq.Find(),它在文档的根目录上操作,基本上做同样的事情.但是后来人们会尝试sq.Find()在一条线上写字,然后在sq.Find()某个地方写下来,并且(理所当然地)期望它再次在文档的根部运行......但是如果我保持状态,那么你就是刚刚在第一次调用后修改了上下文.

那么......我应该如何设计我的API?我是否添加了另一个Init方法,所有查询应该从重置堆栈开始(但是我如何强制它们从那开始呢?),或者添加一个Reset()他们必须在他们的行尾调用的方法?我是否超载[]而告诉他们从那开始?我会说"忘记它,没有人使用那些保存状态的功能吗?"

基本上,您希望如何用C#编写jQuery示例?

  1. sq["ul.first"].Find(".foo") ...
    垮台:虐待[]财产.

  2. sq.Init("ul.first").Find(".foo") ...
    失败:除非我添加一些奇怪的"初始化"机制,否则没有什么能真正迫使程序员从Init开始; 用户可能会尝试使用.Find而不是获得他期望的结果.此外,InitFind是几乎相同的,无论如何,除了前者把堆栈复位了.

  3. sq.Find("ul.first").Find(".foo") ... .ClearStack()
    垮台:程序员可能忘记清理堆栈.

  4. 不能这样做.
    end()未实现.

  5. 使用两个不同的对象.
    也许HtmlDocument用作所有查询应该开始的基础,然后每个方法返回一个SharpQuery可以链接的对象.这样,HtmlDocument始终保持初始状态,但SharpQuery对象可能具有不同的状态.遗憾的是,我必须实现两次(一次用于HtmlDocument,一次用于SharpQuery对象).

  6. new SharpQuery(sq).Find("ul.first").Find(".foo") ...
    构造函数复制对文档的引用,但重置堆栈.

c# interface-design jquery html-agility-pack

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

使用pass-by-reference而不是pass-by-pointer时的二进制兼容性

这个问题是作为这个问题的后续问题:C++中指针变量和引用变量之间有什么区别?

阅读了我在stackoverflow上找到的答案和一些进一步的讨论后,我知道编译器应该像处理pass-by-pointer一样对待pass-by-reference,而引用只不过是语法糖.考虑到二进制兼容性,如果存在任何差异,我还无法弄清楚一件事.

在我们的(多平台)框架中,我们要求在发布和调试版本之间(以及框架的不同版本之间)进行二进制兼容.特别是,我们在调试模式下构建的二进制文件必须可用于发布版本,反之亦然.为此,我们只在接口中使用纯抽象类和POD.

请考虑以下代码:

class IMediaSerializable
{
public:
    virtual tResult Serialize(int flags,
                              ISerializer* pSerializer,
                              IException** __exception_ptr) = 0;
//[…]
};
Run Code Online (Sandbox Code Playgroud)

ISerializer并且IException也是纯粹的抽象类.ISerializer必须指向现有对象,因此我们总是必须执行NULL指针检查.IException实现某种异常处理,其中指针指向的地址必须改变.出于这个原因,我们使用指向指针的指针,指针也必须是NULL指针.

为了使代码更清晰并省去一些不必要的运行时检查,我们希望使用pass-by-reference重写此代码.

class IMediaSerializable
{
public:
    virtual tResult Serialize(int flags,
                              ISerializer& pSerializer,
                              IException*& __exception_ptr) = 0;
//[…]
};
Run Code Online (Sandbox Code Playgroud)

这似乎没有任何缺陷.但问题仍然是我们是否仍然满足二进制兼容性的要求.

更新: 澄清事情:这个问题不是关于代码的pass-by-pointer版本和pass-by-reference版本之间的二进制兼容性.我知道这不能是二进制兼容的.事实上,我们有机会重新设计我们的API,我们考虑使用pass-by-reference而不是pass-by-pointer而不关心二进制兼容性(新的主要版本).问题只是关于仅使用代码的pass-by-reference版本的二进制兼容性.

c++ interface-design pass-by-reference binary-compatibility pass-by-pointer

4
推荐指数
1
解决办法
513
查看次数

使用界面时的最佳做法

很多时候,在设计接口时,我会一直遇到相同的情况.这种情况是使用接口的某些实现需要接口中的特定参数而其他实现不需要.

  • 设计界面时的最佳做法是什么?
  • 是否可以使用某些实现接口但不使用所有参数的实现?

或者在这些情况下,我应该只参考一个参数列表(某些结构)并在每个实现中相应地处理该列表?

c# architecture interface-design interface

2
推荐指数
1
解决办法
2744
查看次数

如何表达参数需要在C#中实现多个接口?

与此问题类似:我如何需要一个方法参数来实现多个接口? 我想要一个方法参数来实现几个接口.

接口应以任意方式组合,我不想为每个有效组合创建接口.

想一个文件.有可能:

  1. readable => IReadable
  2. 可写=> IWriteable
  3. 存档=> IArchive
  4. 自动生成=> IGenerated

...

如果我想表达一个参数需要是一个可写的,生成的存档我不想生成,IWritableGeneratedArchive因为有太多的组合,我想用它与一些我无法修改的现有类.

伪代码:

void WriteTo( IWritable + IGenerated + IArchive file)
{
   //...
}
Run Code Online (Sandbox Code Playgroud)

c# interface-design interface

2
推荐指数
1
解决办法
261
查看次数

*你*使用C++ ABC构造函数做什么?

人们在这里使用C++抽象基类构造函数?我说的是没有数据成员且没有非纯虚拟成员的纯接口类.

任何人都可以用有用的方式展示任何使用ABC构造函数的习语吗?或者它只是固有的使用ABCs实现接口,它们保持空,内联和保护?

c++ interface-design constructor abc

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