标签: clean-architecture

清洁体系结构和缓存失效

我有一个试图遵循清洁架构的应用程序,我需要做一些缓存失效,但我不知道应该在哪一层做这个.

为了这个例子,假设我有OrderInteractor2个用例:getOrderHistory()sendOrder(Order).

第一个用例是使用a OrderHistoryRepository,第二个用例是使用a OrderSenderRepository.这些存储库是具有多个实现(MockOrderHistoryRepository以及InternetOrderHistoryRepository第一个)的接口.该OrderInteractor只与经过界面论文库为了隐藏真正实现交互.

Mock版本非常虚拟,但Internet历史存储库的版本将一些数据保留在缓存中以更好地执行.

现在,我想实现以下内容:当成功发送订单时,我想使历史记录的缓存无效,但我不知道应该在哪里执行实际的缓存失效.

我的第一个猜测是一个补充invalidateCache()OrderHistoryRepository,并在结束使用此方法sendOrder()交互器内的方法.在InternetOrderHistoryRepository,我将只需要实现缓存失效,我会很好.但我将被迫在其中实际实现该方法,MockOrderHistoryRepository并且向外部暴露了存储库执行某些缓存管理的事实.我认为OrderInteractor不应该知道这个缓存管理,因为它是Internet版本的实现细节OrderHistoryRepository.

我的第二个猜测是InternetOrderSenderRepository当它知道订单已成功发送时执行缓存失效,但它会强制此存储库知道InternetOrderHistoryRepository,以便获取此repo用于缓存管理的缓存密钥.而且我不希望我OrderSenderRepository依赖于OrderHistoryRepository.

最后,我的第三个猜测是使用某种CacheInvalidator(无论名称)接口与Dummy存储库被模拟RealInteractor使用的实现以及使用Internet存储库时的实现.这CacheInvalidator将注入到,Interactor并且选定的实现将由Factory构建存储库和存储库提供CacheInvalidator.这意味着我将拥有MockedOrderHistoryRepositoryFactory- 正在构建MockedOrderHistoryRepositoryDummyCacheInvalidator- 以及InternetOrderHistoryRepositoryFactory- …

java android clean-architecture

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

休眠业务对象可以用作干净架构中的实体吗?

在我们的项目中,我们使用 eclipse hibernate 插件生成的类进行持久化。生成的类具有以下结构。

MyClass extends BaseMyClass //POJO's, that are refenced in the hbm
files
Run Code Online (Sandbox Code Playgroud)
MyClassDAO extends BaseMyClassDAO //DAO objects that use hibernate
session objects to provide CRUD API's for working with DB
Run Code Online (Sandbox Code Playgroud)

我的问题是,如果我们使用映射文件中使用的 POJO 类作为最内层的实体,是否会违反 Uncle Bobs 的清洁架构。

在这种情况下,hibernate 特定的 DAO 类将属于最外层,而 UseCases 层将通过提供要实现的接口与该层进行通信。

java hibernate hexagonal-architecture onion-architecture clean-architecture

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

Repository pattern with changing data on server over time

I am following Clean Architecture proposed by famous Robert C. Martin. The birds eye view of Clean Architecture looks like as follows:

在此处输入图片说明 However right now my concern about Repository pattern modification. Basics steps of Repository pattern are:

  1. Search in-memory cache AND provide data to app layer
  2. If not found, search local data source AND sync to in-memory cache AND provide data to app layer
  3. 如果没有找到,搜索远程数据源并同步到本地数据源并向应用层提供数据

严格按照上述步骤操作,如果本地数据源中存在数据,它将永远不会从远程数据源同步,而数据可能会在远程更改。我该如何修改才能处理这种情况?一个想法出现在我的脑海中,写在下面,但我确实在寻找更好的解决方案。

我的想法是跟踪本地数据库中每条记录的上次同步时间。如果上次同步时间超过阈值时间,则自动同步。

android repository-pattern data-layer restful-architecture clean-architecture

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

在 Clean Architecture 中使用 NSFetchedResultsController

我已经在没有太多运气的情况下寻找了答案。这个问题几乎相同,但答案不是很清楚(至少对我来说!): 它是 VIPER 架构中 NSFetchedResultsController 的位置?

