问题标签 [leaky-abstraction]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
8 回答
2137 浏览

oop - 流畅的接口和有漏洞的抽象

什么是流畅的界面?我找不到一个好的定义,但我得到的只是我不太熟悉的语言(例如 C++)的长代码示例。

另外,什么是泄漏抽象?

谢谢

0 投票
4 回答
662 浏览

python - Python:对没有 if 子句的非空列表的迭代是空的。为什么?

sum()没有过滤和聚合(等)的非空序列上的迭代器如何不产生任何结果?

考虑一个简单的例子:

[('a', 97), ('b', 98), ('c', 99)]符合预期。

现在,只需将 out 替换为ord(el)从某个生成器中取出第一个值的表达式,使用(...).next()- 请原谅人为的示例:

这产生[]. 是的,空列表。没有('a',东西)元组。没有。

但我们没有过滤、聚合或减少。n没有过滤或聚合的对象生成器表达式必须产生n对象,对吗?这是怎么回事?

0 投票
1 回答
752 浏览

asp.net - MVC Contrib 是否兑现了提高 ASP.NET MVC 生产力的承诺

我很想开始一个新的 ASP.NET MVC 项目。一些教程推荐使用MVC Contrib。如果 Stack Overflow 社区兑现了通过 ASP.NET MVC 提高生产力的承诺,我想征求他们的意见。基本上,MVC Contrib 的好处值得为我的应用程序添加另一个泄漏抽象吗?

0 投票
2 回答
757 浏览

c# - 不使用 ORM 的 N 层数据库应用程序,UI 如何指定需要显示的数据?

我在这里寻找指针和信息,我会制作这个 CW,因为我怀疑它没有一个正确的答案。这是针对 C# 的,因此我将在下面对 Linq 进行一些引用。我也为这篇长文道歉。让我在这里总结一下问题,然后是完整的问题。

总结:在 UI/BLL/DAL/DB 4 层应用程序中,如何更改用户界面,显示更多列(例如在网格中),避免通过业务逻辑层泄漏到数据访问层,以获取要显示的数据(假设它已经在数据库中)。


让我们假设一个具有 3(4) 层的分层应用程序:

  • 用户界面 (UI)
  • 业务逻辑层 (BLL)
  • 数据访问层 (DAL)
  • 数据库(DB;第 4 层)

在这种情况下,DAL 负责构造 SQL 语句并针对数据库执行它们,返回数据。

是“正确”构建这样一个层以始终执行“选择*”的唯一方法吗?对我来说,这是一个很大的禁忌,但让我解释一下为什么我想知道。

假设我希望在我的 UI 中显示所有拥有有效就业记录的员工。“活动”是指就业记录从开始到日期包含今天(或者甚至可能是我可以在用户界面中设置的日期)。

在这种情况下,假设我想向所有这些人发送电子邮件,所以我在 BLL 中有一些代码可以确保我还没有向同一个人发送电子邮件,等等。

对于 BLL,它需要最少的数据量。也许它会调用数据访问层来获取活跃员工的列表,然后调用来获取它已发送的电子邮件列表。然后它加入这些并构造一个新列表。也许这可以在数据访问层的帮助下完成,这并不重要。

重要的是,对于业务层来说,它需要的数据真的不多。也许它只需要两个列表的每个员工的唯一标识符进行匹配,然后说“这些是那些活跃的人的唯一标识符,你还没有发送过电子邮件”。然后我是否构建 DAL 代码来构建仅检索业务层需要的 SQL 语句?IE。只是“从员工那里选择 id ...”?

那么我该怎么做用户界面呢?对于用户而言,最好包含更多信息,具体取决于要发送电子邮件的原因。例如,我可能想包括一些基本的联系信息,或者他们工作的部门,或者他们的经理姓名等,而不是说我至少要显示姓名和电子邮件地址信息。

