preface

When the needs of the project continue to expand, when the development team continues to grow, when new technologies continue to emerge, when the quality of software continues to improve, I still can’t break up with you, CAN’t break up with you. I don’t make any comments on the students who sing aloud. If you do encounter the above problems and do not evolve your architecture, chances are that the problems you encounter are supernatural events. So the core point here is architecture, so what is it? What good can it do?

architecture

What exactly is architecture? I’m not good enough to tell you. I’m not. I can tell you what I learned in the learning process, I think architecture is a contract, what contract? In order to better research and development efficiency, scalability and stability, more accurate risk prevention and control capabilities. That might be a little abstract.

As a senior homebody, the distance between bed and door is the longest in the world, and the last time I went to the bathroom, it seemed like we were never alone, did we, Mac? Err, that’s a bit of a digressions. I might leave my stuff in the place I like after I use it, but it’s just a bit disorganized in other people’s eyes. It’s regular in my eyes. Because I always follow this rule, every book has a place that I define for it. But my mom didn’t know that. Although she cleaned it up very well, she put the book in the wrong place. She probably didn’t know it, even if I asked her next time. To find the book, I had to go through it again. If we both follow a rule, a convention, a consensus that we’ve defined together. The book will always be there, and there will be rules on whether to add new books or remove them.

It can be seen that the benefits of architecture are not only the introduction of new technologies, but also the better experience of the product itself, but also the unified specification, which makes the structure clearer, more robust, and more convenient for team collaboration.

The above is not the topic of today, and the understanding of architecture is limited to my understanding. Compared to Android, we know more architectures called MVC, MVP, MVVM, etc. About this… The other person doesn’t want to talk to you and throws a link at you. A good article is made up of content and excellent comments, so take your time and enjoy it, forget it, buy one, get one free. Here, I jump right into today’s topic, the Clean architecture.

The Clean frame

Most of the time, when faced with a problem, we have to think from three directions: What, how and why. To quote a bigwig: The unthought life is not worth living. Therefore, do not just be satisfied with the fast food culture, often move the brain, do not look at the problem on the surface! Err, digress again… Let me start with what.

What

Concepts are always boring. If you don’t like them, you can directly skip to How or the summary of this chapter. However, concepts are also the most basic.

In our elegant tradition of No picture,say a J8, let’s start with a meaningless structure.

This picture may seem incredible to you, but for us professionals, it is also blindsided (manual funny). Let me briefly explain:

  • Enterprise Business Rules: Business objects
  • Application Business Rules: Used to process our Business objects, where the Business logic resides, also known as interactors
  • Interface Adapters: Get the data we need. The Presenters and Controllers are there
  • Frameworks and Drivers: Here are all the concrete implementations: UI, utility classes, base Frameworks, etc.

For the picture above, Mina can poke here.

After I explain, you may still be confused. Let’s look at another picture:

It seems to make more sense than the picture above. You know why? Because there’s a lot less writing. Ha ha. The rest of the content and my open source projects are based on this. Let me explain it separately.

Presentation Layer

Our performance layer here is based on MVP, and I think Clean itself is more abstract and independent of MVP. Those of you who are familiar with MVP know exactly what this layer is for. As always, here’s a picture first.

Does that look familiar? The P layer makes the V layer (Fragment and Activity) contain no logic except UI logic. Presenters in my open source project consist of multiple interactors. We’ll talk about that.

Domain Layer

As is clear from the diagram, this is mainly the interactor implementation class and business object. Speaking of truth, this should only belong to Java module, but sometimes our business object, may want to implement the entity class interface in the third-party library, have to be changed to Android module, temporarily did not think of a good way, there are big men who know can advise.

Data Layer

This is a Repository schema, which can be seen here. As far as I can tell, this pattern should be used whenever a project is complex and needs to be layered, and it makes clean of clean architecture more noticeable.

This is a concept, and I’m sure you don’t want to see it, so I’ll give you a brief introduction. If you want more details, you can poke here.

conclusion

Now let’s talk about my opinion, the latter is a more specific Android structure compared to the former. Insert a clean architecture dependency rule here: the inner layer cannot depend on the outer layer. The three also explain what they are used for, so why are they divided into these three, and what is the connection between them? I am a layman, so I should use the common saying that the domain layer does not feel the existence of the data access layer by using the Repository pattern from the data layer, that is, the original data is independent, and the business rules are not bound to the specific data, which data do you want? I’ll get it for you, but you don’t need to know where I got it from; So the domain layer doesn’t know anything about how the data layer is implemented, and the main job of the domain layer is you give me the data, so I have to use it, how do I use it? I make all the decisions; Then call back to render the UI to the presentation layer. Therefore, most of the business logic is at the domain level, which can be said to be the core of an APP. I think one of the most important design concepts is data-driven UI, which I’d like to give myself credit for, haha. In fact, if you have 13 numbers in your mind by now, you can jump to Why, because how to use it is already a concrete thing, and the architecture itself is a consensus, is abstract, from a Java perspective you can implement this interface with multiple classes. The following uses are just a little code representation of my understanding of the Clean architecture.

How

The following example is selected from my open source library CrazyDaily, taking Zhihu Daily as an example.

Data Layer

The data layer pulls data from our Repository, either in the cloud, on disk or in memory.

public interface ZhihuService {
    String HOST = "http://news-at.zhihu.com/api/4/";

    @GET("news/latest")
    Flowable<ZhihuNewsEntity> getZhihuNewsList();

    @GET("news/{id}")
    Flowable<ZhihuNewsDetailEntity> getZhihuNewsDetail(@Path("id") long id);
}

