Roman Imankulov

Recent content on Roman Imankulov
https://roman.pt/ (RSS)
visit blog
Temporary vs Permanent Errors
5 May 2024 | original ↗

When working on external integrations, we often implement basic error handling. Most of the time, we just use resp.raise_for_status() and leave it for your future self to handle. Quite often, we don’t handle errors because we genuinely don’t know how the external system will behave and what types of errors to expect from it. Indeed, it can be...

Interface-mock-live (IML) pattern for connecting with third-party services in Python applications
8 Jan 2024 | original ↗

To KISS or not to KISS I remember how, several years ago at Doist, we talked about integrating with external services, like email providers or analytics tools. The question was whether to use a simple function or an abstraction layer. We ended up with having two groups. KISSers. The first one advocated for following the KISS principle and calling...

Handling Unset Values in Fastapi With Pydantic
26 Dec 2023 | original ↗

In the update API endpoints that allow for partial updates (aka PATCH updates), we need to know if a model field has been explicitly set by the caller. Usually, we use None to indicate an unset value. But if None is also a valid value, how can we distinguish between None being explicitly set and None meaning “unset”? For example, let’s say we...

GitHub Copilot Context
19 Dec 2023 | original ↗

How to provide coding guidelines for GitHub Copilot and influence GitHub Copilot suggestions. In my project, I use naming conventions for models. I have different suffixes for different model types, and I subclass my models from various base classes. It would be awesome if I could let GitHub Copilot know about my conventions, so it can suggest...

Django Admin and Service Layer
15 Aug 2023 | original ↗

Services are a missing layer in the Django architecture. Django does not provide guidance on where to place complex logic for modifying multiple models, but many development teams have chosen to follow the clean architecture pattern and introduce a service layer. This layer acts as a middleman between interfaces such as views or API endpoints,...

Refiner
11 Jul 2023 | original ↗

I created a Refiner, an open-source project that automatically fixes grammar and stylistic errors. It can also adjust the tone and formatting. That is addictively useful. Now, pretty much all my git commit messages, comments to Jira tickets, and Slack comments pass through the wisdom of this tool. The post you are reading has also gone through a...

From Django class-based views to service functions
6 Apr 2023 | original ↗

Photo by Valery Fedotov If you use Django class-based views (CBV), do you feel like it takes significant mental effort to wrap your hand around the logic spread across various mixins? I have never been a big fan of Django’s class-based views (CBV) and their mixin approach. In my experience, classical function-based views (FBV) work as good as...

Parametrizing Pytest Fixtures
7 Mar 2023 | original ↗

Photo by Markus Winkler Parametrizing pytest fixtures is a powerful technique for writing more concise and readable tests. I find parametrizing fixtures helpful in two cases. When testing multiple implementations of the same interface. When testing the same function against different inputs. Testing interface implementations Thanks to Python duck...

10 Minutes
28 Feb 2023 | original ↗

Photo by Lukas Blazek Setting aside ten minutes daily to learn something is possible. If it is not, where does your time go? On a personal level: as you wake up, you have roughly 100 such 10-minute blocks before you go to bed. Can you squeeze out one block before bed, commuting, or after lunch? On a company level: your company is buying roughly...

How I Make Choices
21 Feb 2023 | original ↗

When choosing between alternatives, whether big or small, it’s way too easy to fall into an analysis paralysis trap. Quite often, I find myself indecisive when I make a non-trivial purchase or a solution that will likely determine my future. In other words, not like choosing between sorts of cheese in a supermarket, but rather choosing which...

Feature Flags at Building Radar
14 Feb 2023 | original ↗

Photo by Artem Bryzgalov If it hurts, do it more often In the summer of the past year, I joined Building Radar as a contractor developer. The team recently launched a new product, onboarded some clients, and was looking for ways to move forward faster. When I joined, the team was releasing a new product version every three weeks, and the release...

Say Maybe to Hell Yeah
31 Jan 2023 | original ↗