UI 如何获取这些数据?我是否更改 DAL 以确保将足够的数据返回给 UI?我是否更改 BLL 以确保它为 UI 返回足够的数据?如果从 DAL 返回到 BLL 的对象或数据结构也可以发送到 UI,那么 BLL 可能不需要太多更改,但是 UI 的要求会影响层超出它应该与之通信的层. 如果这两个世界在不同的数据结构上运行,则可能必须对两者进行更改。

那么当 UI 发生变化时,为了进一步帮助用户,通过添加更多列,我必须/应该多深才能更改 UI?(假设数据已经存在于数据库中,因此不需要更改。)

提出的一个建议是使用 Linq-To-SQL 和 IQueryable,这样如果处理什么(如在什么类型的数据中)和为什么(如在 WHERE 子句中)返回 IQueryables 的 DAL,BLL 可以可能会将这些返回到 UI,然后 UI 可以构造一个 Linq 查询来检索它需要的数据。然后,用户界面代码可以拉入它需要的列。这会起作用,因为使用 IQuerables,UI 最终会实际执行查询,然后它可以使用“select new { X, Y, Z }”来指定它需要什么,甚至在必要时加入其他表。

这对我来说看起来很乱。UI 自己执行 SQL 代码,即使它隐藏在 Linq 前端之后。

但是,为了发生这种情况,不应该允许 BLL 或 DAL 关闭数据库连接,并且在 IoC 类型的世界中,DAL 服务可能会比 UI 代码想要的更快地被处理掉,所以Linq 查询可能只是以“无法访问已处置的对象”异常结束。

所以我正在寻找指针。我们离我们有多远?你是如何处理这个问题的?我认为对 UI 的更改会通过 BLL 泄漏到 DAL 中的事实是一个非常糟糕的解决方案,但现在看起来我们无法做得更好。

请告诉我我们有多愚蠢并证明我错了?

请注意,这是一个遗留系统。多年来,更改数据库架构并不在范围内,因此使用 ORM 对象的解决方案基本上相当于“选择 *”并不是一个真正的选择。我们有一些大表,我们希望避免拉起整个层列表。

0 投票
4 回答
512 浏览

java - 设计问题:RMI 需要显式导出对象

我有两个通过 RMI 通信的应用程序,一个从服务器(其中会有多个)和一个主服务器。

遵循良好的抽象设计,我想以一种方式实现从站,它不知道在与主站交谈时,它正在使用 RMI(例如,这两个应用程序也可以在同一个 JVM 中运行) :

问题:上面标记的行PROBLEM LINE不起作用,因为我不能简单地通过它(它Slave本身就是一个RemoteMaster回话的)。我必须明确地做一个UnicastRemoteObject.exportObject(this, 0)(或者toStub(this)如果它是之前导出的),但这会使Slave类依赖于 RMI,从而破坏了设计。

此外,registerSlave迫使我 catch RemoteException,这也增加了 RMI 依赖性。

你会建议什么来解决这些问题?

(这也让我感到困扰,这些类必须实现 Remote,但我想我们只能在抽象方面走这么远)

0 投票
11 回答
23629 浏览

programming-languages - 泄漏抽象的含义?

术语“泄漏抽象”是什么意思?(请举例说明。我经常很难理解一个单纯的理论。)

0 投票
3 回答
1205 浏览

c++ - 我应该为我的不透明对象使用整数 ID 还是指针?

我正在一些图形 API(DirectX9 和 DirectX11)之上编写一个抽象层,我想听听你的意见。

传统上,我会为每个要抽象的概念创建一个基类。
因此,在典型的 OO 方式中,我将拥有一个类 Shader 和 2 个子类 DX9Shader 和 DX11Shader。

我会重复纹理等的过程......当我需要实例化它们时,我有一个抽象工厂,它将根据当前的图形 API 返回适当的子类。
在 RAII 之后,返回的指针将被封装在 std::shared_ptr 中。

到目前为止一切都很好,但就我而言,这种方法存在一些问题:

  1. 我需要提供一个公共接口来封装这两个 API(以及未来的其他 API)的功能。
  2. 派生类存储在单独的 DLL 中(一个用于 DX9,一个用于 DX11 等),并且在客户端中有一个 shared_ptr 是一个诅咒:退出时,图形 dll 被卸载,如果客户端仍然有一个 shared_ptr 到由于从卸载的 DLL 调用代码,图形对象之一繁荣、崩溃。