NSFetchedResultsController 对于 iOS 应用程序来说似乎是一种非常有用的方法,但是我所看到的所有示例都将其置于 ViewController 层——至少,VC 成为了一个委托。在 Clean Architecture/Viper 中,模型层与视图层非常脱节,我无法弄清楚 NSFRC 在这样的架构中是如何使用的。对上述问题的回答意味着交互器应该是一个委托,但这没有意义——然后托管对象将呈现给交互器,而不是 PONSO。也许我对它的理解还不够好,但是 (a) 它在 Clean Architecture 中占有一席之地吗?(b) 如果是,那么需要正确的 Swift 实现模式吗?

core-data ios swift viper-architecture clean-architecture

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

Golang交易API设计

我正在尝试使用Go 遵循Clean Architecture。该应用程序是一个简单的图像管理应用程序。

我想知道如何最好地设计我的存储库层的接口。我不想将所有存储库方法组合到一个大接口中,就像我发现的一些示例一样,我认为在Go中,小接口通常是首选。我认为与管理映像有关的用例代码不需要知道存储库还可以存储用户。所以我想有UserReaderUserWriterImageReaderImageWriter。复杂之处在于代码需要是事务性的。事务管理属于“清洁体系结构”的范畴尚有争议,但我认为用例层需要能够控制事务。我认为,单笔交易属于业务规则,而不是技术细节。

现在的问题是,如何构造接口?

功能方法

因此,在这种方法中,我打开一个事务,运行提供的功能,并在没有错误的情况下提交。

type UserRepository interface {
    func ReadTransaction(txFn func (UserReader) error) error
    func WriteTransaction(txFn func (UserWriter) error) error
}

type ImageRepository interface {
    func ReadTransaction(txFn func (ImageReader) error) error
    func WriteTransaction(txFn func (ImageWriter) error) error
}
Run Code Online (Sandbox Code Playgroud)

问题:不,我不能在单个事务中轻松编写用户和图像,我必须为此创建一个额外的UserImageRepository接口并提供单独的实现。

作为存储库交易

type ImageRepository interface {
    func Writer() ImageReadWriter
    func Reader() ImageReader
}
Run Code Online (Sandbox Code Playgroud)

我认为这与功能方法非常相似。它不能解决多个存储库结合使用的问题,但至少可以通过编写一个简单的包装器来实现。

一个实现可能看起来像这样:

type BoltDBRepository struct {}
type BoltDBTransaction struct { *bolt.Tx }
func …
Run Code Online (Sandbox Code Playgroud)

architecture design-patterns transactions go clean-architecture

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

干净的架构登录流程

我正在我的 Android 应用程序中开发一个具有干净架构的登录屏幕。

成功使用登录时,我需要将令牌保存到共享首选项。

在启动画面上,我需要检查用户是否登录

所以我的问题是哪里是完美的地方:

  1. 保存令牌

我应该在 LoginUseCase(域层)中保存令牌吗

class LoginUseCase(private val userRepository: UserRepository, private val schedulerProvider: SchedulerProvider) {