There is a 2009 post from Derek Sivers, No yes. Either HELL YEAH! or no, a very short one, and it can be condensed even further in a single sentence. If you’re not saying “HELL YEAH!” about something, say no. Brilliant advice on learning to say “no” to so-so experiences to laser-focus on a single stellar thing. Yet, there is a big-big caveat!...

7 habit-building techniques I learned from 'Atomic Habits'
24 Jan 2023 | original ↗

It’s been a little over a year since I read Atomic Habits and I wanted to share some of the key takeaways that have really resonated with me. When I first read the book, I thought it was an enjoyable read, but it didn’t necessarily blow my mind. It wasn’t until I started implementing some of the concepts from the book that I had my “a-ha” moment....

Simplifying PostgreSQL enum migrations with SQLAlchemy and alembic-enums
17 Jan 2023 | original ↗

do you really need postgresql enums? (Update from 9 Jan 2024) Working with Django reminds me how much less painful enums could be if they were represented by VARCHAR fields at the database level and enforced by Django models at the application level. Inspired by this, in my next SQLAlchemy model, I used the ChoiceType from the sqlalchemy-utils...

Most Popular Posts of 2022
10 Jan 2023 | original ↗

What I wrote about in 2022? In 2022, I wrote 20 blog posts starting from a Dealing with large pull requests and closing the year with Stop Me Before It’s Too Late. Additionally, I tried to record my TIL findings in May and June, but quickly abandoned this idea after only three posts, still trying to determine if the format made sense. The topics...

Surviving Late Night Events
1 Jan 2023 | original ↗

The New Year celebration is tough for me. One thing that makes it especially challenging is that the tradition requires you to be awake enough to observe the second 00:00:01 of the upcoming year and enthusiastically cheer its arrival. Throughout the years, I’ve learned that while I can be awake, there is never enough energy to be enthusiastic...

Stop Me Before It's Too Late
13 Dec 2022 | original ↗

Proactivity and communication are essential for healthy relationships at work. I often use the phrase “Stop me before it’s too late” in this work style and find that it can serve as a good catchphrase marker for these two traits. The context of saying “stop me before it’s too late” is typically when I encounter a problem (usually a blocker) with...

Pydantic as a Backward Compatibility Layer
6 Dec 2022 | original ↗

Data structures evolve with time. Say you have data storage with person objects. I assume the storage is schema-less. Maybe it’s your primary storage in MongoDB, a Redis cache, or a log record in ElasticSearch. { "name": "Guido Van Rossum", "email": "guido@python.org" } At some point, you decide to store a profession alongside each person. New...

Resolve Discussions
30 Aug 2022 | original ↗

You write a specification draft and share it with colleagues for feedback. With Google Docs, Notion, or Confluence, typically, colleagues leave contextual feedback on specific lines of the document. From there, an entire discussion can evolve. A specification with many unresolved comments is a time sink for everyone who touches it. Not only do...

Long name, short body
16 Aug 2022 | original ↗

Martin Fowler argues that functions should be as short as a few lines of code. I feel like that’s a bit extreme, and usually, my functions are longer than that. It turns out my test functions are a different beast. Reflecting on how I write code, I noticed that my test functions are usually much shorter than my regular code. Not only are they...

AWS Certified Developer
2 Aug 2022 | original ↗

I passed the AWS Certified Developer - Associate certification exam a week ago. Below I’m sharing my journey, thoughts, and tips about the process. Why I decided to pass the certification exam? In broad strokes, I had two primary goals: the certificate and the knowledge that the preparation brings. Knowledge part. I worked with AWS for many years...

Opportunistic Refactoring
26 Jul 2022 | original ↗

You know developers solve business problems with code. Taking this literally, you are so busy working on new features that you often find yourself making implementation shortcuts. Under the pressure of the product team, you don’t have time to get back and clean it up. You know, in the long run, this is not sustainable. Shortcuts of the code...

Python Performance Profiling
19 Jul 2022 | original ↗

Performance profiling in Python When it comes to performance, you never know where the bottleneck is. Fortunately, the Python ecosystem has tools to eliminate guesswork. They are easy to learn and don’t require codebase instrumentation or preparatory work. When I worked at Doist, I spent hours staring at the profiling plots of our full sync API....

