2018 has been an interesting year from a personal and professional point of view. It’s like that Charles Dickens line in the opening of A Tale of 2 Cities:
It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way.
This year though, I did learn a number of things which stand out:
- Kubernetes. I had played around with docker containers and run them locally, but running a cluster all the way to production was fun. I know “the internet” has some concerns with the complexity of kubernetes, but I really like the way it has been designed and how the various elements are abstracted to allow for ease of replacement. I liked it.
- Kotlin. Java is standard for those who find themselves in large enterprises. I think a lot more people are going to start using Kotlin because of its interoperability with Java libraries and its superior (in my opinion) syntax.
- ORM vs Plain SQL. I’ve used ORMs for the past 12 years, starting with .NET’s Entity Framework where the Entities were auto-generated from the database, to code-first entities, to JPA and Hibernate, etc. I’ve also worked SQL scripts that spanned thousands of lines when working on an ETL project for a data warehouse a couple of years ago. This year, I started preferring SQL scripts within the database layer of an application compared to ORM. It started out when trying to resolve performance problems from the queries generated by the ORM, and then realised that removing the layer of abstraction actually gave more control, which I preferred.
- Android. I had worked on small Android personal projects in the past, but this year was the first time I worked on an application for an enterprise to be used by many users. I enjoyed crafting the code using patterns such as MVP, as well as using the ReactiveX I learnt in Angular last year for handling user interaction and other ‘listener’ logic.
- React Web. I’d worked with React Native on previously so I understood how React works, but this was the first year I worked with React web to understand how the React syntax translates to HTML, and the complexities of a growing application. I’m also not the biggest fan of Redux after working on some large applications, as I feel it is sometimes introduced too early when not needed, and adds unnecessary complexity. But it does have its place.
- Responsibility results in growth. I worked with some of the most dynamic and technologically forward-thinking teams this year. And many of the people in these teams didn’t have decades of experience. But I learnt that when given responsibility with the appropriate guidance, people rise to the occasion. Mistakes are made, but the resulting growth and ownership that results is so much better.
- Release 1 is the hardest. There are so many different forces that keep the first release from happening, from too much scope, to misunderstood requirements, to politics, to lack of discipline within a team, and so much more. After that, subsequent small releases and bug fixes happen relatively quickly.
- TDD Sometimes. I’ve always been a strong advocate for TDD. I even wrote my masters thesis on it. I still hold that it drives good design of code. Yet this year I learnt that the up-skilling of a team is sometimes much, especially teams that haven’t had much experience testing. For newer teams, the tests then become tightly coupled with the implementation, making refactoring much harder, the very thing that TDD is supposed to facilitate. Integration tests that test from the API all the way to a mocked database or mocked service call work better in such scenarios. They allow for refactoring while having a degree of security that bugs are not being introduced.
- Opinionated languages / frameworks are easier. Teams have fewer discussions about the structure of the code and are more aligned when using opinionated languages and frameworks. In less opinionated languages and frameworks, though they are normally easier and quicker to get something up and running, unnecessary complexity sometimes emerges from everyone’s subjective interpretation of what right looks like.
- Everybody is figuring it out. What we know for sure today, we don’t know for sure tomorrow. What we advocate strongly for today, we reject strongly tomorrow. What disgusts us today we embrace tomorrow. And that’s ok.