I share TL;DR versions of articles on software engineering that I read every weekday through my newsletter - in.snippets(). Sign up here to receive these in your inbox.
“As a young discipline we’ve spent a lot of time working out ‘how’ to build software and that’s a big focus in schools still. But once you have the foundations, you need devs who engage with the ‘why’ actively. Engineers who have a thirst for using technologies to leapfrog human/user problems. Those with empathy to reach for magical experiences. That is what defined a product engineer in my books. Bad product engineers cut too many corners but great ones know that minimum loveable products need the right depth to be considered during the build phase.”
-Jean-Michel Lemieux, CTO at Shopify
The article shares 9 key traits of product-minded software engineers and 6 things software engineers can do to build up a product mindset:
- Understand how and why your company is successful
- Build a strong relationship with your product manager
- Engage in user research, customer support and other activities, where you can learn more about how the product works
- Bring well-backed product suggestions to the table
- Offer product/engineering tradeoffs for the projects you work on
- Ask for frequent feedback from your product manager.
IMHO, adopting this mindset can help all engineers build a deeper understanding of the product we are working on and in turn, help us be better engineers who build better products.
8 min read
5 principles of software architecture that help software architects make effective decisions:
1. SOLID principles
a) Single Responsibility Principle:
Each system capability (e.g. service/module/API) should have only one responsibility
b) Open-Closed Principle:
It is preferable to extend a system behavior, without modifying it.
c) Liskov Substitution Principle:
Given two distributed components with the same contract, one should be replaceable with another component with the same contract without altering the correctness of the system.
d) Interface Segregation Principle:
Interfaces/contracts must be as fine-grained as possible and client-specific
e) Dependency Inversion Principle:
High-level modules should not depend on low-level ones; they should both depend on abstractions.
2. The principle of Least Astonishment: leverage the pre-existing knowledge of users to minimize their learning curve when using a module
3. The principle of Least Effort: Everyone tends to follow the path that is as close to effortless as possible. So, aim for a strong start by putting the right architecture & expectations in place.
4. The principle of Opportunity Cost: The opportunity cost of a choice is what we give up to get it. To make a good economic decision, we want to choose the option with the greatest benefit to us but the lowest cost.
5. The principle of Last Responsible Moment: Don’t make a premature decision but instead delay commitment and keep important and irreversible decisions open until the cost of not making a decision becomes greater than the cost of making a decision.
7 min read
This post shares in detail the Dropbox team’s rationale behind migrating their code to static type checking; challenges the team faced through the process & how they navigated those; various approaches they used for adoption internally; and the impact it made on the engineering the team’s productivity. A few benefits that convinced the team to go full throttle with this:
- A type checker finds many subtle (and not so subtle) bugs
- Refactoring is much easier
- Type checking provides quick feedback and allows to iterate faster.
- There is no need to write fragile, hard-to-maintain unit tests that mock and patch the world to get quick feedback.
- IDEs and editors such as PyCharm and Visual Studio Code take advantage of type annotations to provide code completion, to highlight errors, and to support better go to definition functionality
It is a great case study of the usefulness of static type checking in Python for large-scale projects.
20 mins read
This post was written by Paul Hinze 6 years ago when he changed jobs and transitioned from a dev culture of pair programming to that of peer code review. He shares a balanced perspective on both these practices.
In pairing, everybody on the team gets better together because of constant communication. Junior developers can be trained easily by giving them an experienced pair; best practices, knowledge, new tools, and techniques spread naturally & quickly across the team. It is not all sunshine and rainbows with pairing though. It can lead to over-diluting core talent which can kill both productivity and morale. When it comes to tackling the larger problems of system design and architecture, that require more deep thought or creativity, pairing can be detrimental to progress.
In teams that follow the practice of code review, there is a motivating pressure to perform well for the review. There are no barriers to take on deep thought problems. As code reviews are asynchronous, there is a lot of work schedule flexibility. Code reviews can be strategically distributed to ensure that more experienced developers always touch certain kinds of code reviews which provide additional quality control and protection against bugs landing in production. However, in teams with code review processes, you can feel lonely, zone out for long periods and run late on deadlines. If code reviews are not done with a tight cadence, they can become bottlenecks
10 mins read
Sidu Ponnapa has spent much of his career scaling the 'people side of tech'. He has helped seed and scale GojekTech from 1 million to 10 billion GMV in the last 4 years. In this post, Sidu expounds on how can team leaders & decision-makers bounce off programmers’ discipline to build & scale effective organizations. Programming is inherently difficult. Programmers face inherent challenges of programming - ambiguity, complexity, integration, and paradox - while building solutions for hard problems. To reduce the difficulty of problems, programmers break things down into ‘systems’, and define how they engage with these systems through ‘disciplines’. Many of these disciplines are a perfect fit when dealing with the problems inherent in scaling businesses. Because all competent programmers are experienced at designing, building and running large, complex systems, they are excellent sounding boards when developing non-tech systems.
8 min read
P.S - I share this list of the best of tech articles that our team at Appsmith reads through the week.