Software engineering is a discipline that requires constant learning “by design”. As new frameworks are released and adopted, as the reliable, old and tried technologies get new releases that introduce major changes and completely new APIs, the only way to not fall behind* is to keep learning, or, at the very least, to be able to learn on-demand, only what is needed, when it is needed.
Dogfooding is the practice of using your own products as a way to uncover potential issues and/or improvement areas for them. While it is not a new practice, there has been some recent controversy with it, especially with what has happened at DoorDash that made news when it announced it would require all of its employees — including engineers (gasp!) — to deliver food once a month. The program is an expansion of an initiative to get employees regularly testing its products. It was expanded to include three options for employees to test out the business each month. They’re referring to it as: WeDash, WeSupport and WeMerchant. WeDash is the overall program which includes “dashing,” executing actual deliveries. WeSupport entails employees shadowing a customer experience agent, and WeMerchant, which is the newest addition, entails employees shadowing merchants to better observe logistics and the experience of fulfilling orders. DoorDash encourages its employees who are going out to deliver food or shadow merchants to team up with a couple colleagues to do the job.
One recent tweet sparkled my interest and I decided to write a post about it. There’s usually a lot of good content on Twitter that can motivate me to write and, this tweet definitely fits the bill:
I’ve just recently finished reading the book “Atomic Habits” by James Clear, and, it’s a very fascinating book that touches upon the power of making tiny changes to achieve remarkable results. The main takeaway can be boiled down, in simple terms, to a simple idea: what could you achieve if you focused on getting 1% better than yesterday, every day, for a year? Doing some math, we can arrive at the following two formulas that illustrate this difference clearly:
With the market being so hot right now for senior developers and experienced applicants, it’s undoubtedly a hard time to be an early-career developer in search of a new job. So, it makes it especially important for the rest of us to ensure that early-career engineers can be set up for success so that they can thrive and pass on what they’ve learned to the next generation of developers, keeping up the nice cycle of knowledge sharing embedding in it the new technologies and best practices that inevitably will arise.
There are several things we need to keep in mind as we are writing code to deliver a certain feature. The set of things changes with time, with the sense of urgency that the feature itself requires and also with team culture.
With the covid pandemic still going strong, WFH has become the norm in recent times, and, as a more structural shift in the way modern software related companies conduct their business took place, it has become the standard also for the future. This means that there are many companies adopting remote-first work and opening their workforce to fully remote positions, for eg. Spotify. What this means is that the opportunities for interesting work have now become globally accessible to anyone no matter where they are within the world.
There are many books and blog posts and youtube videos detailing how you can advance in your career and become a better developer. Typically, advancing in your career means aiming for and reaching positions like Senior Software Engineer or Staff Software Engineer and, usually, getting to those positions, implies that, at some extent, and some point in time, you must already be performing at the required level while still being one level below the target.
Using git as a system for version control is more and more becoming the standard way of keeping your code versioned for its changes. There is probably a minority of companies that don’t use it, but, most of them will, and every company does it differently. The way a company uses git (or not at all) can tell you a lot about its engineering culture and what is valued within the development teams by the leadership.
Most software developers working at product companies usually work on delivering features to customers and/or defined by stakeholders within the organization in a roadmap. These features are usually (but not always!) tied to a well-defined business metric or goal or to a specific product vision to be fullfilled in a given timeframe: “We want the product to do X by date Y and we want to ensure that our biggest client from BigCorp receives the feature he has been asking for months now”. These scenarios, in one form or another are what ends up driving product development and indirectly contributes to other factors like: developer happiness and productivity, product engagement, client retention, etc.
Modern agile practices in software development are usually a synonym with well-defined chunks of work over a specific timeline, usually a 2-week sprint. What this implies is that by having a fixed timeline to work on, it also limits the amount of work that a team can deliver in that fixed period of time. So, it becomes imperative that people work on what can deliver the most impact. However, knowing how to choose exactly what to work on can be a bit of a tricky question that can arise when using these types of practices. Immediately, several questions can arise such as:
One of the most underrated things in the industry, especially when you’re working as a full-time developer, is the power of keeping a “knowledge stash” handy. There’s this perception that knowledge comes through experience, time, or simply osmosis, and, while that can be true over a long enough period of time and for the more superficial knowledge, there are just too many layers in a professional codebase that it’s impossible to grok it immediately.
Testing is almost a science in itself. There are people who love it, people who hate it, people who can’t work without it. There are also different interpretations of what the benefits of testing exactly are.
Design patterns are great for creating maintainable and reusable code, and, while being universally applicable, they lend themselves well to be implemented in languages that support OOP like Java. This is because these patterns are usually defined in terms of specific “collaborators” that can be very well modelled as interfaces and/or classes, so, it’s easier to “see the patterns” in front of you when using a language that naturally lends itself to it. They are, in essence, a proven and tried way to tackle a problem in software design that has a solution that is proven to be good, robust and generally accepted as a standardized way to solve that specific problem.
In most product-based companies, there’s an inherent bias on focusing on churning out features out the door as fast as possible. There’s this notion that the time to market for new features is everything. While this can be true for companies which are exploring their market fit, or attempting to expand their products in an attempt to increase their market share, there’s a huge “middle ground”, for companies who have a decent client portfolio and are stable enough that they can grow their products in a more methodical and controlled manner, where having this culture of simply pushing the technical boundaries of the product and churn out new features is not the only thing that matters.
Software engineers love complexity. Complexity is an inherent part of writing software because the medium itself (programming languages) is complex on its own. When you put together with it the discipline of doing software engineering, where you add time constraints, customers, budgets and changing requirements… well… it’s complicated.
An interesting post on the HN Ask section, posed a question that prompted me to write this short piece:
Every once in a while there is a popular tweet, either with some strong statement in it or some controversial opinion that makes the internet blow up, ensuing endless retweets and many separate discussions about the content, or the person, who tweeted it. The most recent one has been this post by DHH (for context, he is the one who created Ruby on Rails - let that sink in by thinking just how many jobs this one guy ended up, indirectly, creating in the industry over the years. His impact in the field, like it or not, can’t be dismissed, period) that summarizes the key idea of an article he published, which you can (and definitely should!) read here:
Often in life, it’s said that the perfect is the enemy of the good. What this means is that sometimes, it’s worthy to settle on a good enough approach for doing something, even if it’s obvious that there could be improvements in some areas. The issue, of course, is that the sunk cost fallacy is very real, and, sometimes, attempting to reach perfection from a system that is already good enough can warrant more problems that will (in many cases) outweight the promised benefits. So, it is important to maintain a critical view on when to judge a system as being good enough for a given purpose as opposed to attempt and make it “perfect”, because, in life, perfection is often elusive.
One of the biggest struggles for any product-based company is to know exactly what to build. What to build is really important because that’s what ends up driving your business forward and it’s also the only way to attract, and eventually retain customers. Then, word of mouth, will do a lot of the “marketing” in spreading the word and expand the influence of your product to prospective new customers and that’s how part of the initial growth can happen.
Often it is needed to write tests for our application that deal with some form of Authentication, and, even more frequently, the goal of these tests is not to worry about the actual authentication mechanism itself, but, instead, of what logic occurs when we assume that the authentication was successful. In testing jargon, we want to simply unit test the logic that sits behind the authentication mechanism, not concerning ourselves with the authentication piece itself.
Usually, when thinking about what really makes a team move fast, the first tendency is to look at how many points the team is commited to, what is the churn, what is actually being done or not. This is usually interesting, in the sense that, while the numbers can give you some accurate measurement of speed, if you want to look at it from that angle, they don’t often tell the whole story. The whole story is better told by looking at execution patterns, or in other words, how such a velocity is achieved.
Recently, we’ve been experimenting at work with looking at ticket estimates under a different light than always. As many other software companies, we’ve ended up falling victims of the mantra: more points = more value, and, well, this can create some really awkward icebreakers in retros and other meetings, where the focus shifts towards looking at the “net negative space” instead of focusing on real progress.
I follow several technical people on Twitter from all steps of the technical ladder, from juniors all the way to managers, PM, TPMs, Tech Leads, etc. I like to do this because it gives me a wider frame of reference to look at myself and see exactly where I stand in my own progression. It’s critical to me that I have a wider view of different levels in the industry besides only my own, otherwise, I can become biased in my own judgment.
One of the biggest challenges that has risen during the pandemic for software teams which were suddenly forced to go full remote, is how to keep the team spirit and team cohesion high. This is something that can be seen as a cross-cutting concern for employees and for managers alike, for different reasons. In some cases, employees feel more prone to share their thoughts and to collaborate when being in the same room, as opposed to being fully remote. Again, this is somewhat of a personal preference but, it’s undeniable that if you can simply walk over to your colleagues desk and ask something, sync on progress or simply chitchat to relax and switch contexts, it makes having a cohesive team a lot easier. Managers and alike, also like to have cohesive teams as it increases mission sense and purpose, keeps employees more engaged with the company and one another, and is likely to lead to more effective teams in the long term. So, how can we build this cohesion while staying full remote?
Modern software development is much more complex than a few years ago, because its reach has grown, use cases have multiplied and there’s basically no business nowadays which doesn’t rely on software to function. This means that the demands that the software must meet are much more complex and diverse than before. With increased demand, comes also increased availability and reliability.
As a developer, at least once in a while, I bet you’ve experienced something like this: you get assigned a ticket at a beginning of the sprint, and, start working on it. It’s a relatively self-contained and small ticket, should be wrapped up in about a week’s time. You make good progress everyday, no real blockers, and, after 4 days of work, interspersed with meetings in between, you add your final tests, clean it up, and put it up for review. Thursday, 12h00. With some luck, you get your review feedback today, process it Friday morning, and right near the end of the day, you can merge it and slide into the weekend with a feeling of a job well done… Except… it’s never like this, right?
One of the biggest challenges when starting a new job, both from an employee perspective and a company perspective, is deciding what is a good task to assign someone who just joined the team. In fact, of all three companies I’ve worked at so far, I’ve experienced different approaches to the onboarding process, and, while some worked better than others, I feel that none of it was exactly what I would look for in my own ideal onboarding.
There has always been an ongoing debate in the tech community, at least, for as long as I can say I started engaging with it about whether or not developers should work on side projects or not.
Recently stumbled upon a Twitter post that went along the lines of: “how can infrastructure teams use most of the services offered by vendors like AWS without having a deeper understanding of how they are built internally?”
I follow several technical people whose stances on tech I can identify with in a few platforms, and, by far, Gergely Orosz has been one of the most influential people I’ve decided to follow, and, I’m glad I did! As a former Uber manager his posts and insights are always extremely interesting to read. Some of the topics are geared towards senior ICs or people who are on track to become managers or who have more people responsibilities than a standard IC, but, at least recently, I’ve found for myself that you can always take away something valuable from such articles, even if you aren’t yet at that level. This is a bit in-line with the Stackoverflow article about growing by doing stretch assignments.
Recently, I’ve been thinking about the importance of working with context. What does this mean exactly? Context can mean a lot of different things to different people, so I’ll try to elaborate on what I exactly mean by this and how exactly it can help you.
This post will detail how this blog came to be and how I work on the posts and what is the current work flow I’m using to manage new posts.
I’ve always liked writing about things I am learning or have a real interest on, and, I’ve been writing online for “as long as I can remember”, going back to my contributions on a Physics forum while I was still in high school.