    fun execute(username: String, password: String): Single<Token> {
        return userRepository.login(username, password)
            .andThen(userRepository.saveToken(.....)
            .subscribeOn(schedulerProvider.getIOScheduler())
            .observeOn(schedulerProvider.getUIScheduler())
    }

}
Run Code Online (Sandbox Code Playgroud)

或者我应该将保存令牌作为用例并将令牌保存在演示层中

class LoginPresenter(private val view: LoginContract.View,
                     private val setLoginStateUseCase: SetLoginStateUseCase,
                     private val loginUseCase: LoginUseCase,
                     private val schedulerProvider: SchedulerProvider): LoginContract.Presenter {

    private val compositeDisposable = CompositeDisposable()

    override fun performLogin(username: String, password: String) {

        if (username.isNullOrEmpty() || password.isNullOrEmpty()) {
            view.onShowLoginError("Field should not be empty")
        } else {
            view.showLoading() …
Run Code Online (Sandbox Code Playgroud)

android clean-architecture

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

干净的架构:在不同的层共享相同的模型/实体

在我干净的架构 Android 应用程序设置中,我为每一层(数据、域、表示)都有自己的 Gradle 模块。我也为每一层都有自己的模型/实体,它们使用映射器从一层转换到另一层。这导致我有很多 kotlin 数据类,代表基本相同的东西,但在不同的层。这对我来说听起来不对。

简单的例子:

数据层- Android 库模块

@JsonClass(generateAdapter = true)
data class BuildingEntity(
    @Json(name = "u_id")
    val id: String,

    val name: String,

    val latitude: Double,

    val longitude: Double,

    @Json(name = "current_tenants")
    val tenants: List<TenantEntity>? = null
)
Run Code Online (Sandbox Code Playgroud)

领域层- 纯 Kotlin 模块

data class Building(

    val id: String,

    val name: String,

    val location: CoordinatePoint,

    val tenants: List<Tenant>? = null
Run Code Online (Sandbox Code Playgroud)

表示层Android 应用模块

data class BuildingModel(

    val id: String,

    val name: String,

    val location: LatLng,

    val …
Run Code Online (Sandbox Code Playgroud)

architecture android kotlin clean-architecture

5
推荐指数
2
解决办法
2857
查看次数

干净的架构 - 在哪里放置输入验证逻辑?

也许在应用程序中,我有一个功能允许用户使用带有一些验证逻辑的表单发送反馈:

  • 名称可以为空
  • 反馈信息应至少为 5 个字符

您会将这些验证逻辑放在何处,domain layer作为业务逻辑还是presentation layer作为 UI 逻辑?

这些逻辑适用于所有应用程序(android、iOS、web)。请注意,我们已经进行了服务器端验证。

coding-style business-logic clean-architecture

5
推荐指数
2
解决办法
5179
查看次数

Spring Boot 微服务中的客户端库

三年前,我作为开发人员参与了我的第一个微服务项目。我对微服务概念一无所知。该项目正在构建为 Spring Boot 微服务。一般来说,没有什么特别的,但所有项目都应用了基于客户端库的微服务之间的集成方式,这种方式颇有争议。我认为那些客户端库是通过幼稚的方式制作的。我会尽量给出他们的主要想法。

项目中有三个模块:*-api,*-client*-impl. 这*-impl是一个成熟的 REST 服务,并且*-client是此 REST 服务的客户端库。*-impl*-client模块依赖于*-api(它们*-api作为 maven 依赖项导入)。在*-api又包含哪些应该由执行Java接口@RestController从类*-impl模块,并通过实现客户端库的功能,这REST服务(通过类RestTemplateFeignClient)。另外,*-api通常包含可被覆盖的DTO Bean验证扬鞭注释。在某些情况下,这些接口可能包含来自 Spring-MVC 的@RequestMapping注释。因此@RestControllerFeignClient同时的实现继承了@RequestMapping

*-api

@ApiModel
class DTO {
  @NotNull
  private String field;
  // getters & setters
}

interface Api {
  @RequestMapping("/api")
  void method(DTO dto)
}
Run Code Online (Sandbox Code Playgroud)

*-客户 …

client-library spring-boot microservices spring-cloud clean-architecture

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

干净架构中的Android特定代码

我已经阅读了多个针对 android 的简洁架构教程,但它们都具有非常基本的结构和简单的网络调用,这让我感到疑惑。

  1. 我想知道的是我应该把处理加速度计、地理围栏、位置、短信和类似的代码放在哪里?我最初的想法是将它们放在单独的存储库中。但是由于这些是可以启动或停止的单独的长时间运行的进程,所以感觉不对。我已经尝试将这些类从存储库重命名为服务,以便更清楚地表达意图。不过好像还是有点不对劲。什么是好的选择?

  2. 为了能够接收发送的短信状态,我需要注册一个接收器。谁应该为此负责?存储库本身在收到对 sendSms() 的调用后是否应该注册该接收器,发送消息并释放接收器,或者 UseCase 首先必须检查 SmsRepository 是否已启动,如果没有启动它,从而注册接收器,然后调用 sendSms() 方法?或者也许应该采取另一种方法在应用程序启动时注册接收器并在关闭时取消注册?

  3. 这是一个合适的包结构吗?

在此处输入图片说明

编辑: 4. 如果您想不断地侦听服务器结果该怎么办?您是直接从 viewmodel 订阅存储库还是在完成后继续调用相同的用例(其目的是获取一次结果)?我对 UseCase 的理解是它只返回单个结果并且不应该是可订阅的。

android clean-architecture

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