AWS SAM
12 Jul 2022 | original ↗

I started my new project with the AWS SAM framework. In this post, I share some takeaways I have learned about creating serverless applications with it. Learning curve Overall, a different experience from writing a web app built around a classical monolith web framework. If you look at speakers presenting AWS SAM on stage, you may feel that it’s...

My setup for a typescript react project
5 Jul 2022 | original ↗

A memo about my setup for a TypeScript React project: I copy and paste these commands whenever I need to start a new project and ensure that it has all linters, formatters, and pre-commit hooks configured. Initialize proper version I use nvm, and I automatically initialize the node environment with nvm if .nvmrc is found. # File ~/.zshrc test -f...

GitHub Copilot
28 Jun 2022 | original ↗

$100 per year for a GitHub copilot is a no-brainer investment. The expectations from a tool that writes code are as inflated as programmers’ salaries and ego, but Copilot delivers to them. It helps me switch contexts less often and stay in the flow. It saves my mental energy by writing boilerplate code, helping me come up with consistent...

Be kind to your manager
21 Jun 2022 | original ↗

Photo by Elisa Ventur I started my career as a developer, then spent several years as a team lead, and then got back to mostly writing code again. Here, I’m reflecting on the challenges of being a middle manager. Everything is more complicated than it looks. Why my manager is so stressed? They may not know how to manage yet All the time,...

Parse JSON-encoded query strings in FastAPI
14 Jun 2022 | original ↗

React ↔︎ FastAPI dashboard I work on a dashboard that shows charts with filters. React serializes filter parameters into JSON and sends them to the FastAPI in a query string. The FastAPI server returns the data to display the chart. My dashboard FastAPI parses your request and maps it to controller parameters. Can I turn complex parameters in the...

AWS Surprise Bill
7 Jun 2022 | original ↗

Stray service I got a surprise bill from AWS. More than $300 for May and almost $100 for June. Until that, I thought that surprise bills were something that happened to others. My surprise bill from AWS About a month ago, I passed the Amazon MQ workshop. I was sure that I destroyed all the services as I completed it. It turns out that it was not...

State of JS 2021
1 Jun 2022 | original ↗

I came across the state of JavaScript 2021 report, released in February. The report falls into the same bucket as the Python Developer Survey and StackOverflow developer survey, but with focus on the JavaScript ecosystem. I found it to be full of insights. Many features of modern JavaScript are not known to me. As someone who considers himself...

DynamoDB
27 May 2022 | original ↗

How it works Data is stored in tables with items like rows. Rows in tables are uniquely identified by their primary key, consisting of a partition key and an optional sort key. The schema is not defined for the rest of the attributes. Different items can have different attributes or different types of the same attribute. Sharding is automated by...

1984 is now
16 May 2022 | original ↗

Photo by Markus Spiske I could never expect to read an anti-utopia not as a grim overview of the future but as an outline of today’s world. I was reading this to reflect on the current events in Russia and thinking why so many people fell victim to relatively unsophisticated propaganda and became their supporters and apologists. My biggest...

Elastic Beanstalk
11 May 2022 | original ↗

Played with Elastic Beanstalk. At first glance, it looks like a very user-unfriendly version of Heroku. At a second glance, better than it seems. They offer out-of-the-box autoscaling, monitoring, spot instances, and even a wrapper around SQS for queues. The admin panel is quite user-friendly by AWS standards. In general, of course, everything...

Django Plausible Proxy
27 Apr 2022 | original ↗

I released Django Plausible Proxy, a Django application to proxy requests and send server-side events to Plausible Analytics. Plausible is a lightweight and open-source web analytics platform, a privacy-friendly alternative to Google Analytics. I started using it for Django side projects about a month ago and loved its minimalistic interface and...

Shared database antipattern. A three-legged race
11 Feb 2022 | original ↗

In software development, we often make decisions that look like an excellent idea in the short run but result in the horror of maintenance down the road. Letting two independent services use a shared database is one of those ideas. Also, more often, I’ve seen its less obvious variant. There’s a legacy system that’s hard to maintain. When the...

