Yeah… it seems very acquainted isn’t it? Yes, that’s the default challenge construction A.S provide you with once you create a brand new challenge. We don’t have time and begin coding. We put networking stuff, repositories stuff, information sources stuff, and another stuff/libraries you’ll be able to assume off, we simply put all of it there, in our superior app module.
What if our app begin rising until the purpose it now has like +60 screens, some of this screens have complicated UI, or some of them use particular libraries like Lottie, just some of them have sockets connection, and so on…
Let me ask you a query, what do you assume goes to occur in your monolithic app on that case🧐? (Take a couple of seconds and give it some thought).
I’m going to handle you some of the issues that DEFINITELY gonna occur when your challenge grows. Let me know in the feedback if we thought the identical factors.
- You most likely didn’t understand however it is vitally probably that you’ve round dependencies between your options. Something like FeatureA calling FeatureB and vice-versa (I’ll be addressing you why that is dangerous for your challenge later).
- As I acknowledged earlier than, most likely just a few or only one of your options makes use of sure library, however like we solely have one module, and all our options reside inside that module, all of them can entry to any library that’s carried out right here, even when they don’t use/want it.
- If you modify just one of your options, the entire app module shall be recompiled. And consider, in case you have hundreds of options, makes use of dagger, and so on. That construct time generally is a looong time.
- If there are extra builders engaged on the identical challenge, the possibilities to break one thing are larger as you all can contact one thing that’s HIGHLY coupled to the remaining of the challenge.
- If you might be utilizing Kotlin you’ll be able to’t profit of modifiers like
protected, and so on. They are largely used for disguise courses that the modules that implement it doesn’t must entry.
And the listing can continue to grow and rising, however I believe you already understood the place I wish to go. How can we resolve all the issues listed earlier than and even enhance our code high quality 🧐?
Modular programming is a software program design approach that emphasizes separating the performance of a program into unbiased, interchangeable modules, such that every comprises all the pieces essential to execute just one side of the specified performance.
You can assume of modularization like flip some of your packages into small reusable items of code throughout your utility.
Let me present an instance of a monolithic and a modularized challenge (BTW IMHO the monolithic one could be very effectively organized and it’s extremely most likely to be modularized simply).
Aren’t they se similar 🤔?… Kind off. The variations between them is that the modularized challenge have not the issues we listed above. And even higher, it earn some issues:
- Faster construct occasions, as a result of if there’s a change in some module. Only that module shall be compiled once more. (Also, the modules that implement this module, however the profit continues to be there).
- Each module now implements ONLY the libraries it makes use of. Nothing extra, nothing much less, simply what the module want.
- You can configure your gradle for cache builds, do parallelism & extra!
- You can create experimental
appmodules, and check any new
libraryright here earlier than you set it in your actual app module.
- You can publish some of your libraries and obtain contribution of the neighborhood. Real case pattern? Timber
I copy this class into all of the little apps I make. I’m drained of doing it. Now it’s a library.
Even the official docs say that you need to modularize your challenge.
Before we get there, it’s essential know that there is no such thing as a solely ONE option to modularize your tasks. I’d say that there are thousand of methods to modularize any challenge, it simply relies upon.
The commonest manner of modularization you’ll find is modularization by clear structure layer, the place you solely have:
information— Android library module
area— Pure Java/Kotlin module
presentation— App Module
I began to modularize my tasks following that strategy, however after some time I spotted that it wasn’t sufficient… I felt one thing was lacking, one way or the other that sort of modularization may be even higher.
That was my breaking level 🤯, and I began to analyze extra & extra about modularization and I understand that there is no such thing as a solely ONE option to modularize your challenge, you could have hundreds of approaches round there, and is as much as you to take the perfect practices and take a look at it until you could have a strong, maintainable, testable, scalable code.
You should bear in mind the purpose of modularization
Small reusable self contained items of code
My recommendation for you is to begin with the issues which have much less dependencies on. Probably extracting your networking courses, or some utilities, and so on. Once you begin extracting these courses into it’s personal modules you’ll understand your code shall be getting cleaner and extra modular.
But, as all the pieces in life, it comes with a value. Your are going to face some challenges… however I’m certain you’ll overcome them 🤜🤛.
- Gradle — You’ll must take care of handle your gradle libraries dependencies & android min max SDK variations. You wont prefer to handle the variations manually for every module, it will possibly get tough. One of the perfect practices is to have a base gradle file and use it round your modules.
- Circular Dependencies — You need to remember that your modules depend upon one another on a cyclic manner, this recommendation is generally for your function modules. Like the pattern i listed initially (FeatureA 🔁 FeatureB). You may have a compile error as a consequence of round dependencies and also you received’t be capable of construct the challenge.
- Styles — This LOOKS like if it’s kinda tough, however just isn’t. All you must do is transfer your design system to at least one module, and implement that module in all of your function modules & app module.
- Navigation — Navigation between options it’s going to change into a brand new factor! now your options doesn’t know one another. There are some tips for this, you’ll be able to have an interface throughout function modules and its implementation be on the app module (your app module will implement all of your function modules on the finish) or you’ll be able to load your courses by certified identify (my favourite), or depend on libraries just like the navigation library, personally I wouldn’t advocate it for now as a result of I consider the navigation library just isn’t designed for modularized tasks. Check out this weblog the place I inform my expertise on manufacturing apps with it.
- DI — Dependency injection. For this half, the library you might be utilizing for DI will get an enormous participation. But the principal concept that works for me it doesn’t matter what library it’s, is the next: for my function modules I construct my DI modules graph inside their library modules after which inject these DI modules to the app graph in the app module. For another modules like utilities, networking, and so on, I’ll most likely assemble it’s DI modules in the app module.