Tip #1 — Use dependency injection.
Dependency Injection is not a library, it is a pattern and you’ve probably used it several times. Ever pass an instance to a constructor? Well, you have used constructor injection.
Tip #2— Limit the class visibility as much as you can
For small code bases it might be okay to have everything public. However, as your code-base and your team grows, I find much more beneficial to expose only what is needed.
Exposing only what’s needed reduces the cognitive complexity of code bases. Something important if you want your team to scale gracefully.
Tip #3 — Package-by-feature rather than by-functionality
Very subjective. I have develop in code-bases that follow package-by-feature and package-by-functionality.
I always found more difficult to limit the visibility of classes (Tip #2) when the packages are organized by functionality, often times finding myself having to have almost all public.
Tip #4 — Immutability everywhere
Tip #5 — Use GIT
Maybe this tip should say, use version control. But I make it more explicit to GIT as I find it far superior to any other version control system.
Tip #6 — Try master-only workflow…you may like it
For many years I have used git-flow. And I always found the same issue. When you team and the number of commits per day grows, so it does the number of conflicts.
When I discovered master-only workflow years back, I was like: “people are crazy, commit to master directly???”. But it turned out to be way, way better.
Tip #7 — Push don’t pull
There are many many, many architectural patterns you can choose for your app. But regardless which architecture servers your purpose best, there is one think that you can do in all of them. That is push don’t pull.
That’s short to say that all your interfaces between objects should not contain methods like:
To implement the push don’t pull principle, you don’t really need Observables, or Rx. This is also a pattern, not a library that can be implemented using simple callbacks.
Tip #8 — Avoid singletons whenever possible
Although I haven’t always succeeded, I do try very hard to avoid singletons as much as I can. The simple(istic) explanation for me is:
A better approach, that requires a lot of discipline and a lot of good architecture around, is using scopes for your instances. In other words, objects are confined inside a scope, and they are around for as long as that scope is needed. Once outside the scope, all instances belonging to it can be destroyed.
Of course, you can always need some objects that need to be around for the entire life of you application (largest scope), but you’d be surprised how small that number is.
Scoping your objects allow you to reduce the state they need to keep, because they’re created only when needed, and destroyed when not needed.
Tip #9 —Diversify
Expose yourself to what people do around you. Even in different fields. The are a lot of very good and talented people out there, and only a few of them work in your same field. Even if you don’t master/understand one field, just reading how different people tackle same or different problems is a great source of knowledge.
Tip #10 —Step out of your comfort zone
If there is anything you think you’re not very good at, find a way to work on it, even if only for a while. It may feel stressful — and it is, reason why we often times avoid it — but a little bit of that healthy stress will serve as catalyst for growth. It will challenge yourself and make you rise to the occasion.