Tech debt hackathons is a waste of time
31 Jan 2022 | original ↗

Photo by Jess Zoerb Repaying your tech debt with a code cleanup hackathon? Planning a bug fixing week to decrease the issues backlog? Likely, you’re wasting your time. When I worked at Doist, we had a long-standing issue with Sentry. Sentry is an error tracking service, and our application recorded every exception there. Quickly, the list of...

You can use Pydantic in SQLAlchemy fields
19 Jan 2022 | original ↗

In a post Don’t let dicts spoil your code I wrote that it’s better to avoid raw data structures such as dicts and lists. Instead, I suggest converting them as soon as possible to objects representing your domain. In a few places of my code, I found that raw dicts appear as attributes of SQLAlchemy models JSON fields. It feels dirty: you have a...

Dealing with large pull requests
8 Jan 2022 | original ↗

Photo by Elise Coates Sometimes, my pull requests grow too big to review. I want to split them into small chunks to be reviewed and merged independently. At the same time, I want to keep working on the feature in a branch, creating newer pull requests until the work is done. Automating PR stacks GitHub has a stacked pull requests thing. For two...

Optimize pip install with wheels
22 Dec 2021 | original ↗

Photo by Jon Cartagena Having that pip install -r requirements.txt that takes ages to install? Make sure you install all binary packages from wheels. When “pip install” can’t find a wheel, it falls back to installing from source. In a large project, dependency after dependency, it slows down builds and makes developers unhappy. What are Python...

How to pretty print SQL from Django
21 Dec 2021 | original ↗

Often, I find myself experimenting in the Django console with ad-hoc model queries. Where it’s not clear how Django turns a queryset to SQL, I find it helpful to print the resulting query. Django QuerySet object has a query attribute. However, its format would benefit from extra formatting. I used pygments and sqlparse to make the output of query...

User Stories for small teams and individuals
10 Dec 2021 | original ↗

Photo by AbsolutVision My wake up call I should admit that all my life, I believed that user stories are feature requests with a fancy and rigid ticket structure. My personal experience is limited. Last week, I had to explain the concept of user stories to a different person, only to learn that I knew nothing about the subject and mostly...

SQLAlchemy and Alembic notes
28 Nov 2021 | original ↗

My notes on SQLAlchemy and Alembic Quickstart snippet A quickstart snippet for the SQLAlchemy ORM playground. # file: playground.py import sqlalchemy as sa from sqlalchemy.orm import declarative_base, sessionmaker import datetime engine = sa.create_engine("sqlite:///:memory:", echo=True) Session = sessionmaker(bind=engine, expire_on_commit=False)...

Codemaps Leaflet
9 Nov 2021 | original ↗

Codemaps is my project to visualize git repos content using the treemaps visualization technique, available at https://usecodemaps.com/. Codemaps of CPython repo At the moment, it uses plotly treemaps and React Plotly.js to display the maps. I liked how it worked, but I didn’t particularly appreciate how sluggish it was on large repositories....

Time Series Caching with Python and Redis
1 Nov 2021 | original ↗

Time series plot for historical pricing of Ethereum transfers Some takeaways on practical time series caching with Python and Redis from the Dashboards project that I implemented with Anyblock Analytics in 2021. The full code of the sample project is available at github.com/imankulov/time-series-caching. TLDR. We replaced generic Flask-caching...

Flow: The Psychology of Optimal Experience
22 Oct 2021 | original ↗

Key idea: our happiness can depend more on our state of mind than on external factors. Almost any activity can become the source of happiness if you nerd in deep enough. The key is to find the activity that you can easily turn into a game and start enjoying the process rather than waiting for the outcome. of learning and self-improvement. Google...

Structure Flask Project With Convention Over Configuration
5 May 2021 | original ↗

Photo by Simone Viani When people ask me what a should beginner Python developer choose, Flask or Django, to start their new web project, all other things being equal, I always recommend Django. Unlike Flask, Django is opinionated. In other words, every time you need to make a choice in Flask, Django has the answer for you. Among others, Django...

