I left that company and started working for CleverTap in October 2019. In my 2 years, my work ranges from Kubernetes to Vue.js and Natural language Processing to shell scripting. Here are some of the important things I learned which you might have come across.
I cannot say enough about how important software architecture is. I learned that planning systems and the projects I was working would help me reduce my coding time by at least 30%! Initially, when we start with the project we just want to blaze through the story/feature and jump on to the next one.
We don’t care how bad the code is or how the system is organized. That just incurs a technical debt in the long run which will have to be addressed later on with folds of effort. Building a well-planned codebase would not only help us building features on top of that faster and easier but also help other engineers the hassle of re-architecting the code again and again.
I got into the habit of creating a technical document before even writing a single line of code. It documented the changes I will make to the existing architecture and the impact of my new code. In fact, sometimes planning and reiterating on this document would take longer than actual code itself but it paid dividends in the long run.
I basically went from loathing planning software to loving planning and having discussions about it.
What is good code? According to me, good code is that which I enjoy reading. As many people say writing good code is like writing a good story. It should flow smoothly and easy to follow, and in the end, things should tie up beautifully. This will not only help your life but other developers’ life as well.
Some examples of good code vs bad code.
Convoluted:
if(success){
// do something
...
...
response.close()
value = true
} else {
do things ...
response.close()
value = false
}
return value
Simplified:
value = false
if (!success){
response.close()
return value
}
// flow for success
This is an easy example but clearly shows by making certain adjustments we could avoid nesting and so much convolution.
So many times we just get stuck on what to name a variable, class or a method. The fact that you’re facing that dilemma is good to begin with, as opposed to people naming random things. Naming code better enhances the readability and makes us go through code faster.
Bad naming is like taking class notes in bad handwriting and pulling out hair during exams deciphering it.
On the contrary good naming would many times save us from reading the internals. Here is an example of naming vs better naming
class Student {
void setStudentName()
void getStudentName()
}
...
Student student = new Student()
student.setStudentName()
student.getStudentAge()
Better:
class Student {
void setName()
void getName()
}
...
Student student = new Student()
student.setName()
student.getAge()
In the first example, we are repeating understood information again. In the better example, we can see that the setName method clearly implies what it does as equal to writing setStudentName.
Ideally, the internals of a method or a class should be roughly understood by a correct and good name. But in many cases, that’s difficult to implement.
The next best step is to write a good 2 lines of explanation of the method and its class. This would save all the people a lot & a lot of frustration and time! Imagine how many times you have read a method where you have no idea what's going on.
How much those 2 lines would help. Do some good in this world, please!!
One of the reasons why I love Golang is that It reminds the developer to write that piece for each public exported piece of code.
Another important lesson I learned is how important test cases are. Initially like everyone I considered my project done as soon as I finished writing code Guess what used to happen, something would break many times and something could be high risk. Writing test cases helps us catch important bugs in the initial stages of development.
Good test cases is a certificate against your code that certifies things are working fine at your end.
It would help you sleep peacefully at night.
Now to achieve this you also have to code structured in an easily testable fashion. Thus the importance of architecture.
Example:
func updateSomething() {
// business logic
repository.instance.get() // get instance of dependency
dependency2.instance.get()// another dependency
....
}
Better testable code:
func updateSomething(db repository, dep2 dependency2 ) {
// business logic
db.update()
dep2.stuff()
....
}
What is the difference between the first snippet and second? Let's say I want to test the above method without actually updating my database or hitting an HTTP API which could be dependency 2. In the first case, it would be really difficult to mock those since they are initialised in the method itself. As opposed to that I could simply pass those mock dependencies as a parameter and making my life so much simpler to test.
Initially as a ‘fresher’ whenever I faced a roadblock I would rush to my senior for help. To put it simply I did not have the confidence in myself that I could solve it.
Obviously this could not go on for too long. I would give up if the first StackOverflow answer did not solve my problem. Not only did I not how to google properly but I also gave up pretty quickly. Many times the solution was as simple as following the second-most voted answer on StackOverflow.
As things progressed I gained confidence in myself that I WOULD be able to solve this problem. Trust me, the majority of the time that would help you with solving the problem. I went from giving up after the first solution that didn’t solve my problem to scanning the internal code of the libraries I used for specific problems and solutions.
I remember as a fresher when I received my first projects and features to work on I got overwhelmed pretty quickly. Initially, I lacked confidence that I would be able to solve this or complete this by myself.
As I aforementioned we gain confidence and our mindset changes. I learned that as things progress us developers figure stuff out. Sometimes after assessing, we have to jump in knowing that there is an unknown.
Even right now, when I get a new feature/project to work upon which I have never experienced there is a corner in me that’s a bit overwhelmed when there are certain unknowns. But I have gained the confidence I will figure it out.
I have many things to learn but these are some of the important things which I have learned in my 2-year journey which even you might come across more or less. As I learn more and more things I understand so many things still to learn.
Agree with me or disagree do tell me on Linkedin.