public class ZhihuDataRepository implements ZhihuRepository {
    ...
    @Inject
    public ZhihuDataRepository(HttpHelper httpHelper) {
        mZhihuService = httpHelper.getZhihuService();
    }
    @Override
    public Flowable<ZhihuNewsEntity> getZhihuNewsList() {
        returnmZhihuService.getZhihuNewsList() ... }... }Copy the code

The awkwardness here is that only cloud data is provided, which is obtained using a retrofit+ OKHTTP framework. The correct way would be to provide a Factory to ZhihuDataRepository instead of HttpHelper. The Factory gets the corresponding data according to different conditions. Like this:

 @Inject
  UserDataRepository(UserDataStoreFactory dataStoreFactory,
      UserEntityDataMapper userEntityDataMapper) {
    this.userDataStoreFactory = dataStoreFactory;
    this.userEntityDataMapper = userEntityDataMapper;
  }Copy the code

UserDataStoreFactory is a factory class that gets data from different places. UserEntityDataMapper is our wrapper class for data. Interface Adapters? ZhihuRepository ZhihuDataRepository implements ZhihuRepository, but ZhihuRepository is not the data layer, but the domain layer. Obviously, it is associated with the interface, but the content is independent. Yes, this is the legendary dependency inversion principle.

Domain Layer

public interface ZhihuRepository {

    Flowable<ZhihuNewsEntity> getZhihuNewsList();

    Flowable<ZhihuNewsDetailEntity> getZhihuNewsDetail(long id);
}

public abstract class UseCase<T, Params> {

    ...

    public UseCase() {... } protected abstract Flowable<T> buildUseCaseObservable(Params params); public void execute(Params params, DisposableSubscriber<T> subscriber) { ... }... } public class ZhihuNewsListUseCase extends UseCase<ZhihuNewsEntity, Void> { private final ZhihuRepository mZhihuRepository; @Inject public ZhihuNewsListUseCase(ZhihuRepository zhihuRepository) { mZhihuRepository = zhihuRepository; } @Override protected Flowable<ZhihuNewsEntity> buildUseCaseObservable(Void aVoid) {returnmZhihuRepository.getZhihuNewsList() ... }}Copy the code

It’s really perfect. It has nothing to do with the data layer. ZhihuRepository controls the data layer ZhihuDataRepository using an interface. It really feels like architecture is getting more and more interesting. I can handle most of our business logic here.

Presentation Layer

@ActivityScope public class HomePresenter extends BasePresenter<HomeContract.View> implements HomeContract.Presenter { private ZhihuNewsListUseCase mZhihuUseCase; . Inject // Multiple UseCase public HomePresenter(ZhihuNewsListUseCase zhihuUseCase...) { mZhihuUseCase = zhihuUseCase; . } @Override public voidgetZhihuNewsList() { mZhihuUseCase.execute(new BaseSubscriber<ZhihuNewsEntity>() { @Override public void onNext(ZhihuNewsEntity zhihuNewsEntity) { mView.showZhihu(zhihuNewsEntity); }}); } } public interface HomeContract { interface View extends IView { void showZhihu(ZhihuNewsEntity zhihuNewsEntity); . } interface Presenter extends IPresenter<View> { void getZhihuNewsList(); . } public class HomeActivity extends BaseActivity<HomePresenter> implements HomeContract.View { @Override protected voidinitData() { mPresenter.getZhihuNewsList(); . } @Override public void showZhihu(ZhihuNewsEntity zhihuNewsEntity) { ... }... }Copy the code

To tell the truth, I really don’t want to stick the code, it’s too troublesome, but if I don’t stick it, it’s not easy to understand, and what we help each other is the code, my eyes inexplicably sour. The performance layer is more of an MVP concept, so..

Simple logic, Activity retrievesdata (View) -> call the Presenter interface -> call the UseCase interface (Domain) -> call the Repository interface (Data) -> get the raw Data -> call the Repository (Data) – > callback UseCase (Domain) -> Callback Presenter (Presenter) -> Callback Activity (View)

If you don’t understand, buy a piece of tofu and kill yourself.

Why

How isn’t really important, but it takes up a lot of space.

Do you think Why is the most important? With this question in mind, let’s look at Why.

  • Easy to maintain
  • Easy to test
  • Very cohesive
  • Decoupled

High cohesion, low coupling gives me a headache. It’s easy to maintain, it’s easy to test, it’s easy to understand, it’s independent, let’s look at this:

  • Presentation Layer: Use Android Instrumentation and Espresso for integration and functional testing
  • Domain Layer: Use JUnit and Mockito for unit testing
  • Data Layer: Use Robolectric (because it relies on classes in the Android SDK) for integration testing and unit testing

I am ashamed to say that I did not write the test in the open source project. I believe I will add it in the future. I am not the irresponsible person to present the big guy’s open source project about clean, Android-CleanArchitecture.

SaoHua off

This is about the end of clean, if you have any questions, please feel free to contact me and discuss with me. Start with a bowl of chicken soup and learn to be at peace with life’s imperfections. Be comfortable with your emotions and know how to let them flow out naturally. Interestingly enough, one of my libraries, MTRVA, was influenced by my architecture. It’s a RecyclerViewAdapter equivalent to the Presenter layer, and we always have to process resources or data in Adapter, just like Activity. It lets you just focus on the UI logic. Some people say, my interface is simple, do not have to calculate anything, give me the list, setAdapter, done. Er… That’s not necessary. Similarly, a simple project does not require a complex architecture. Those of you who have seen the clean architecture from start to finish will clearly see that the clean architecture is cumbersome. Architecture is inherently evolving from requirement to requirement. Good luck building your own structure. Finally, thanks to those who have supported me all the time!

portal

Github:github.com/crazysunj/

Blog: crazysunj.com/