0

With the purpose of learning Hilt I started "migrating" my multi-module Kotlin app from using classes with static methods as helpers to Hilt injection.

After a lot of headaches, now everything's going fine, and I could say I'm happy and in the 80% of the migration, but suddenly a question have come to my mind and stopped coding.

I have some modules, like "Core", "Common", "Repository", etc, and each have its own helpers (although I have to say that most of them are in "Common"), the other are "Repositories", "DAO", "Services" and so) and I wonder to know if the best practice (if there is one regarding this) is to do injection for everything (like a screen helper with methods to convert sp to px and so, language helper to get string from resources, etc), or injection should be only used for context, database, repos, services and that kind of classes.

I'm happy with my progress, and I'm quite sure I'm going in the right direction to make a complete decoupling, but wanted to know what do you have to say about that.

Thanks in advance.

1 Answer 1

2

There is no best practice for this. Instead, consider the reasons why an object instance is desirable:

  • The object needs to maintain state in between method invocations.
  • You need to support polymorphism.

There are other reasons, but these are typically the main ones.

Helper methods which are idempotent, and do not need to maintain state, are perfectly fine as static methods. Any external dependencies can be passed as method parameters. Logic like converting sp to px is not likely to have side effects, and is therefore idempotent.

Even when writing unit tests, you can call static methods. Logic is just logic. Data access objects typically implement an interface or abstract class because it is desirable to mock those objects for testing purposes, not because it is some "best practice".

It is not surprising to me that a significant portion of your helper methods work just fine as static methods. Many such methods are little more than handy wrappers for an algorithm that, given some input, always returns a predictable result without affecting anything outside of its own scope.

Don't convert everything to an object. If the helpers do not need to implement polymorphism, or need to track state, keep it simple, and keep them static.

5
  • What a great and detailed explanation @Greg Burghardt, Of course I'll mark it as correct, but let's see if I understood correctly with same examples of my project: I'll enumerate the most important classes of my project and write if I should convert them to objects according what I understood of your explanation. please let me know on each if I'm correct. Commented Jul 27, 2022 at 22:14
  • 1. Context => of course Inject 2. Database => clearly Inject 3. Helper classes with methods like Locale getStringResourceByName, Utils DP2PX, Utils isTablet Utils generateRandom... => Use as static methods 4. Repository (module with methods that access database) => Inject? (put Inject because they're subject to change if database engine changes) 5. Services (module that connect app with repository) ?? Maybe static... Again, thanks for your time :) Commented Jul 27, 2022 at 22:14
  • @DiegoPerez: 4 is definitely inject because it ultimately connects to the database. You should define an interface for your repositories. Then you can write unit tests for code needing a repository. Consider doing some research and asking follow-up questions. Commented Jul 27, 2022 at 23:31
  • Hello @Greg Burghardt, sorry if I'm "abusing" of your time, but I have another question: I'm refactoring so some classes that don't need to act as objects are just static methods classes using Kotlin's "companion object", but in this classes I need dependencies inside companion object as well (for example context or -in my case- an AppSettings class instance), but I'm not sure how to provide that dependencies. Should I create a field with the dependency and before calling a method set that field value from the caller? Ex: AWUtils.app = app > var isTablet = AWUtils.isTable? Is it OK this way? Commented Jul 29, 2022 at 20:04
  • @DiegoPerez: if this is a conceptual question, I would post a new question on this site. Commented Jul 29, 2022 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.