21 tools to document your Python project
17 Mar 2021 | original ↗

Photo by Aaron Burden Overview of tools and services to document your Python web application from installation instructions to public API. How to make sure API documentation is in sync with your code. How to serve internal documentation and keep it private. Why documentation matters One of the best questions you can ask a team before joining it,...

Linter for Python Architecture
23 Feb 2021 | original ↗

The goal of the architecture is to organize and constrain the dependencies between the components of your project. For example, in a regular Django project, views depend on models, and not vise versa. If you have utility functions, they shouldn’t depend on any specificities of your project. I was playing with import-linter, and it looks...

Product Management. Explanation for Developers
21 Dec 2020 | original ↗

If you work in a small company, chances are, your organization never had a dedicated role of a product manager. In startups, a product manager is one of the “hats” of the company’s founder. Founders use their vision and gut feelings to identify where the project should move. From a developer’s perspective, the role and the value of a product...

Meeting culture for seniors and veterans
6 Dec 2020 | original ↗

Photo by Mihai Surdu I often see seniors and veterans in the organization making two mistakes: talk when it’s time to listen and not knowing when to shut up. I am guilty as well, so here’s the memo for myself. There’s time to talk, and there’s time to listen. If you’re familiar with the topic, you may feel a burning desire to jump in with your...

Don't let dicts spoil your code
22 Nov 2020 | original ↗

Photo by Martin Sanchez How often do your simple prototypes or ad-hoc scripts turn into fully-fledged applications? The simplicity of organic code growth has a flip side: it becomes too hard to maintain. The proliferation of dicts as primary data structures is a clear signal of tech debt in your code. Fortunately, modern Python provides many...

4 Reading mistakes I made
20 Nov 2020 | original ↗

Photo by Giancarlo Duarte My thoughts on how to become a better reader. The context is non-fiction books. Not reading enough. I decided that there shouldn’t be a moment when I don’t have any book reading. Also, I try not to have a day where I don’t read at least a bit. I know that people don’t like electronic books, but this is my primary way of...

Alignment Matters
25 Oct 2020 | original ↗

Thought on hiring and career planning in application to software development. Skills for sale Imagine you can somehow measure your skills as you measure your weight. In reality, of course, a single number doesn’t catch the multitude of nuances of your traits. An area can become a better representation of your skills. We usually call it “area of...

Python code cleanup for beginners. 12 steps to readable and maintainable code.
18 Sept 2020 | original ↗

Photo by Lea Verou It’s my responsibility to hire Python developers. If you have a GitHub account, I will check it out. Everyone does it. Maybe you don’t know, but your playground project with zero stars can help you to get that job offer. The same goes for your take-home test task. You heard this, when we meet a person for the first time, we...

Boring Meetings and Multitasking
10 Sept 2020 | original ↗

Photo by Chris Montgomery I use multitasking as a measure of the success of our regular team meetings. If someone has time to reply to emails or finish their code during the meeting, then the topic doesn’t concern them, and it’s a waste of their time. It’s that easy. The worst thing you can do here is to reprehend. Saying that someone is not...

On Burnout
2 Sept 2020 | original ↗

My summary of the video The Thing About Burnout from @ashleymcnamara. Symptoms and development Burnout is like PTSD. After some recovery time, you may feel you’re OK, but some triggers can get you back to the burnout state. The burnout recovery time is two years. A two-week-long vacation doesn’t help. The process is burning out is slow. It can...

5 reasons to love Python type hints
25 Aug 2020 | original ↗

I’m a big fan of type hints, and I honestly don’t understand why some people find it ugly or unpythonic. They improve the auto-complete and code navigation in the IDE. They protect you against trivial errors and remind you about corner cases. Beyond IDEs, more and more tools in the Python ecosystem take advantage of typing information. The...

Accelerate. Five-minute summary
15 Aug 2020 | original ↗

A five-minute summary of the book “Accelerate: The Science of Lean Software and DevOps” by Nicole Forsgren, Jez Humble, and Gene Kim. Photo by Ahmad Odeh About the book The overall idea of “Accelerate” is to find how engineering practices affect companies’ performance and the well-being of their employees. This book feels like two books under the...

