在DDD中,其中一个关键概念是Repository,它允许您检索实体(或聚合根),然后在更新后将其保存回来.
假设我们需要对实体执行一些"批量"操作,并且实体的数量使得绝对不可能将它们检索到内存中.即操作只能在数据库中执行.
这种"批量"运营的地方在哪里?它应该是存储库中的方法吗?它不会"泄漏"数据库特定操作的存储库抽象吗?它不会将业务运营从实体转移到存储库吗?
" 抽象和封装是互补的概念:抽象关注于对象的可观察行为......封装集中于产生这种行为的实现......封装通常是通过信息隐藏来实现的,这是隐藏所有内容的过程.物体的秘密对其基本特征没有贡献." - 面向对象分析与设计的Grady Booch
您能否通过信息隐藏向我展示一些有说服力的封装优势的例子?
language-agnostic oop encapsulation abstraction information-hiding
设计可理解软件(实际上,设计任何东西)的关键属性之一是开发一组良好的抽象.目前,这些抽象包括函数,类,接口,递归和高阶函数等.但还有什么呢?我们怎样才能进一步抽象出我们的设计,这样我除了直接,直接的目标外,我不需要考虑任何事情?现有技术尚未利用哪些新颖的抽象?
另请注意,我列表中的大多数项目(可能是递归的例外)也是用于代码重用的工具.代码重用不是这个问题的主题,也不是我认为良好抽象的必要方面.函数作为抽象很有用,因为它们隐藏了描述性名称背后的内容,而不是因为我可以从几个不同的地方调用它们.
一个结构不良的想法:一个驱动程序函数只调用一系列其他函数,而不维护它自己的任何状态,真的和函数一样吗?我们把它写成一个函数,并将其称为函数,但它可能代表了一个不同的概念?这通过在返回值和过程而不返回值的过程之间进行区分来反映在某些语言中.但也许有更好的方法来查看这种差异,以某种不同的方式来抽象相对不相关的步骤序列?
重申一下,未来的编程语言如何才能更好地促进抽象?
我是Peter Pilgrim.我看过Martin Odersky在Scala中创建了一个控件抽象.但是我似乎还没有在IntelliJ IDEA 9中重复它.它是IDE吗?
package demo
class Control {
def repeatLoop ( body: => Unit ) = new Until( body )
class Until( body: => Unit ) {
def until( cond: => Boolean ) {
body;
val value: Boolean = cond;
println("value="+value)
if ( value ) repeatLoop(body).until(cond)
// if (cond) until(cond)
}
}
def doTest2(): Unit = {
var y: Int = 1
println("testing ... repeatUntil() control structure")
repeatLoop {
println("found y="+y)
y = y + 1
}
{ …Run Code Online (Sandbox Code Playgroud) 假设我有两个协议:
(defprotocol A
(f [this]))
(defprotocol B
(g [x y]))
Run Code Online (Sandbox Code Playgroud)
我想将协议B扩展到支持协议A的所有实例:
(extend-protocol A
String
(f [this] (.length this)))
(extend-protocol B
user.A
(g [x y] (* (f x) (f y))))
Run Code Online (Sandbox Code Playgroud)
主要动机是避免必须将B分别扩展到A可能扩展到的所有可能的类,或者甚至是其他人可能扩展到A的未知未来类(例如,如果A是公共API的一部分,例如) .
但是这不起作用 - 你会得到如下内容:
(g "abc" "abcd")
=> #<IllegalArgumentException java.lang.IllegalArgumentException:
No implementation of method: :g of protocol: #'user/B found for
class: java.lang.String>
Run Code Online (Sandbox Code Playgroud)
这有可能吗?如果没有,是否有一个合理的解决方法来实现相同的目标?
我正在尝试将DataBinding添加到我的应用程序中.在我的应用程序中,我有一个BaseActivity,它有一个工具栏和一个FrameLayout.FrameLayout是扩展BaseActivity的活动的容器.如何在我的BaseActivity和扩展活动中添加数据绑定?
我将在没有DataBinding的情况下共享我的代码:
这是我的BaseActivity.java:
public class BaseActivity extends AppCompatActivity {
@Override
public void setContentView(@LayoutRes int layoutResID) {
LinearLayout container = (LinearLayout) getLayoutInflater().inflate(R.layout.activity_base, null);
FrameLayout activityContent = (FrameLayout) container.findViewById(R.id.activityContent);
getLayoutInflater().inflate(layoutResID, activityContent, true);
super.setContentView(container);
Toolbar toolbar = (Toolbar) container.findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(menuItem);
}
public void setTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
Run Code Online (Sandbox Code Playgroud)
这是activity_base.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<include
android:id="@+id/toolbarLayout"
layout="@layout/toolbar" …Run Code Online (Sandbox Code Playgroud) 假设我有1个完整的类,其中包含约20种提供不同功能的方法。
现在,我们有多个使用此类的客户端,但我们希望它们具有受限的访问权限。
例如-
客户端1-可以访问method1 / m3 / m5 / m7 / m9 / m11
客户端2-可以访问method2 / m4 / m6 / m8 / m10 / m12
有什么办法可以限制此访问权限?
我认为的一种解决方案:
创建2个扩展父类的新类,并覆盖无法访问的方法,并从中抛出Exception。但是,如果第3个客户端有不同的要求,我们必须为其创建新的子类。
还有其他方法吗?
我可能会以错误的方式接近这一点,所以请原谅我的天真:
为了学习Clojure,我已经开始将我的OAuth客户端库移植到Clojure.我这样做是通过包装clj-http来实现的,就像我在Python库中包装Python Requests一样.到目前为止,这似乎工作得很好,我真的很高兴看到Clojure中的实现变得生动.
但是我遇到了一个问题:我计划支持OAuth 1.0和2.0,并将各自的功能分成两个文件:oauth1.clj和oauth2.clj.现在,每个文件理想情况下应该公开一组与HTTP谓词对应的函数.
(ns accord.oauth2)
...
(defn get
[serv uri & [req]]
((:request serv) serv (merge req {:method :get :url uri})))
Run Code Online (Sandbox Code Playgroud)
这些函数基本相同,实际上现在在oauth1.clj和oauth2.clj之间完全相同.我的第一反应是将这些函数移动到core.clj中,然后在相应的OAuth名称空间(oauth1,oauth2)中要求它们,以避免两次写入相同的代码.
只要我在文件中使用引用的函数,即oauth1.clj或oauth2.clj,这就没问题了.但是,假设我们想要使用这个库,因为我打算(这里是REPL,或者你的程序),如下所示:
=> (require '[accord.oauth2 :as oauth2]) ;; require the library's oauth2 namespace
...
=> (oauth2/get my-service "http://example.com/endpoint") ;; use the HTTP functions
Run Code Online (Sandbox Code Playgroud)
oauth2/get找不到var,因为单独将它拉入oauth2.clj中的命名空间似乎并没有公开它,好像它实际上在那个命名空间中一样.我不想用更多的功能包装它们,因为这基本上违背了目的; 函数是如此简单(它们只是包装一个request函数)我会在三个地方写它们,基本上,如果我这样做的话.
我确信我不是正确地在Clojure中使用命名空间,而且可能是习惯性地考虑抽象问题和代码共享的一般方法.
所以我想知道这个惯用解决方案是什么?我完全错误地采取了这种方式吗?
编辑:
这是问题的简化:https://gist.github.com/maxcountryman/5228259
请注意,目标是一次编写HTTP谓词函数.他们不需要特殊的派遣类型或类似的东西.他们已经很好了.问题是它们不会暴露于accord.oauth1或者accord.oauth2,accord.oauth2例如,当您的程序需要时.
如果这是Python的,我们可以只导入功能是这样的:from accord.core import get, post, put, ...为accord.oauth1和accord.oauth2,然后当我们使用accord.oauth1,我们将有机会获得所有这些进口的功能,例如模块 …
我对这个用例有一个普遍的问题:我有一个班级A.这个类有一个非抽象的方法doStuffCallback(),可以被覆盖,但并不是每个子类都需要.但是:我想确保如果方法被覆盖,则子类方法必须调用parents方法.
例:
abstract class A {
private function doStuff() {
$this->doStuffCallback();
}
protected function doStuffCallback() {
// IMPORTANT CODE HERE
}
}
class B extends A {
protected function doStuffCallback() {
parent::doStuffCallback(); // I want to enforce this because the parents method code is important
// ALSO IMPORTANT CODE
}
}
Run Code Online (Sandbox Code Playgroud)
因为重写的方法做同样的事情,为同一个责任定义两个方法和调用两个方法的私有帮助方法会非常难看.像这样:
abstract class A {
private function doStuff() {
$this->callDoStuffCallback();
}
private function callDoStuffCallback() {
$this->internalDoStuffCallback();
$this->doStuffCallback();
// This is VERY ugly
}
private function …Run Code Online (Sandbox Code Playgroud) 虽然下面的例子看起来有点奇怪,但这是因为我试图减少我目前得到的一个相当大的问题.当他们坐在几个抽象层后面时,我正在努力研究如何调用多方法,而defmulti和相应的defmethods在多个命名空间中定义.我真的觉得我错过了一些明显的东西......
假设我有以下场景:
使用Clojure,实现通用接口的推荐方法是通过协议或多方法.在这种情况下,当我根据供应商的价值进行切换时,我认为处理下面描述的情况的最佳方法是通过多方法(但我可能是错的).
我的多方法定义看起来像这样,它定义了一个我想用来与每个供应商的API交流的通用接口:
(ns myapp.suppliers.interface)
(defmulti purchase-item :supplier)
(defmulti get-item-price :supplier)
Run Code Online (Sandbox Code Playgroud)
对于每个供应商,我可能想要这样的东西:
(ns myapp.suppliers.supplier1
(:require [myapp.suppliers.interface :as supplier-api]))
(defmethod purchase-item :supplier1 [item quantity] ...)
(defmethod get-item-price :supplier1 [item] ...)
Run Code Online (Sandbox Code Playgroud)
和
(ns myapp.suppliers.supplier2
(:require [myapp.suppliers.interface :as supplier-api]))
(defmethod purchase-item :supplier2 [item quantity] ...)
(defmethod get-item-price :supplier2 [item] ...)
Run Code Online (Sandbox Code Playgroud)
到目前为止,没问题
现在我的代码调用这些抽象的方法,我假设看起来像:
(ns myapp.suppliers.api
(:require [myapp.suppliers.supplier1 :as supplier1]
[myapp.suppliers.supplier2 :as supplier2])
(defn buy-something
[supplier item quantity]
(purchase-item [supplier item quantity])
(defn price-something
[supplier item]
(get-item-price [supplier item])
Run Code Online (Sandbox Code Playgroud)
这开始看起来有点......丑陋.每次实施新供应商的API时,我都需要将myapp.suppliers.api更改为:要求新供应商的方法并重新编译.
现在我正在上一级工作,我想从supplier2购买一个小部件. …
abstraction ×10
clojure ×3
oop ×3
protocols ×2
android ×1
controls ×1
function ×1
inheritance ×1
java ×1
multimethod ×1
namespaces ×1
php ×1
repeat ×1
scala ×1