From project to project, we notice that our code performs the same functions and looks almost the same. This makes us wonder - are we not doing the extra work by rewriting the same thing? We begin to copy classes from previous projects and still understand that we are doing something wrong and are right - just copying classes from a project to a project, we can easily lose / replace / wipe something, and if our team leads several more projects simultaneously, then error detection in borrowed classes will require manual changes in all projects. Tired of stepping on this rake, we decide that we need a common code that will be shared on all our projects and any changes in it will be easily pulled. Yes, we are creating our library of reusable components! You will learn about different ways to organize your library, about all the pros and cons of approaches under cat :)
There are several ways to organize our common code base:
Any library for our application is just a lot of classes organized in a certain way. Each time we connect some Retrofit or Dagger in build.gradle , we load the library as an aar / jar archive from one of the library publishing platforms. The most popular library publishing platforms are JCenter and MavenCentral. The developers of the library work in their repository on the new version, and when the version becomes ready to go out into the world, they publish it on one of the platforms and say "Hey, we have released a new version of our top library!". All that remains to be done for developers who use this lib in their projects is to change the version in build.gradle and enjoy new features. Conveniently? Not that word!
But how convenient is this approach if our library is developing and every day updated with new features by different developers from different projects of our team? Let's see how it looks in practice.
We create the repository of our library, add some features there, debug it, and are ready to share it with our team. Then we will learn about such words as JCenter, MavenCentral, Bintray, Jitpack.io ... all these are platforms for publishing libraries. Now the main platform for Android projects is JCenter. If you create a project, you will see that in the build.gradle (project level) in the repositories, JCenter is specified
repositories { google() jcenter() }
That is, if the developer wants to connect your library, then it will be enough for him to connect it to build.gradle of the module level.
The easiest way to publish the library for me seems to be Jitpack.io, a couple of steps and your library is ready to use.
If we created a library and uploaded it to the repository, then the rest of our team has only the received jar / aar archive. In order for the whole team to be able to work on any - each developer must deflate the library repository and make changes to it.
When developing and using libraries, one has to deal with such a concept as versioning. That is, the set of changes in the library that we want to publish must be fixed by the version. This will help when updating the library to a new version to understand how serious / breaking changes have been made, thanks to the adopted versioning scheme.
In order to verify that the changes made fulfill what we intended - it is necessary to check the behavior of the written code in the project. We raise the version of the library and ... here is one of the bottlenecks of this approach. Our library and the project are in different repositories, which means that we cannot just get library classes in the project. We have 2 options to check the new library code:
In the previous approach, we faced the difficulty of getting new code at the development / debugging stage in the project, since the library and project code are in different repositories and studio projects. The Git Submodule approach also involves the use of separate repositories, but allows the main project to get the library as a module using Git. This means that the library code will be available in the project and all changes will be immediately available in the project!
Submodules allow you to contain one Git repository as a subdirectory of another Git repository. This makes it possible to clone another repository inside the project, storing the commits for this repository separately.
Simply put, we have 2 repositories: a project and a library. The project repository stores the library code and a link to the status of the library repository. So Git understands what state (version) of the library the project needs.
Read more about how Git Submodule works here.
In the Git Submodule approach, team work on the library is organized as follows:
When the pool was poured into master , and the teams are notified of the library update, they are not aware of how global the changes in the new version are. After all, the approach with Git Submodule does not require any versioning scheme. But this problem is easily solved by introducing a versioning scheme. All that is required is to write a version and description of what has been changed and added to the description of the pool request in the master branch. Then the developers will understand how much they can now really upgrade to the new version of the library. It sounds great, but the question is:
Yes, the studio does not know how to commit separately to the lib connected by the submodule. I use SourceTree to solve this problem. This application is for Windows and Mac, and for Linux there is GitKraken.
Git Subtree is an enhanced version of Git Submodule. In Git Subtree we tried to solve the problems that developers encountered while working with Git Submodule; there is a good article on the hub that describes the differences between the tools. Although they work differently, they solve one problem.
Git Submodule / Subtree tools are great for solving the problem of creating a common code base for a team involved in several projects. One of the important advantages is the instant verification of new code on the project after making changes to the library. In this, the standard approach of publishing a library to JCenter or MavenCentral is inferior. If you decide to take Git Submodule / Subtree to your team, think in advance about the versioning scheme, and create rules / plugins to control versioning.
Great reuse to everyone!