Feature Branching vs. Continuous Integration
12 May 2020 | original ↗

Photo by Sophie Dale My summary and takeaways from Martin Fowler’s Patterns for Managing Source Code Branches. Summary Having a CI pipeline, running tests on every commit is not Continuous Integration. Copying Open Source best practices to commercial development without understanding their context and limitations can be harmful. Feature branches...

On the Code Ownership
3 May 2020 | original ↗

Photo by Goran Ivos Code ownership is a smell, and we need to avoid it. When several developers contribute to the same codebase, several great minds are thinking of the same problem, which eventually results in a better solution. On the opposite side of the spectrum, with strong code ownership, you inevitably end up with a code that is easier to...

On Feature Flags at Doist
21 Apr 2020 | original ↗

Photo by Dean Brierley I shared our experience introducing feature flags in the tech ecosystem at Doist with our partners from CloudBees. https://www.cloudbees.com/case-study/doist CloudBees, known for rollout.io asked us to share our case study, and it was good opportunity to reflect on our journey towards the feature-flag based development,...

Quote of the Day Privacy Policy
1 Jan 2001 | original ↗

Privacy Policy Roman Imankulov built the Quote of the Day app as a Free app. This SERVICE is provided by Roman Imankulov at no cost and is intended for use as is. This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service. If you choose to use my...

Python project
1 Jan 2001 | original ↗

Here is a starter for a Python project. It can be used as the next step after creating the boilerplate with cookiecutter-python-project Dependencies: deescovery for dynamic discovery of modules python-dotenv for loading environment variables from .env and .env. files (e.g., .env.development) click for creating CLI commands Optionally, IPython for...

Pydantic
1 Jan 2001 | original ↗

Project-specific models See Pydantic model options for more options. from pydantic import BaseModel class Model(BaseModel): """Generic project-specific model.""" class Config: # Allow field population by its name or alias # (helpful for mapping external API values) allow_population_by_field_name = True class FrozenModel(BaseModel): """Generic...

Poetry
1 Jan 2001 | original ↗

Initialization Quickly initialize a new Python environment with Poetry. We explicitly stick to Python 3.11.x (we don’t want automatic upgrades to 3.12, etc.). Also, we activate Poetry virtual environment on startup. poetry init --python '~3.11' --no-interaction --quiet poetry install echo 'source $(poetry env info -p)/bin/activate' > .startup...

Git
1 Jan 2001 | original ↗

Delete merged branches Leftovers from merged branches are distracting. Too many of them make commands like git branch -l useless. Here are some commands to clean them up. Get the list of all branches that have been merged into the current branch. git branch --merged Delete all branches that have been merged into the current branch. We exclude...

External links
1 Jan 2001 | original ↗

Timeless blog posts and articles. I found myself sharing these links over and over again, so I decided to put them here. Software development Questions on software development and organization of team work. Ship / Show / Ask. A modern branching strategy on how to relax code review process without sacrificing quality. Frequency reduces difficulty...

Docker and docker-compose
1 Jan 2001 | original ↗

Helpful services composerize: convert docker run to docker-compose Docker commands Reclaim disk space Clean up disk space by removing all the docker containers older than 14 days. docker image prune -a --filter "until=336h" See Prune unused Docker objects Run a container and attach current directory Example for a specific version of Python....

AWS
1 Jan 2001 | original ↗

Go-to region Use us-east-2 aka US East (Ohio). Set up personal AWS profile to use echo "export AWS_PROFILE=personal" >> .startup Account info for your current requisites aws sts get-caller-identity

About me
1 Jan 2001 | original ↗

I am a passionate full-stack web developer with 16 years of hands-on and management experience. I love helping startups owners and small teams turn their ideas into products. If you want to hire me, schedule a meeting to talk about your project or drop me a line at roman.imankulov@gmail.com Python. My primary area of tech expertise is in web...

↑ these items are from RSS. Visit the blog itself at https://roman.pt/ to find other articles and to appreciate the author's digital home.