我正在设置一个 C# Asp.Net Core Api,它将在未来大幅增长。因此,我试图尊重干净代码架构,以我的域为中心,没有任何依赖性和周围的一切:
public abstract class Entity
{
public Guid Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我目前正在实施存储库。我的问题是,对于 mongoDb,似乎必须提供属性[BsonId],或者在我的实体中使用 BsonId。但这意味着在我的实体项目中添加 mongoDb 引用,我不是它的忠实粉丝。
public interface IRepository<TDocument> where TDocument : Entity
{
IQueryable<TDocument> AsQueryable();
IEnumerable<TDocument> FilterBy(
Expression<Func<TDocument, bool>> filterExpression);
IEnumerable<TProjected> FilterBy<TProjected>(
Expression<Func<TDocument, bool>> filterExpression,
Expression<Func<TDocument, TProjected>> projectionExpression);
Task<TDocument> FindOne(Expression<Func<TDocument, bool>> filterExpression);
Task<TDocument> FindById(Guid id);
Task InsertOne(TDocument document);
Task InsertMany(ICollection<TDocument> documents);
Task ReplaceOne(TDocument document);
Task DeleteOne(Expression<Func<TDocument, bool>> filterExpression);
Task DeleteById(Guid id);
Task DeleteMany(Expression<Func<TDocument, bool>> filterExpression);
}
Run Code Online (Sandbox Code Playgroud)
在我在 Clean Architecture 上找到的示例中,他们大多使用实体框架,不需要绝对属性即可工作。 …
我是第一次学习干净和垂直切片架构,如果我们使用 ASP.NET Core Identity,我很难理解授权和身份验证的适用范围。而且,在某些情况下,感觉将身份用户(使用用户名、密码、电子邮件等)与任何用户相关的域实体分开会很棘手。
例如,如果我们有一个使用 ASP.NET Core MVC、ASP.NET Core Identity 的解决方案,那么示例项目结构可能如下:
演示/WebUI 项目:
app.services.InjectInfrastructure(); // same for application
Run Code Online (Sandbox Code Playgroud)
基础设施项目:
应用项目:
领域项目:
因此,我们可以有一个具有以下流程的场景:
我很难分离身份验证问题的情况是系统中的用户根据他们在登录时所做的选择具有不同的角色和权限。
例如,一个教育应用程序,教师可以选择他们当前代表的学校。在一所学校中,他们可能担任某种角色(例如校长),而在另一所学校中,他们可能担任特权较小的角色。
在这样的场景中,角色、应用程序用户(都是身份问题)似乎与域(将容纳不同的学校和每个学校拥有的角色)紧密耦合。
我的首要问题是,我们如何以干净的架构方式使用 ASP.NET 身份来实现这种身份验证/授权场景?
目前这种情况带来了多个问题:
有没有人曾经遇到过/使用干净的架构实现过这样的系统?任何人对此有任何见解都会很棒!
asp.net-mvc asp.net-identity asp.net-core clean-architecture
我的问题如标题所示。
Room 有注释@Entity,在 Room 中,这被视为Entity.
但在 Clean 架构中,当使用 Domain 层时,Entity也会使用 an。
例如,领域层内的用例使用的实体。
然而,我认为 Room 认为的Entity是 Clean 架构的 aDTO或POJOas。
话虽如此,在创建应用程序时,我应该在表示层、领域层和数据层中为我的模型命名什么?
我最近读完了 Unckle Bob 的《Clean Architecture》一书。他在那里写道
三个范式。三个约束。结构化编程对直接控制转移施加了纪律。面向对象编程对间接控制转移施加了纪律。函数式编程对分配施加纪律。这些范式中的每一个都带走了一些东西。他们都没有添加任何新功能。每一次都增加了纪律并降低了能力。
我的应用程序具有以下文件夹结构
app
core
features
feature1
domain
entities
entity1
entity2
entity3
entity4
entity5
entity6
data
models
model1
model2
model3
model4
model5
model6
presentation
feature2
domain
entities
entity1
entity2
entity3
entity4
entity5
entity6
data
models
model1
model2
model3
model4
model5
model6
presentation
Run Code Online (Sandbox Code Playgroud)
这两个功能的模型 1 到 6 完全相同,并且随着应用程序的扩展,还会有更多功能出现。这变得越来越难以维护。干净的架构是否允许跨多个功能共享模型和实体?这是通过核心文件夹完成的吗?
我花了一周的时间试图将 hilt 依赖注入添加到我的示例笔记应用程序中,android studio 在发生错误后一直向我抛出错误。无论如何,这让我很生气,因为 AppModule我一直在尝试将我的房间数据库注入到应用程序中存储库,然后我的应用程序存储库到我的用例类,最后将用例类注入到我的用例类中sharedViewModel
,所以这是我的AppModule对象:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideNoteDatabase(app: Application): NoteDatabase {
return Room.databaseBuilder(
app,
NoteDatabase::class.java,
NoteDatabase.DATABASE_NAME
).build()
}
@Provides
@Singleton
fun provideNoteRepository(db: NoteDatabase): NotesRepo {
return RepoImplementation(db.noteDao())
}
@Provides
@Singleton
fun provideNoteUseCase(repo: NotesRepo): NoteUseCase {
return NoteUseCase(
getNotesUseCase = GetNotesUseCase(repo),
deleteNoteUseCase = DeleteNoteUseCase(repo),
updateNoteUseCase = UpdateNoteUseCase(repo),
insertNoteUseCase = InsertNoteUseCase(repo)
)
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的应用程序类:
@HiltAndroidApp
class Application : Application()
Run Code Online (Sandbox Code Playgroud)
我的编辑片段:
@AndroidEntryPoint
class EditFragment : Fragment() {
private var _binding: …Run Code Online (Sandbox Code Playgroud) 一些Android多模块架构示例表明领域层依赖于数据。其他人则相反。
\n\n\n\n\n领域层是位于 UI 层和数据层之间的可选层。
\n
与此同时,proandroiddev.com 上的另一篇文章说:
\n1.
\n\n\n域层\xc2\xa0是洋葱的最内部部分(与其他层没有依赖关系),它包含\xc2\xa0实体、用例和存储库接口。\xc2\xa0用例组合来自1个或多个存储库接口的数据。
\n
\n\n最常见的错误之一是让您的应用程序由数据层/特定数据系统驱动。
\n
\n\n\n域层不依赖于数据层。
\n
那么您能否描述一下哪种方法更适合 Android 多模块?为什么?
\narchitecture android clean-architecture android-architecture android-multi-module
为了在Android上使用mvp模式实现"干净"架构,建议将android框架视为插件,而不是将任何知识产权感知依赖项泄漏到演示者层.使用rxjava,如果我有一个用于将数据"推送"到视图层的演示者,我可能希望有这样的逻辑:
public interface SearchPresenter {
interface ViewLayer {
void updateResults(List<SearchResult> searchResults)
}
void bind(ViewLayer viewLayer);
void unbind();
}
public class SearchPresenterImpl implements SearchPresenter {
ViewLayer viewLayer;
CompositeDisposable compositeDisposable;
@Override
public void bind(ViewLayer viewLayer) {
this.viewLayer = viewLayer;
compositeDisposable = new CompositeDisposable();
compositeDisposable.add(
searchInteractor.getSearchResults()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::refreshView));
}
private void refreshView(List<SearchResult> searchResults) {
//send the results back to the view layer to update a RecyclerView
viewLayer.updateResults(searchResults)
}
@Override
public void unbind() {
compositeDisposable.dispose();
}
Run Code Online (Sandbox Code Playgroud)
但是,通过观察'AndroidSchedulers.mainThread()',这会强制依赖于:
import io.reactivex.android.schedulers.AndroidSchedulers
Run Code Online (Sandbox Code Playgroud)
在这一点上,我的主持人现在知道android并且与之相关; 我想避免.
处理这个的建议方法是什么,以保证结果在Android的UI(主)线程上传递给ViewLayer,而演示者维护没有任何与Android相关的依赖?
我正在使用干净的架构开发android项目.我有以下课程:
public abstract class RxBaseInteractor<T, Params> {
private final CompositeDisposable disposables;
public RxBaseInteractor() {
this.disposables = new CompositeDisposable();
}
abstract public Observable<T> buildUseCaseObservable(Params params);
public void execute(DisposableObserver<T> observer, Params params) {
Preconditions.checkNotNull(observer);
final Observable<T> observable = this.buildUseCaseObservable(params)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
addDisposable(observable.subscribeWith(observer));
}
public void dispose() {
if (!disposables.isDisposed()) {
disposables.dispose();
}
}
protected void addDisposable(Disposable disposable) {
Preconditions.checkNotNull(disposable);
Preconditions.checkNotNull(disposables);
disposables.add(disposable);
}
}
Run Code Online (Sandbox Code Playgroud)
所以执行(..)获取DisposableObserver然后有一个dispose()方法被调用来处理这个observable.
在我的例子中,observable可能来自WebApi使用Realm进行改造或缓存.
现在在演示者onDestroy()中,我调用了interactor.dispose(),如:
@Override public void destroy() {
super.destroy();
myInteractor.dispose();
}
Run Code Online (Sandbox Code Playgroud)
从视图中调用之后调用:
@Override public void onDestroy() {
super.onDestroy();
if …Run Code Online (Sandbox Code Playgroud) 我已经看到了 MVP 架构的好例子(这里和这里)。两者都只提供简单的交互器,但我想知道如何处理更复杂的用例,包括在其他用例中重复的步骤。
例如,我的 API 需要令牌来验证任何调用。我创建了一个交互器来获取该令牌 ( GetToken)。我想获取用户的上次登录日期 ( GetLastLoginDate),然后获取该日期和现在 ( GetVersionChanges)之间发生的更改列表。
那些交互者应该被链接在哪里?我想将它们分开,因为其中一些在代码的其他部分被重用。我想出了两个解决方案。
演示者应该链接所有交互者。只要用例不复杂并且没有很多先决条件,这个解决方案就可以工作。在我看来,这不是正确的地方,因为它给演示者带来了另一项责任。
Interactor 可以使用许多存储库(那时没有破坏干净的架构规则)。为什么不在TokenRepository其他交互器中使用?因为获取令牌比到达存储库要复杂得多。在其他交互器中重复这些步骤不会重用已经存在的代码。
这两种解决方案都有其缺陷,并且都违反了基本原则(DRY,单一职责原则)。
android ×6
kotlin ×2
rx-java ×2
.net-core ×1
android-mvp ×1
android-room ×1
architecture ×1
asp.net-core ×1
asp.net-mvc ×1
c# ×1
dagger-hilt ×1
dispose ×1
entity ×1
flutter ×1
mongodb ×1
mvp ×1
mvvm ×1
observable ×1
oop ×1
use-case ×1