这促使我重新设计我做事的方式:我认为我可以只返回指向资源的原始指针并让图形 API 自行清理,但仍然存在客户端悬空指针和接口问题的问题。我什至考虑过像 COM 这样的手动引用计数,但我认为这将是一个倒退(如果我错了,请纠正我,来自 shared_ptr 世界,手动引用计数似乎很原始)。

然后我看到了 Humus 的工作,他所有的图形类都用整数 ID 表示(很像 OpenGL 所做的)。创建一个新对象只返回它的整数ID,并在内部存储指针;这一切都是完全不透明的!

代表抽象的类(例如 DX9Shader 等)都隐藏在设备 API 后面,这是唯一的接口。
如果要设置纹理,只需调用 device->SetTexture(ID) 即可,其余的在幕后进行。

缺点是 API 的隐藏部分过于臃肿,需要大量样板代码才能使其工作,而且我不喜欢全能类。

有什么想法/想法吗?

0 投票
1 回答
257 浏览

clojure - 如何最好地与 clojure 抽象集成?

我正在 clojure 中实现一个有序集,在其中我根据它们的等级检索元素。这意味着我可以在对数时间内检索第 4 个元素(根据集合的顺序)、第 3 个或第 7 个元素。

为了使我的新数据结构与 clojure 的常用方法(或“抽象”)集成,例如conj, get,nth等,这是更好的方法:

  1. 实际实现conj,例如,在我的数据类型的协议中,或者
  2. 实现 Rich Hickeyclojure.lang.IPersistentSet或类似的接口。

第一个似乎更容易,但也更容易弄乱函数的语义。第二个似乎我正在实现一个从未打算成为公共 API 一部分的接口,并且与该接口(协议)相关联的实际方法令人困惑地不同。例如,似乎为了conj用我的集合实现,我必须实现一个具有不同名称的cons方法。clojure.lang.IPersistentSet似乎几乎没有关于这一切如何工作的文档,这对实施这个排名集提出了很大的挑战。

我应该选择哪一个?我应该实现自己的方法还是clojure.lang接口的方法?如果我应该做后者,哪里有一些好的文档可以指导我完成整个过程?

编辑:我想明确表示我正在尝试创建一个集合,您可以通过指定元素的等级(例如,“给我第 5 个元素,先生。放。”)。据我所知,clojure 中还没有这样的集合。

0 投票
1 回答
51 浏览

c# - 当我知道隐藏在它后面的类时,如何返回 T?

我知道 T 是List<string>(或List<MyClass>)。应该如何看待反射或允许我返回此字符串列表的东西?

背景:反序列化方法用于解析html数据。它类似于网站中使用的自己的 myJson.myDeserialize 方法,它没有 API。

0 投票
1 回答
1213 浏览

entity-framework - 通用存储库和泄漏抽象

我正在实现存储库模式。我这样做的主要原因:

  • 将客户端代码从持久性细节中抽象出来(实体框架)
  • 支持可测试性

通用存储库与否?

我遇到的问题是我是否应该有一个通用存储库。一种IQueryable<T> Query()方法将为调用代码提供构造特定查询的方法。这里的问题是这是泄漏的抽象——实体框架的细节现在正在泄漏到我的客户端代码中。

在此处输入图像描述

  • 这将如何影响单元测试? 我还能ICustomerRepository用这个实现来模拟吗?

  • 这种效果会如何替换我的持久层?像 Azure 存储表或 NHibernate。

否则我将不得不在 上实现非常具体的查询方法ICustomerRepository,例如GetIsActiveByFirstName()GetIsActiveByDistrict()。我非常不喜欢这种方式,因为我的存储库类将挤满不同的查询方法。这个系统有数百个模型,因此可能有数百甚至数千个这样的方法来编写和维护。