我的'干净架构'Android应用程序中有3个gradle模块:'data','domain'和'presentation'."数据"和"呈现"都取决于"域名",但不是彼此.'presentation'保存Application类实现,'data'保存一些存储库单例的实现.
我想使用Dagger 2在Application中实例化存储库,但在这种情况下,我需要在'data'和'presentation'之间建立间接gradle依赖关系.从Clean架构的角度来看,这种依赖性看起来很丑陋,使得可以从"表示"访问"数据".将Dagger组件和模块代码放在单独的gradle模块'di'中会创建循环gradle依赖'data' - >'di' - >'data'.
有没有正确的方法将所有DI代码移动到单独的模块中?
android circular-dependency gradle dagger-2 clean-architecture
在开发 Android 应用程序并尝试遵循干净的架构指南时,最好的方法是什么(但不是非常严格 - 因为这对于较小的项目来说可能是矫枉过正的)。
就我而言,我不确定哪种方法是最好的(如果有最好的)关于 数据层,以及数据层是否应该在自己的模型类上运行,或者它是否可以直接在域层模型上运行。
此外,如果数据层应该在自己的模型类上运行,数据源是否应该像DB或API拥有自己的模型(例如用于API使用Retrofit和Gson带有Gson注释的模型类),然后映射到数据层模型,或者数据层模型本身应该是DBand返回的模型API(这意味着必须对数据层模型进行注释,以便Gson能够在Retrofitand 的情况下解析它Gson)。
这个项目就是这种情况: https : //github.com/android10/Android-CleanArchitecture/blob/master/data/src/main/java/com/fernandocejas/android10/sample/data/entity/UserEntity.java
下面的图片应该阐明我的意思的 3 种方法:
在图 1 中,DB和API返回特定的模型类。在它的情况下,API它可能看起来像(使用Retrofit和Gson):
class ArticleResponse(@SerializedName("source") val source: SourceResponse,
@SerializedName("author") val author: String?,
@SerializedName("title") val title: String,
@SerializedName("description") val description: String?,
@SerializedName("url") val url: String,
@SerializedName("urlToImage") val …Run Code Online (Sandbox Code Playgroud) 我刚开始阅读有关干净架构的文章,但对用例实现的定义感到困惑。
考虑一个具有一组函数的控制器类,这些函数在执行一些逻辑后接受 T 并返回 R
interface IController {
fun usecase1(param:T) : R
fun usecase2(param:T) : R
}
Run Code Online (Sandbox Code Playgroud)
现在我可以使用 IController 实例执行用例。
另一种方法是将每个用例定义为一个类并注入需要该功能的其他对象。
class UseCase1 {
fun execute(param:T):R {}
}
class UseCase2 {
fun execute(param:T):R {}
}
Run Code Online (Sandbox Code Playgroud)
将用例作为单独的单元与将其作为某个类的功能之间有什么优点/缺点?
IMO,单独的单元会增加构造和注入开销,而其他方法则存在“继承问题而不是组合”。哪条路是正确的?
我在我的应用程序中使用 Clean Architecture 模式和 MVVM 架构。所以我有用于单个操作的用例,例如 LoginUseCase、DownloadAttachmentUseCase 等。
我很好奇的是,如果我想在我的视图模型中链接多个用例,执行类似的操作,首先登录,一旦成功,下载附件。
我是否需要创建另一个单独的用例,例如 LoginAndDownloadAttachmentUseCase ?
您如何看待将持久性模型和领域模型分开?我读到,您不必将持久性问题与业务问题混合在一起(DDD、清洁架构、MartinFowler、Eric Evans 等等)。即便如此,我仍然在所有项目中看到领域模型直接用 ORM 注释进行注释,与持久化机制耦合的领域模型达到了贫血模型并违反了其他原则。
//PersistenceJPA entity
@Entity
@Table(name="training_cycle")
class TrainingCycle {
@Id
private Long id;
private String name;
@Column(name="discipline_id")
@JoinColumn(name="discipline_id")
private Long disciplineId; //Referencing by Id because Discipline is another Aggregate ROOT
//EmptyConstructor, getters and setters avoided
}
//PersistenceJPA entity
@Entity
@Table(name="training_cycle")
class Discipline {
@Id
private Long disciplineId;
private String name;
//EmptyConstructor, getters and setters avoided
}
Run Code Online (Sandbox Code Playgroud)
因此,如果你想遵循干净的原则,你需要拆分域和持久性模型(如下所示)以获得具有业务行为的域模型(这可以避免贫血模型并遵循SRP),因此你需要将域模型映射到当您想要与数据存储区交互时,持久化模型(使用诸如mapToEntity(DomainModel DM)和mapToDomain(PersistenceModel PM)之类的典型方法,可能在映射器/转换器中,也可能在存储库类中),反之亦然,当您想从数据库检索数据时。
class Discipline {
private DisciplineId disciplineId;
private String name;
public Discipline(DisciplineId disciplineId, String name) …Run Code Online (Sandbox Code Playgroud) 我正在使用 Clean Architecture 开发 Flutter 应用程序。现在我正在寻找一个图书馆或其他类似 ArchUnit 的东西。测试架构并确保包的正确访问。
您如何解决问题并确保符合架构。我很感激想法或替代方案。
我目前正在开发一个使用分层架构(Web /应用程序/基础设施/域)的.NET 5应用程序。如果我要遵循洋葱/干净架构模式,依赖关系应该仅朝一个方向流动,例如:
Web -> 应用程序 -> 基础设施 -> 域
我现在发现自己需要从应用程序层发送几封包含特定前端 URL 的电子邮件。这意味着应用程序层将了解 Web 层,从而打破依赖流。
示例用例流程如下:
在步骤 #3 中,我位于应用程序层,但需要 Web URL 来构建电子邮件正文。
我该如何解决这个问题?
我试图通过这个YouTube 教程遵循 Clean Architecture ,因此我在数据层中有一组模型对象来扩展实体对象。
由于我有很多模型,其中一些模型有很多字段,我希望使用json_serializable包来自动生成样板代码,这些代码是工厂以及与 Json 和 fromJson 转换器方法相关的样板代码。
但是运行时:
flutter pub run build_runner 构建
它失败:
[严重]由于类型原因,无法生成
fromJson代码。serversServer
我的数据架构如下,在数据层:
- HostModel extends Host(Entity)
- String name,
- List<ServerModel> servers,
- ServerModel extends Server(Entity)
- ... // many many fields
Run Code Online (Sandbox Code Playgroud)
然而,当且仅当所有实体类都用 注释时,@JsonSerializable(explicitToJson: true)我才设法使其工作。
这对我来说非常困扰,因为我了解到清洁架构通过层分离所有关注点并遵循 SOLID 原则。所以我认为实体不应该“意识到”原始模型。并且反序列化方法应该可以用任何其他方法(例如 XML)替代,这显然违反了这里的原则。
我该如何解决这个问题?谢谢您的帮助!
我正在使用分页 3 的干净架构并尝试填充lazyColumn。
我的数据层模块中有以下类,我不想将 PagingData 传递到域层,因为我想让域不受任何 Android SDK 的影响。
class RepositoryImp @Inject constructor(
private val foodService: FoodService,
private val foodDatabase: FoodDatabase) : Repository {
@OptIn(ExperimentalPagingApi::class)
override fun fetchAllComplexSearch(): Flow<ResponseState<List<ComplexSearchEntity>>> {
val pagingSourceFactory = { foodDatabase.foodDao().fetchAllComplexSearchPaging() }
val pagingDataResult = Pager(
config = PagingConfig(pageSize = ITEMS_PER_PAGE_DEFAULT),
remoteMediator = ComplexSearchRemoteMediator(
foodDatabase = foodDatabase, foodService = foodService
),
pagingSourceFactory = pagingSourceFactory
).flow
val data = pagingDataResult.map { pagingData ->
pagingData.map { complexSearchModel ->
ResponseState.Success(
listOf(
ComplexSearchEntity(
complexSearchModel.id,
complexSearchModel.title,
complexSearchModel.image,
complexSearchModel.imageType
)
)
) …Run Code Online (Sandbox Code Playgroud) android clean-architecture android-jetpack-compose android-paging-3