From f03bc37b93fe7b274026edf3266cc070c244eb4c Mon Sep 17 00:00:00 2001 From: eugenchio Date: Thu, 19 Dec 2024 11:38:46 +0200 Subject: [PATCH] Update headings with anchor links in blog posts. --- content/blog/three-steps/index.md | 8 +++--- content/blog/why-go-full-stack/index.md | 14 +++++----- .../index.md | 12 ++++---- .../blog/zero-downtime-DB-migrations/index.md | 28 +++++++++---------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/content/blog/three-steps/index.md b/content/blog/three-steps/index.md index a9dbc0b..837b73d 100644 --- a/content/blog/three-steps/index.md +++ b/content/blog/three-steps/index.md @@ -17,7 +17,7 @@ where did they stem from? Of course, the approach I propose here might not fit every situation. However, so many problems in my practice fall into these three buckets that I thought it was worth treating them as a checklist: -## #1: Understand "why" +## [#1: Understand "why"](#1-understand-why){#1-understand-why} - Who will be using this feature? - What problem are we trying to solve for them? @@ -52,7 +52,7 @@ about asking or think it's none of their business. Please don't skip this step. Not only will it help you solve this particular problem at hand better, but it's also essential for your professional growth. -## #2: UX design +## [#2: UX design](#2-ux-design){#2-ux-design} Regardless of the interface you're building — a UI, API, or command line — consider the user interface carefully before jumping to writing code. @@ -85,7 +85,7 @@ And if you're building an API or a command-line interface, your design would be the documentation and usage examples. It doesn't have to be polished at this stage but should include at least the most important use cases. -## #3 - Data structures +## [#3: Data structures](#3-data-structures){#3-data-structures} > "Bad programmers worry about the code. Good programmers worry about data > structures and their relationships." - Linus Torvalds. @@ -122,7 +122,7 @@ relational databases, don't skip ER diagrams :) [![ER diagram example](dbdiagram.png)](dbdiagram.png) *Credit: [dbdiagram.io](https://dbdiagram.io)* -## Summary +## [Summary](#summary){#summary} When you start working on a new feature: diff --git a/content/blog/why-go-full-stack/index.md b/content/blog/why-go-full-stack/index.md index ff278ba..0f47229 100644 --- a/content/blog/why-go-full-stack/index.md +++ b/content/blog/why-go-full-stack/index.md @@ -22,7 +22,7 @@ already built enough websites to [crash the stock market](https://en.wikipedia.org/wiki/Dot-com_bubble), even without jQuery! But that was going to change. -## 2010-s: The rise of frontend frameworks +## [2010-s: The rise of frontend frameworks](#2010-s-the-rise-of-frontend-frameworks){#2010-s-the-rise-of-frontend-frameworks} The major shift happened somewhere in the 2010-s when frontend frameworks emerged. A remarkable demonstration of what they made possible is Trello, @@ -46,7 +46,7 @@ I'm not sure if it was pure coincidence or a result of Trello's popularity, but at that time [TODO list](https://todomvc.com/) had become a canonical example, showcasing the capabilities of JS frameworks. -## APIs +## [APIs](#apis){#apis} Simultaneously in the 2010-s there was an explosive growth of APIs: @@ -60,7 +60,7 @@ application and a mobile app, and when needed, it can be exposed outside and used by external integrations. Widespread adoption of the REST API concept has further boosted the API development. -## Frontend developers +## [Frontend developers](#frontend-developers){#frontend-developers} Frontend frameworks were hot in the 2010-s. People were talking about them at conferences. At that time, the joke about "X days without a new JavaScript @@ -103,7 +103,7 @@ better quality development due to higher specialization, but it's not always the case. It could be true for some projects and false for others due to the reasons outlined in the next section. -## What problems do full-stack developers solve +## [What problems do full-stack developers solve](#what-problems-do-full-stack-developers-solve){#what-problems-do-full-stack-developers-solve} [![Why go full-stack](why-go-full-stack.png)](why-go-full-stack.png) @@ -165,7 +165,7 @@ which optimizations are possible. On the other hand, backend developers understand the internals very well, but they may not look at the product from the end user's perspective. -## State of modern frontend +## [State of modern frontend](#state-of-modern-frontend){#state-of-modern-frontend} What has changed in frontend development since the 2010-s? Well, many things, but most importantly – it has matured: @@ -189,7 +189,7 @@ much easier to work with it than ten years ago. Yes, a large portion of complexity is still there, but it's no longer such a mess, so there are fewer reasons for backend developers to hate it. -## Should you hire full-stack developers? +## [Should you hire full-stack developers?](#should-you-hire-full-stack-developers){#should-you-hire-full-stack-developers} It depends. There could be no benefit from full-stack developers in areas of your project with little or no back-and-forth between the backend and frontend. @@ -206,7 +206,7 @@ exist, and it is possible to find them. You can also have a hybrid team – some frontend and backend developers and some full-stack folks to take the best from both worlds. -## Should you become a full-stack developer? +## [Should you become a full-stack developer?](#should-you-become-a-full-stack-developer){#should-you-become-a-full-stack-developer} When you read these lines, I bet you already know the answer. It's perfectly fine if you don't want it – specialization is nothing wrong. Most job offers diff --git a/content/blog/why-public-chats-are-better-than-direct-messages/index.md b/content/blog/why-public-chats-are-better-than-direct-messages/index.md index dc701f4..f6436c8 100644 --- a/content/blog/why-public-chats-are-better-than-direct-messages/index.md +++ b/content/blog/why-public-chats-are-better-than-direct-messages/index.md @@ -10,7 +10,7 @@ we communicate makes an enormous impact on our work. In this post, we talk about one of the best strategies for improving communication in a team: **making it open**. -## What is open communication? +## [What is open communication?](#what-is-open-communication){#what-is-open-communication} Over the years, we at ivelum have developed a work culture that relies on open communication, an approach borrowed from open-source communities. We prefer to @@ -31,7 +31,7 @@ ivelum, we do the opposite. Many folks who join our teams notice that we communicate differently from how they used to do it at their previous job. We explain why and try our best to ensure a smooth transition. -## Why? +## [Why?](#why){#why} [![Boost team performance](rocket.png)](rocket.png) @@ -39,7 +39,7 @@ Simple: **it boosts team performance - a lot.** Of course, it takes some adaptation effort for new team members, but the effect is so significant that it soon pays off. -## Minimize distractions +## [Minimize distractions](#minimize-distractions){#minimize-distractions} At first, it may seem that when all work communication is public, it might cause a lot of distraction. In reality, the opposite is true because of how @@ -60,7 +60,7 @@ will respond when they have time. It greatly helps to minimize distractions, which is especially important for developers. To be productive with code, they need prolonged periods of focused work. -## This is not "noise" +## [This is not "noise"](#this-is-not-noise){#this-is-not-noise} Okay, reducing distractions is all well and good, but why would people in a team chat browse through lots of messages which are not addressed to them @@ -82,7 +82,7 @@ Finally, proper organization of chat channels reduces the risk of information overload to a minimum. Each chat channel can be dedicated to a particular project or a team, and people follow only channels in which they're interested. -## Why isn't everyone doing it? +## [Why isn't everyone doing it?](#why-isnt-everyone-doing-it){#why-isnt-everyone-doing-it} Even when teams agree that they may benefit from open communication, they sometimes don't rush to implement it in practice. @@ -103,7 +103,7 @@ the most secretive companies – [Apple – is now reconsidering its practices](https://www.fastcompany.com/90748492/apple-airpods-pro-creation) because the downsides are so significant. -## Bottom line +## [Bottom line](#bottom-line){#bottom-line} There are certain things that the most productive teams do differently. Of course, open communication is not a silver bullet that magically solves all diff --git a/content/blog/zero-downtime-DB-migrations/index.md b/content/blog/zero-downtime-DB-migrations/index.md index 8747a63..a26778d 100644 --- a/content/blog/zero-downtime-DB-migrations/index.md +++ b/content/blog/zero-downtime-DB-migrations/index.md @@ -21,7 +21,7 @@ migrations and provide quick recipes for the most common scenarios. - [Heavy DB operations](#heavy-db-operations) - [Conclusion](#conclusion) -## How does a deployment process work? +## [How does a deployment process work?](#how-does-a-deployment-process-work){#how-does-a-deployment-process-work} Let's take a look at a simplified deployment process for a typical web application. Most applications these days rely on load balancing and container @@ -52,7 +52,7 @@ a database upgrade should look like this: [![Deployment process with the DB upgrade](deployment-process-with-DB-upgrade.svg)](deployment-process-with-DB-upgrade.svg) -## How to run the DB migration script +## [How to run the DB migration script](#how-to-run-the-db-migration-script){#how-to-run-the-db-migration-script} Please note that how you run a DB migration script matters. For example, it might be tempting to make it part of the application startup, like this: @@ -90,7 +90,7 @@ For example, it could be a one-time Kubernetes task that is launched as a part of a deployment process or something like that. Just remember the main principle — launch it only once, and if it fails — roll back immediately. -## What can cause downtime during database migration? +## [What can cause downtime during database migration?](#what-can-cause-downtime-during-database-migration){#what-can-cause-downtime-during-database-migration} There are two main reasons for this: @@ -109,7 +109,7 @@ Now, let's look at the most common cases related to the backward incompatibility problem. We'll also briefly talk about heavy DB operations at the end of this post. -## Example 1: downtime caused by a new column +## [Example 1: downtime caused by a new column](#example-1-downtime-caused-by-a-new-column){#example-1-downtime-caused-by-a-new-column} Let's say we're building a new feature — user avatars. After registration, every user will get a randomly generated avatar with an option to upload their @@ -145,7 +145,7 @@ However, since we're talking about "zero-downtime deployments," this is not good enough for us. Let's see how we can deploy this new feature without any downtime. -## Solution {#solution-1} +## [Solution](#solution-1){#solution-1} The trick is to split the feature deployment into multiple phases and deploy them one by one, waiting for each phase to deploy completely before moving to @@ -176,7 +176,7 @@ values in this field since the app version that we deployed on Phase 1 already generates avatars for all new users. Therefore, we can safely enforce the "non-null" constraint and deploy all the remaining avatar features. -## Example 2: downtime caused by a column removal +## [Example 2: downtime caused by a column removal](#example-2-downtime-caused-by-a-column-removal){#example-2-downtime-caused-by-a-column-removal} Let's say that the "User avatars" feature we described in the previous example didn't meet our expectations. It wasn't popular enough, so we decided to roll @@ -195,7 +195,7 @@ execution, there will be a time when the previous application version is still running in production, but the `avatar` column no longer exists, so all functionality related to it will be broken. How could we avoid this? -## Solution {#solution-2} +## [Solution](#solution-2){#solution-2} Use the same technique as with the previous example — split the deployment into two phases: @@ -220,7 +220,7 @@ any way. After Phase 1 is deployed, there are no more mentions of the `avatar` column anywhere in the application code, so we can safely drop it. -## Example 3: renaming a column or changing its data type +## [Example 3: renaming a column or changing its data type](#example-3-renaming-a-column-or-changing-its-data-type){#example-3-renaming-a-column-or-changing-its-data-type} Let's say we'd like to upgrade the avatars feature that we described in [example 1](#example-1-downtime-caused-by-a-new-column). Instead of storing @@ -259,7 +259,7 @@ won't be able to read or write the data because the column name changed. The application will remain broken until its new version is fully deployed. How can we avoid this? -## Solution {#solution-3} +## [Solution](#solution-3){#solution-3} Use the same technique as with the previous examples — split the migration into phases. This case is more complicated — we need four phases: @@ -310,7 +310,7 @@ After Phase 3 finishes deploying, we can remove the old column from the DB. No application changes are required in this phase since the application was already upgraded in the previous phases. -## Example 4: renaming a table +## [Example 4: renaming a table](#example-4-renaming-a-table){#example-4-renaming-a-table} Surprisingly, renaming a table is more straightforward than renaming a column. Imagine we'd like to rename the `Posts` table to more generic `Content`: @@ -322,7 +322,7 @@ deployment. The previous app version, which still runs in production, will try to access the table using its old name, resulting in an error. Let's see how we can avoid this. -## Solution {#solution-4} +## [Solution](#solution-4){#solution-4} In this case, we need two deployment phases: @@ -352,7 +352,7 @@ And the second phase is simply a cleanup — removing the view we no longer need > [renaming a column](#example-3-renaming-a-column-or-changing-its-data-type), > which we described above. -## A generic approach to maintaining backward DB compatibility +## [A generic approach to maintaining backward DB compatibility](#a-generic-approach-to-maintaining-backward-db-compatibility){#a-generic-approach-to-maintaining-backward-db-compatibility} As you can see, all three solutions above use the same technique — split the deployment of a new feature into two or more phases to avoid any downtime @@ -380,7 +380,7 @@ Quick recap: [4](#example-4-renaming-a-table)) illustrate how exactly you can plan your deployment phases to avoid downtime caused by broken backward compatibility. -## Heavy DB operations +## [Heavy DB operations](#heavy-db-operations){#heavy-db-operations} Another common reason for downtime during the DB upgrade is that some modifications performed by the database migration script can cause a heavy load @@ -432,7 +432,7 @@ painfully slow. What could we do? can carefully balance the load on the database while making sure that it doesn't cause slowness or downtime. -## Conclusion +## [Conclusion](#conclusion){#conclusion} While zero-downtime database migration requires some effort, it's not that complex. The two main reasons for downtime are: