Push it harder (Part 2)
Message types and attributes
There are two types of messages: notification and data.
- Notification messages are automatically displayed to end-user devices on behalf of the client app. They have a predefined set of keys and an optional data payload of custom key-value pairs.
- The client app is responsible for processing data messages. Data messages have only custom key-value pairs with no reserved key names.
You can also configure whether your notification message should be collapsible or not by using the collapse_key parameter.
- A collapsible message is a message that may be replaced by a new message if it has yet to be delivered to the device. Common use cases of collapsible messages are messages used to tell a mobile app to sync data from the server.
- A non-collapsible message denotes that each individual message is delivered to the device. Notification messages are always collapsible and will ignore the collapse_key parameter.
- Important! FCM does not guarantee the order of delivery.
A notification has a priority level.
- For Android, there are two options: normal and high.
- Apple's max priority is 5.
- Normal is the default priority for data messages. Messages are delivered immediately when the app is in the foreground. When the device is in Doze, the delivery may be delayed to save some battery.
You may also want to set a TTL for a message. There are some situations when instant delivery is impossible*. So, FCM stores messages and sends them as soon as it is feasible. But, there are some cases in which you may want to drop those undelivered messages. For example, video chat incoming calls or expiring invitation events.
*Device could be turned off, offline, or otherwise unavailable
#dev
Message types and attributes
There are two types of messages: notification and data.
- Notification messages are automatically displayed to end-user devices on behalf of the client app. They have a predefined set of keys and an optional data payload of custom key-value pairs.
- The client app is responsible for processing data messages. Data messages have only custom key-value pairs with no reserved key names.
You can also configure whether your notification message should be collapsible or not by using the collapse_key parameter.
- A collapsible message is a message that may be replaced by a new message if it has yet to be delivered to the device. Common use cases of collapsible messages are messages used to tell a mobile app to sync data from the server.
- A non-collapsible message denotes that each individual message is delivered to the device. Notification messages are always collapsible and will ignore the collapse_key parameter.
- Important! FCM does not guarantee the order of delivery.
A notification has a priority level.
- For Android, there are two options: normal and high.
- Apple's max priority is 5.
- Normal is the default priority for data messages. Messages are delivered immediately when the app is in the foreground. When the device is in Doze, the delivery may be delayed to save some battery.
You may also want to set a TTL for a message. There are some situations when instant delivery is impossible*. So, FCM stores messages and sends them as soon as it is feasible. But, there are some cases in which you may want to drop those undelivered messages. For example, video chat incoming calls or expiring invitation events.
*Device could be turned off, offline, or otherwise unavailable
#dev
❤3
Job interviews are cool when you're not a junior anymore
If you're still a junior with no commercial experience, it's quite tricky to land a job.
- You have almost nothing to put in your resume (at least you think so).
- The competition is damn high.
- You probably have to complete a test task before a technical interview.
- You can be sure that you'll be asked many technical questions, so you have no choice but to prepare for everything*.
- When it finally comes to the interview, you feel nervous: shaking knees, sweaty palms. I know, I've been there. The only way to beat this feeling is to pass more interviews.
Everything changes once you've convinced yourself that you're no longer an immature junior.**
- There is no water in your resume because you now have an experience you're not ashamed to talk about. Like, "I've developed several apps from scratch, here're the links to them. Implemented this and this. Here is my tech stack."
- No test tasks anymore. The choice is rich while the competition is pretty low, so you can afford to decline companies that require you to do a test task.***
- The interview looks more like a pleasant conversation rather than an interrogation. If you've been preparing for interviews being a junior dev, you're probably ready for all these techy questions. Some people won't even ask you these questions - they are more interested to hear about things you've done, technologies and approaches you've used.
- You have a bit of experience in interviews, so you know that you should be able to talk about yourself and your projects for 2-4 minutes, prepare questions for the company, etc.
- You finally have an answer to the question: "What is the most interesting/challenging task you've been working on?"
*Language, framework, libraries, OOP, basic CS things, algorithms, and data structures
**You probably have to work for 1-2 years before doing this
***If you're interested in a particular job, then go for it, do whatever it takes
#career #thoughts
If you're still a junior with no commercial experience, it's quite tricky to land a job.
- You have almost nothing to put in your resume (at least you think so).
- The competition is damn high.
- You probably have to complete a test task before a technical interview.
- You can be sure that you'll be asked many technical questions, so you have no choice but to prepare for everything*.
- When it finally comes to the interview, you feel nervous: shaking knees, sweaty palms. I know, I've been there. The only way to beat this feeling is to pass more interviews.
Everything changes once you've convinced yourself that you're no longer an immature junior.**
- There is no water in your resume because you now have an experience you're not ashamed to talk about. Like, "I've developed several apps from scratch, here're the links to them. Implemented this and this. Here is my tech stack."
- No test tasks anymore. The choice is rich while the competition is pretty low, so you can afford to decline companies that require you to do a test task.***
- The interview looks more like a pleasant conversation rather than an interrogation. If you've been preparing for interviews being a junior dev, you're probably ready for all these techy questions. Some people won't even ask you these questions - they are more interested to hear about things you've done, technologies and approaches you've used.
- You have a bit of experience in interviews, so you know that you should be able to talk about yourself and your projects for 2-4 minutes, prepare questions for the company, etc.
- You finally have an answer to the question: "What is the most interesting/challenging task you've been working on?"
*Language, framework, libraries, OOP, basic CS things, algorithms, and data structures
**You probably have to work for 1-2 years before doing this
***If you're interested in a particular job, then go for it, do whatever it takes
#career #thoughts
👍5🥰1
Meditation
I've been struggling last several years to make a habit of meditating for at least 10 minutes a day. My longest streak is about 1.5 months so far. And still, I witnessed some positive shifts in my life at that time, such as increased self-awareness and focus on work, reduced stress and anxiety levels. But somehow, this practice doesn't stick with me.
Yesterday, I stumbled across a review [RU] of the book on meditation. This book is full of studies on how this simple process changes your mind, brain, and body. It answers the main question: "Why should one meditate?". Moreover, the author of the review gave it 10/10. So, if you still think that meditation is only for people who believe in the supernatural or yogis that want to learn to levitate, then you definitely need to read the book.
After reading the review, I've decided to give this habit another shot. Probably, I'll also read a book sooner or later. So, I'm officially starting a new challenge. From now on, I'll meditate for 10 minutes every single day.
I don't plan to write daily reports on how things are going, but I do plan to post my thoughts after 1/3/6 months in the comments under this post.
#habits #books
I've been struggling last several years to make a habit of meditating for at least 10 minutes a day. My longest streak is about 1.5 months so far. And still, I witnessed some positive shifts in my life at that time, such as increased self-awareness and focus on work, reduced stress and anxiety levels. But somehow, this practice doesn't stick with me.
Yesterday, I stumbled across a review [RU] of the book on meditation. This book is full of studies on how this simple process changes your mind, brain, and body. It answers the main question: "Why should one meditate?". Moreover, the author of the review gave it 10/10. So, if you still think that meditation is only for people who believe in the supernatural or yogis that want to learn to levitate, then you definitely need to read the book.
After reading the review, I've decided to give this habit another shot. Probably, I'll also read a book sooner or later. So, I'm officially starting a new challenge. From now on, I'll meditate for 10 minutes every single day.
I don't plan to write daily reports on how things are going, but I do plan to post my thoughts after 1/3/6 months in the comments under this post.
#habits #books
👍5
Perfect form
As they say, frontend and mobile developers mostly do two things:
1. Transferring JSON back and forth
2. Creating forms
While transferring JSON is a pretty trivial task, form creation can be challenging from a UX perspective.
I do see poor forms quite often. How do I know that they are flawed? I simply don't want to fill them out as I'm too lazy. And a mystery of the millennium remains unsolved:
"Do you really want me to google my postal code if I've already filled out my full address? Isn't there any "super-advanced" service that can match them?"
Here are some tips for better mobile form UX:
- It should be short and simple
As I said, when I see a form, I estimate my time and effort to fill it. I run away or become unhappy if it exceeds some pretty low value. Leave only necessary fields or if you actually need all this data from a user, make sure you don't show all the fields at once*.
- Automatic focus switching
When a user is done with one input and presses "okay" on the keyboard, switch focus to the next field, so he doesn't need to scroll down and explicitly tap on it.
- Dynamic validation
The most crucial thing. Validate fields and give feedback in real-time, not when the user hits submit button. But don't do it after every single modification. Make a small debounce. 500-1000 ms after the user stopped typing or moved to the next field is enough.
In 2009, Luke Wroblewski tested inline validation against post-submission validation and found the following results for the inline version:
✔️ 22% increase in success rate
✔️ 22% decrease in errors made
✔️ 31% increase in satisfaction rating
✔️ 42% decrease in completion times
- Matching keyboard type
For example, if a user is expected to type his phone number, display the numeric keypad.
- Provide placeholders and masked inputs
Sometimes when I fill out some complicated form, I don't know know how my tracking number should look like. Then I see a placeholder like "EZ987654321", which creates an "Aha!" moment, so I look for a similar-looking value in the receipt and copy-paste it.
The most popular use-case for masked input is a phone number input. It automatically formats the data you provide. You type 79998887766 or just 9998887766, you see +7 (999) 888-77-66.
- Avoid dropdowns
It's just not convenient on mobile devices.
- Do not clear the form on submit if some field is invalid
I'm too lazy to do it all over again
- Autocomplete
I'm too lazy to fill in my card details every time I want to buy something on the internet. This example suits well for web apps.
- Use biometrics instead of a login form
I'm too lazy to type my email and password every time to check my balance. But it's almost effortless to put my finger on the button.
- Disable the button during the submission process
By doing this, you prevent users from accidentally tapping the button again which creates duplicate submissions. Moreover, you give instant feedback: "We've received your submission".
Here is a great thorough article on this theme, where the author provides more useful tips with visual examples.
*Multi-step forms
#dev #ux
As they say, frontend and mobile developers mostly do two things:
1. Transferring JSON back and forth
2. Creating forms
While transferring JSON is a pretty trivial task, form creation can be challenging from a UX perspective.
I do see poor forms quite often. How do I know that they are flawed? I simply don't want to fill them out as I'm too lazy. And a mystery of the millennium remains unsolved:
"Do you really want me to google my postal code if I've already filled out my full address? Isn't there any "super-advanced" service that can match them?"
Here are some tips for better mobile form UX:
- It should be short and simple
As I said, when I see a form, I estimate my time and effort to fill it. I run away or become unhappy if it exceeds some pretty low value. Leave only necessary fields or if you actually need all this data from a user, make sure you don't show all the fields at once*.
- Automatic focus switching
When a user is done with one input and presses "okay" on the keyboard, switch focus to the next field, so he doesn't need to scroll down and explicitly tap on it.
- Dynamic validation
The most crucial thing. Validate fields and give feedback in real-time, not when the user hits submit button. But don't do it after every single modification. Make a small debounce. 500-1000 ms after the user stopped typing or moved to the next field is enough.
In 2009, Luke Wroblewski tested inline validation against post-submission validation and found the following results for the inline version:
✔️ 22% increase in success rate
✔️ 22% decrease in errors made
✔️ 31% increase in satisfaction rating
✔️ 42% decrease in completion times
- Matching keyboard type
For example, if a user is expected to type his phone number, display the numeric keypad.
- Provide placeholders and masked inputs
Sometimes when I fill out some complicated form, I don't know know how my tracking number should look like. Then I see a placeholder like "EZ987654321", which creates an "Aha!" moment, so I look for a similar-looking value in the receipt and copy-paste it.
The most popular use-case for masked input is a phone number input. It automatically formats the data you provide. You type 79998887766 or just 9998887766, you see +7 (999) 888-77-66.
- Avoid dropdowns
It's just not convenient on mobile devices.
- Do not clear the form on submit if some field is invalid
I'm too lazy to do it all over again
- Autocomplete
I'm too lazy to fill in my card details every time I want to buy something on the internet. This example suits well for web apps.
- Use biometrics instead of a login form
I'm too lazy to type my email and password every time to check my balance. But it's almost effortless to put my finger on the button.
- Disable the button during the submission process
By doing this, you prevent users from accidentally tapping the button again which creates duplicate submissions. Moreover, you give instant feedback: "We've received your submission".
Here is a great thorough article on this theme, where the author provides more useful tips with visual examples.
*Multi-step forms
#dev #ux
👍6
I've changed my mind about office work
If you don't know, I've recently switched my job place. And now I'm officially a member of the CodePilots team. I still do develop cross-platform mobile apps using the Flutter framework, though.
I always thought that working from home was the best thing mankind had invented. I've never understood my friends who prefer office work. My main argument was that I didn't want to spend several hours in a traffic jam daily. So I was looking for a fully remote job. I even declined one job offer right after I knew that I would have to show up in an office at least three times a week*. By the way, the office was just about 15 minutes away from my place.
My new company allows me to work remotely as long as I want to, though there is an office in my city. This means that now I have an opportunity to work in an office while nobody is forcing me to do it.
Given this freedom of choice, I've decided to try to work a couple of days in the office. And it was a game-changer.
Here are a few advantages of working in the office compared to working remotely I've noticed so far:
- You're not sitting at home all alone all day long, letting your social skills slowly degrade. You go out. You meet a lot of new cool people with the same interests as yours in person. So, you can chat with them during the launch time.
- An office is a place where you don't need to gather all your willpower to get things done. You sit down - you work, just like everybody else in the room.
- Some people have small devils at home that don't allow them to concentrate on something besides their cry. Probably, an office is their "lifeboat."
The problem with transportation remains. Despite this, I started working in the office 3-4 days a week without noticing it.
The conclusion is that it's best when the company takes your interests into account and allows you to pick an option that works out best for you.
*people call it a hybrid work
#career #efficiency #thoughts
If you don't know, I've recently switched my job place. And now I'm officially a member of the CodePilots team. I still do develop cross-platform mobile apps using the Flutter framework, though.
I always thought that working from home was the best thing mankind had invented. I've never understood my friends who prefer office work. My main argument was that I didn't want to spend several hours in a traffic jam daily. So I was looking for a fully remote job. I even declined one job offer right after I knew that I would have to show up in an office at least three times a week*. By the way, the office was just about 15 minutes away from my place.
My new company allows me to work remotely as long as I want to, though there is an office in my city. This means that now I have an opportunity to work in an office while nobody is forcing me to do it.
Given this freedom of choice, I've decided to try to work a couple of days in the office. And it was a game-changer.
Here are a few advantages of working in the office compared to working remotely I've noticed so far:
- You're not sitting at home all alone all day long, letting your social skills slowly degrade. You go out. You meet a lot of new cool people with the same interests as yours in person. So, you can chat with them during the launch time.
- An office is a place where you don't need to gather all your willpower to get things done. You sit down - you work, just like everybody else in the room.
- Some people have small devils at home that don't allow them to concentrate on something besides their cry. Probably, an office is their "lifeboat."
The problem with transportation remains. Despite this, I started working in the office 3-4 days a week without noticing it.
The conclusion is that it's best when the company takes your interests into account and allows you to pick an option that works out best for you.
*people call it a hybrid work
#career #efficiency #thoughts
👍3🤔1
And here is my first technical article on Medium.
Check it out if you are interested in Flutter and already familiar with the BLoC pattern, but you don't like to write too much boilerplate code every time you need another BLoC.
Any feedback is appreciated.
#dev #flutter
Check it out if you are interested in Flutter and already familiar with the BLoC pattern, but you don't like to write too much boilerplate code every time you need another BLoC.
Any feedback is appreciated.
#dev #flutter
Medium
Freezed BLoC — Flutter State Management without boilerplate
In our team in MorningStars, we are using the BLoC library along with Freezed and it helps significantly reduce time on writing boilerplate…
👍2
What is a force update, and why every mobile app needs this feature
Let's say you're developing a banking app, and one day you find some serious security issues in a previous version of the app.
What do you do next?
You release a new version with a patch that aims to solve all of them.
50% of your users seemlessly get the latest version of the app as they have "automatic updates" feature enabled. The other half will still use an outdated version of the app, suffer from those issues, give it one star and write negative feedback in the store, so no one will trust your app/bank when they see these reviews.
How to avoid such situations?
That's where the "forced update" comes into play.
It is a simple mechanism that prevents your users of using an outdated version of the app as soon as you say so.
How does it work?
During the app initialization process you ask your server or Firebase remote config what the minimum allowable version of the app is. If current version number is lower than the allowable one, show user an alert that he needs to update the app with only one possible way of closing it - actually updating the app. And don't forget about the "Update" button, which should redirect the user to the store.
Furthermore, you can also implement "soft update*" feature, but you must be careful not to overwhelm your users with annoying pop-ups every time they enter your app.
I've described only one possible case when this feature could be useful. Another one may be when your backend introduces some breaking changes with the latest update, and your app turns into a pumpkin unable to support these changes.
As you can see, this feature is simple to implement, though it may save your life in the future. So, I believe that every mobile app must have this feature right from the first release.
*telling a user that a new version of the app is available, while allowing to hide the pop-up and continue using the current version
#dev
Let's say you're developing a banking app, and one day you find some serious security issues in a previous version of the app.
What do you do next?
You release a new version with a patch that aims to solve all of them.
50% of your users seemlessly get the latest version of the app as they have "automatic updates" feature enabled. The other half will still use an outdated version of the app, suffer from those issues, give it one star and write negative feedback in the store, so no one will trust your app/bank when they see these reviews.
How to avoid such situations?
That's where the "forced update" comes into play.
It is a simple mechanism that prevents your users of using an outdated version of the app as soon as you say so.
How does it work?
During the app initialization process you ask your server or Firebase remote config what the minimum allowable version of the app is. If current version number is lower than the allowable one, show user an alert that he needs to update the app with only one possible way of closing it - actually updating the app. And don't forget about the "Update" button, which should redirect the user to the store.
Furthermore, you can also implement "soft update*" feature, but you must be careful not to overwhelm your users with annoying pop-ups every time they enter your app.
I've described only one possible case when this feature could be useful. Another one may be when your backend introduces some breaking changes with the latest update, and your app turns into a pumpkin unable to support these changes.
As you can see, this feature is simple to implement, though it may save your life in the future. So, I believe that every mobile app must have this feature right from the first release.
*telling a user that a new version of the app is available, while allowing to hide the pop-up and continue using the current version
#dev
👍6
Some useful links from previous weeks
As I've started driving to the office 4-5 times per week, I get at least an hour a day to consume information. Sometimes I prefer to look out the window and listen to the music as it sets my mood for the day, but other days I want to read or listen to something interesting and useful at the same time.
First of all, I've rediscovered the Podlodka podcast. Of course, I don't mindlessly listen to every episode of it. Here are some that I've found interesting:
1. Mindfulness - paradoxically, one of the most popular episode on their podcast, as they say. Totally worth your time if you want to be a happier person (who doesn't?).
2. Essential knowledge for programmers - checklist for every programmer, especially useful for newbies.
3. Technoblogging - Vasiliy Zubarev (Vas3k) on how to successfully run a blog and build a closed club around it.
I've read several posts from Vas3k blog (en, ru) after listening to conversation with him (1, 2, 3, 4). I guess I just like the way he delivers his thoughts. Long simple authentic posts on popular/contraversial/unclear topics that you read in the same breath. If somebody says that longreads are dead nowadays, members of the Vas3k club are ready to debate.
#links
As I've started driving to the office 4-5 times per week, I get at least an hour a day to consume information. Sometimes I prefer to look out the window and listen to the music as it sets my mood for the day, but other days I want to read or listen to something interesting and useful at the same time.
First of all, I've rediscovered the Podlodka podcast. Of course, I don't mindlessly listen to every episode of it. Here are some that I've found interesting:
1. Mindfulness - paradoxically, one of the most popular episode on their podcast, as they say. Totally worth your time if you want to be a happier person (who doesn't?).
2. Essential knowledge for programmers - checklist for every programmer, especially useful for newbies.
3. Technoblogging - Vasiliy Zubarev (Vas3k) on how to successfully run a blog and build a closed club around it.
I've read several posts from Vas3k blog (en, ru) after listening to conversation with him (1, 2, 3, 4). I guess I just like the way he delivers his thoughts. Long simple authentic posts on popular/contraversial/unclear topics that you read in the same breath. If somebody says that longreads are dead nowadays, members of the Vas3k club are ready to debate.
#links
👍7
Diploma and thoughts on dapps
As you may know, I've been intensively writing my diploma for the last couple of weeks. Of course, right before the deadline. Actually, the last week was a huge mess.
The point was to develop software that enables paid subscriptions for Telegram channels. Moreover, the solution had to be as decentralized as possible. To put it simply, there shouldn't be one point of failure, and users should be able to transfer tokens back and forth without the involvement of a third party. Another requirement was a usage of some stablecoin instead of highly volatile token.
With this in mind I've digged into blockchain technology. The final solution consists of four components:
1. Smart-contract (solidity/brownie/python/pytest) that acts as a database and stores all the logic. Source code is right here.
2. Telegram bot (python/python-telegram-bot/web3.py) that acts as an admin in provided channels adding/removing subscribers. It also helps to verify a user and added channels. Moreover, bot can retrieve an information from smart-contract.
3. Frontend (dart/flutter/flutter_web3) that integrates with Metamask and aims to interact with smart-contract. It has to be here, so users can sign transactions with their private keys and pay a small commission for every transaction that changes state.
4. Script (python, web3.py, cron) that triggers the payment process for debtors (runs daily).
Here are some of the insights and conclusions I came to during the research and development process:
- Transactions that aim to change the state of smart-contract are not free. These transactions require gas. Gas is like a fuel that allows Ethereum network to operate. Gas price measures in ETH. At the time I was testing the interaction with the smart-contract, each transaction cost me about 0.3$. Happily, I was testing it on Rinkeby testnet, where you can get some ETH for free.
- Many apps that claim that they are dapps are at best only half dapps. Fully decentralized solutions shouldn't depend on centralized servers or databases. My solution can't be fully decentralized as Telegram is a centralized software. On top of that, I can't give a bot token to everyone, so they can do whatever they want.
- If some dapp asks you to approve spending of a large number of tokens, claiming it'll improve user experience, don't go along with it. Even if contract is open sourced. If there is a hole in smart-contract, all approved tokens could disappear forever.
- It follows from the previous point that the contract must be covered by tests up and down.
- Solidity isn't really cool. I had to store an array of user addresses for a mapping that maps user address to user structure only to be able to iterate through users. I've also couldn't find any utility methods for arrays/strings/mappings. How to live without generics?!
- One authoritive HR said that large companies, during the recruitment process, look through developer's CV and make a note when they see cryptoprojects in the experience section. It may show that money is more important for a developer than solving complex problems.
#crypto #blockchain #dev #thoughts
As you may know, I've been intensively writing my diploma for the last couple of weeks. Of course, right before the deadline. Actually, the last week was a huge mess.
The point was to develop software that enables paid subscriptions for Telegram channels. Moreover, the solution had to be as decentralized as possible. To put it simply, there shouldn't be one point of failure, and users should be able to transfer tokens back and forth without the involvement of a third party. Another requirement was a usage of some stablecoin instead of highly volatile token.
With this in mind I've digged into blockchain technology. The final solution consists of four components:
1. Smart-contract (solidity/brownie/python/pytest) that acts as a database and stores all the logic. Source code is right here.
2. Telegram bot (python/python-telegram-bot/web3.py) that acts as an admin in provided channels adding/removing subscribers. It also helps to verify a user and added channels. Moreover, bot can retrieve an information from smart-contract.
3. Frontend (dart/flutter/flutter_web3) that integrates with Metamask and aims to interact with smart-contract. It has to be here, so users can sign transactions with their private keys and pay a small commission for every transaction that changes state.
4. Script (python, web3.py, cron) that triggers the payment process for debtors (runs daily).
Here are some of the insights and conclusions I came to during the research and development process:
- Transactions that aim to change the state of smart-contract are not free. These transactions require gas. Gas is like a fuel that allows Ethereum network to operate. Gas price measures in ETH. At the time I was testing the interaction with the smart-contract, each transaction cost me about 0.3$. Happily, I was testing it on Rinkeby testnet, where you can get some ETH for free.
- Many apps that claim that they are dapps are at best only half dapps. Fully decentralized solutions shouldn't depend on centralized servers or databases. My solution can't be fully decentralized as Telegram is a centralized software. On top of that, I can't give a bot token to everyone, so they can do whatever they want.
- If some dapp asks you to approve spending of a large number of tokens, claiming it'll improve user experience, don't go along with it. Even if contract is open sourced. If there is a hole in smart-contract, all approved tokens could disappear forever.
- It follows from the previous point that the contract must be covered by tests up and down.
- Solidity isn't really cool. I had to store an array of user addresses for a mapping that maps user address to user structure only to be able to iterate through users. I've also couldn't find any utility methods for arrays/strings/mappings. How to live without generics?!
- One authoritive HR said that large companies, during the recruitment process, look through developer's CV and make a note when they see cryptoprojects in the experience section. It may show that money is more important for a developer than solving complex problems.
#crypto #blockchain #dev #thoughts
👍4🔥3
Be willing to learn
One day we've all written suboptimal code. Maybe it lacked decomposition, maybe there was some misleading naming, or the code was ready to blow up on the first edge case. It usually happens due to a lack of experience. And it is totally fine. What's not fine is when a developer continuously writes this code, applying bad practices to every project he/she touches without thinking something's wrong.
In such a case, every party suffers. The company spends more hours fixing bugs and adding new features. Moreover, other devs may not understand the code if the guy suddenly disappears. The product owner gets a buggy product with vague development prospects. The developer has fewer opportunities to find another good job if the recruitment process is done right during the tech interview.
There might be several reasons for this:
- Developer has never seen good code, and nobody has ever reviewed his/her projects, so a developer doesn't know what good code feels and looks like
- Developer doesn't want to learn new stuff and try something unknown
The first scenario is not that bad. You can always ask your more experienced colleague or some senior dev from the community to review your project. I'm always happy to help and share my approaches with anybody from the community if it'd make their life a bit easier and code - more maintainable.
The second scenario is much worse, but I can understand these people. If you're a freelancer or your company is satisfied with your work, and you're comfortable with your code, then there is no reason to change anything until something blows up (which will be an unpleasant surprise for all parties mentioned above).
So what's the point?
The point is that it doesn't work this way in our industry. If you want to evolve as a developer to have more career opportunities to work on something that matters to you and millions of people => you should always look for ways to improve your practices and make the development process more predictable.
One day we've all written suboptimal code. Maybe it lacked decomposition, maybe there was some misleading naming, or the code was ready to blow up on the first edge case. It usually happens due to a lack of experience. And it is totally fine. What's not fine is when a developer continuously writes this code, applying bad practices to every project he/she touches without thinking something's wrong.
In such a case, every party suffers. The company spends more hours fixing bugs and adding new features. Moreover, other devs may not understand the code if the guy suddenly disappears. The product owner gets a buggy product with vague development prospects. The developer has fewer opportunities to find another good job if the recruitment process is done right during the tech interview.
There might be several reasons for this:
- Developer has never seen good code, and nobody has ever reviewed his/her projects, so a developer doesn't know what good code feels and looks like
- Developer doesn't want to learn new stuff and try something unknown
The first scenario is not that bad. You can always ask your more experienced colleague or some senior dev from the community to review your project. I'm always happy to help and share my approaches with anybody from the community if it'd make their life a bit easier and code - more maintainable.
The second scenario is much worse, but I can understand these people. If you're a freelancer or your company is satisfied with your work, and you're comfortable with your code, then there is no reason to change anything until something blows up (which will be an unpleasant surprise for all parties mentioned above).
So what's the point?
The point is that it doesn't work this way in our industry. If you want to evolve as a developer to have more career opportunities to work on something that matters to you and millions of people => you should always look for ways to improve your practices and make the development process more predictable.
❤3👍1
At some point, being “just a mobile developer” stopped feeling like enough.
I’ve been a Flutter mobile developer for the last 5 years, and eventually I hit that familiar feeling: plateau. I’ve always believed that constant professional growth is mandatory, but I started questioning where that growth should go next.
Native mobile? iOS / Android? Honestly, it feels like more of the same. For Flutter, knowing how to write your own plugins already covers most real needs. I don’t want to switch to native. It feels too narrow.
Also, I still don’t fully understand why two separate teams often build the same app for different platforms, when a huge amount of code can be reused. I get that sometimes there’s a massive legacy codebase that’s hard to rewrite once and for all, or companies simply can’t find a strong cross-platform team — but still, it feels inefficient.
Then there’s backend. For a long time I thought: why do I need it as a mobile developer? There was simply nowhere to apply it in my daily work.
There’s also the management side. I’ve been a team lead for the last couple of years, and I’ve already developed some management skills — communication, planning, responsibility for delivery. But if I’m honest, my focus is still much more on the technical side.
About 1.5 years ago a new thought appeared:
What if the next step is becoming a CTO of a product I actually care about?
That role gives you much more influence, responsibility, and yes — better money. But let’s be honest: if you only know mobile, becoming a CTO is extremely hard.
Even though I graduated as a software engineer and almost started my career as a Python backend developer, I realized how many gaps I had:
• deployment & infrastructure
• databases (real-world usage, not just theory)
• message brokers, microservices, system design
And then the last year happened.
Chatbots, vibe-coding, agentic coding — this wave hit me like a real wake-up call. Suddenly, improving my skills wasn’t optional anymore. At the same time, these tools made learning backend much more accessible and faster.
So here’s my current plan:
1. Go deep into modern AI tools and solutions — maximum level. I’ve got serious FOMO here I need to get rid of.
2. Build pet project, read books, watch conferences, talk to other developers to grow solid backend skills.
My backend stack right now: Python + FastAPI.
Let’s see where this road leads 🚀
PS. This post was approved by ChatGPT
I’ve been a Flutter mobile developer for the last 5 years, and eventually I hit that familiar feeling: plateau. I’ve always believed that constant professional growth is mandatory, but I started questioning where that growth should go next.
Native mobile? iOS / Android? Honestly, it feels like more of the same. For Flutter, knowing how to write your own plugins already covers most real needs. I don’t want to switch to native. It feels too narrow.
Also, I still don’t fully understand why two separate teams often build the same app for different platforms, when a huge amount of code can be reused. I get that sometimes there’s a massive legacy codebase that’s hard to rewrite once and for all, or companies simply can’t find a strong cross-platform team — but still, it feels inefficient.
Then there’s backend. For a long time I thought: why do I need it as a mobile developer? There was simply nowhere to apply it in my daily work.
There’s also the management side. I’ve been a team lead for the last couple of years, and I’ve already developed some management skills — communication, planning, responsibility for delivery. But if I’m honest, my focus is still much more on the technical side.
About 1.5 years ago a new thought appeared:
What if the next step is becoming a CTO of a product I actually care about?
That role gives you much more influence, responsibility, and yes — better money. But let’s be honest: if you only know mobile, becoming a CTO is extremely hard.
Even though I graduated as a software engineer and almost started my career as a Python backend developer, I realized how many gaps I had:
• deployment & infrastructure
• databases (real-world usage, not just theory)
• message brokers, microservices, system design
And then the last year happened.
Chatbots, vibe-coding, agentic coding — this wave hit me like a real wake-up call. Suddenly, improving my skills wasn’t optional anymore. At the same time, these tools made learning backend much more accessible and faster.
So here’s my current plan:
1. Go deep into modern AI tools and solutions — maximum level. I’ve got serious FOMO here I need to get rid of.
2. Build pet project, read books, watch conferences, talk to other developers to grow solid backend skills.
My backend stack right now: Python + FastAPI.
Let’s see where this road leads 🚀
❤7🔥6🎉4😁1
How my LLM coding subscriptions escalated
It started very innocently.
1. Free ChatGPT
Back then it was already called vibecoding, but I still didn’t really believe in LLMs for real coding tasks.
I mostly used it instead of Google. A bit more advanced Google.
I clearly remember questions like:
"Our designer has an animation idea (attached file) — what’s the best way to implement this in Flutter?”
Useful, but very exploratory. No real trust yet.
2. ChatGPT Plus ($20, on my girlfriend’s account)
I still didn’t fully trust GPT to write code for me.
But the Pro subscription helped in a different way:
– longer conversations
– architectural discussions
– switching between models and access to latest models
– sanity-checking ideas
It felt more like a whiteboard discussion than coding assistance.
3. Free Cursor (≈ 1 month)
Copy-pasting from ChatGPT into my project got annoying very fast.
Most real tasks need context across multiple files.
I was already coding in VS Code anyway, so Cursor felt like a smart wrapper on top of my usual workflow, not a completely new tool.
I mostly used Cursor via tab completion — it honestly felt like it was reading my mind.
Occasionally I asked the side-panel agent questions, but not that often.
4. Cursor Pro ($20)
The free tier wasn’t enough anymore:
– small request limits
– even tab completion stops working after some time
I stayed on it for a few months and slowly adapted.
More and more routine tasks moved to the agent.
I learned about rules, connected MCPs (Figma MCP is 🔥 for frontend).
Cursor also kept adding bonus credits — roughly +$80–90 on top of a single monthly subscription.
I still mostly used it for routine tasks — cases where:
– everything is clear
– I can quickly validate the result
– and fix things manually if needed
5. Cursor $20 + Claude Code $20
I kept hitting Cursor’s limits and decided to try the already hyped Claude Code in parallel.
I had heard about skills and sub-agents, but never really touched them (now they are also available in latest Cursor version).
I spent ~45 minutes experimenting non-stop, building my first custom skill... and hit the 5-hour limit before it was even ready.
Opus 4.5, thinking mode.
Pain.
Sadness.
Now what?
6. Cursor $20 + Claude Code $100
Relatively recently, I upgraded to the 10× Claude Code plan.
If you want to actually experiment with agents, sub-agents, skills, and hooks — iterate, break things, rebuild — upgrading the subscription starts to make sense.
My current setup:
– simple tasks → Cursor (with composer-1). Works surprisingly well.
– more complex tasks → Claude Code (Sonnet 4.5 or Opus 4.5)
What is your setup?
It started very innocently.
1. Free ChatGPT
Back then it was already called vibecoding, but I still didn’t really believe in LLMs for real coding tasks.
I mostly used it instead of Google. A bit more advanced Google.
I clearly remember questions like:
"Our designer has an animation idea (attached file) — what’s the best way to implement this in Flutter?”
Useful, but very exploratory. No real trust yet.
2. ChatGPT Plus ($20, on my girlfriend’s account)
I still didn’t fully trust GPT to write code for me.
But the Pro subscription helped in a different way:
– longer conversations
– architectural discussions
– switching between models and access to latest models
– sanity-checking ideas
It felt more like a whiteboard discussion than coding assistance.
3. Free Cursor (≈ 1 month)
Copy-pasting from ChatGPT into my project got annoying very fast.
Most real tasks need context across multiple files.
I was already coding in VS Code anyway, so Cursor felt like a smart wrapper on top of my usual workflow, not a completely new tool.
I mostly used Cursor via tab completion — it honestly felt like it was reading my mind.
Occasionally I asked the side-panel agent questions, but not that often.
4. Cursor Pro ($20)
The free tier wasn’t enough anymore:
– small request limits
– even tab completion stops working after some time
I stayed on it for a few months and slowly adapted.
More and more routine tasks moved to the agent.
I learned about rules, connected MCPs (Figma MCP is 🔥 for frontend).
Cursor also kept adding bonus credits — roughly +$80–90 on top of a single monthly subscription.
I still mostly used it for routine tasks — cases where:
– everything is clear
– I can quickly validate the result
– and fix things manually if needed
5. Cursor $20 + Claude Code $20
I kept hitting Cursor’s limits and decided to try the already hyped Claude Code in parallel.
I had heard about skills and sub-agents, but never really touched them (now they are also available in latest Cursor version).
I spent ~45 minutes experimenting non-stop, building my first custom skill... and hit the 5-hour limit before it was even ready.
Opus 4.5, thinking mode.
Pain.
Sadness.
Now what?
6. Cursor $20 + Claude Code $100
Relatively recently, I upgraded to the 10× Claude Code plan.
If you want to actually experiment with agents, sub-agents, skills, and hooks — iterate, break things, rebuild — upgrading the subscription starts to make sense.
My current setup:
– simple tasks → Cursor (with composer-1). Works surprisingly well.
– more complex tasks → Claude Code (Sonnet 4.5 or Opus 4.5)
What is your setup?
👍4🤯4😱2🤬1
AI can ship your UI faster — unless your Figma is chaos
Implementing mobile layouts is boring work. You're essentially a human compiler — copying padding values, font sizes, and color codes from Figma to your IDE. No creativity, no challenge, just routine.
I tried using Cursor with design screenshots. It would generate something similar, but never accurate enough:
- Inconsistent spacing values
- Wrong font sizes and weights
- Slightly off colors (`#2A2A2A` instead of `#1F1F1F`)
- Design icons replaced with similar ones from MaterialIcons
Then I discovered Figma MCP and everything changed.
Yes, it costs €12/month, but it's worth every cent.
Figma MCP is a bridge between Figma and your coding agent. It provides tools that allow the agent to extract actual design data — variables, styles, and metadata from selected frames. It also provides screenshots so the agent can understand the visual semantics. Combined, the agent gets both the precise design tokens and the visual context.
The results are significantly better.
But here's the critical part — and this is where most setups fail:
The designer must follow atomic design principles
Your designer needs to:
1. Create design tokens (atoms) — colors, fonts, spacings as variables
2. Build components (molecules) from these tokens
3. Compose screens from these components
Think of it as a proper design system hierarchy.
My workflow
As a Flutter developer, I use the AI agent with Figma MCP for the entire process:
1. Tokens → AppTheme
The agent generates color tokens (like primary500, error300`), typography (`heading1, body2`), and spacing (`spacing8, `spacing16`) with matching names from Figma.
2. Components → Reusable widgets
The agent creates Flutter widgets using these tokens.
3. Screens → Complete layouts
I feed the agent context: “tokens are in AppTheme class, components are in `lib/src/core/uikit`” or use a custom skill, and it generates screens using the existing code structure.
The key is naming consistency. When Figma tokens and Flutter code use identical names, the agent can reference them correctly.
Is it pixel-perfect?
No. I still need to review the generated code and make adjustments.
There's a way to make it more reliable using Flutter golden tests — the agent generates a component, compares it to the Figma screenshot, and if pixels don't match, it fixes the code and compares again. But this feels like overengineering for now. The feedback cycle can take too long for simple components.
Manual review is faster.
Garbage in, garbage out
I'm fortunate that my girlfriend creates proper design systems with clean component structure and consistent tokens. This saves me hours of manual implementation.
But I've worked with many designers who focus only on visual appeal without considering implementation. Their Figma files have random spacing values, inconsistent colors, and “components” that aren't actually reusable.
These designs look good but don't generate good code.
Implementing mobile layouts is boring work. You're essentially a human compiler — copying padding values, font sizes, and color codes from Figma to your IDE. No creativity, no challenge, just routine.
I tried using Cursor with design screenshots. It would generate something similar, but never accurate enough:
- Inconsistent spacing values
- Wrong font sizes and weights
- Slightly off colors (`#2A2A2A` instead of `#1F1F1F`)
- Design icons replaced with similar ones from MaterialIcons
Then I discovered Figma MCP and everything changed.
Yes, it costs €12/month, but it's worth every cent.
Figma MCP is a bridge between Figma and your coding agent. It provides tools that allow the agent to extract actual design data — variables, styles, and metadata from selected frames. It also provides screenshots so the agent can understand the visual semantics. Combined, the agent gets both the precise design tokens and the visual context.
The results are significantly better.
But here's the critical part — and this is where most setups fail:
The designer must follow atomic design principles
Your designer needs to:
1. Create design tokens (atoms) — colors, fonts, spacings as variables
2. Build components (molecules) from these tokens
3. Compose screens from these components
Think of it as a proper design system hierarchy.
My workflow
As a Flutter developer, I use the AI agent with Figma MCP for the entire process:
1. Tokens → AppTheme
The agent generates color tokens (like primary500, error300`), typography (`heading1, body2`), and spacing (`spacing8, `spacing16`) with matching names from Figma.
2. Components → Reusable widgets
The agent creates Flutter widgets using these tokens.
3. Screens → Complete layouts
I feed the agent context: “tokens are in AppTheme class, components are in `lib/src/core/uikit`” or use a custom skill, and it generates screens using the existing code structure.
The key is naming consistency. When Figma tokens and Flutter code use identical names, the agent can reference them correctly.
Is it pixel-perfect?
No. I still need to review the generated code and make adjustments.
There's a way to make it more reliable using Flutter golden tests — the agent generates a component, compares it to the Figma screenshot, and if pixels don't match, it fixes the code and compares again. But this feels like overengineering for now. The feedback cycle can take too long for simple components.
Manual review is faster.
Garbage in, garbage out
I'm fortunate that my girlfriend creates proper design systems with clean component structure and consistent tokens. This saves me hours of manual implementation.
But I've worked with many designers who focus only on visual appeal without considering implementation. Their Figma files have random spacing values, inconsistent colors, and “components” that aren't actually reusable.
These designs look good but don't generate good code.
👍4🔥2
The question I ask at every interview
Once, at one of my first interviews for a mobile dev position, I was asked: what does "good code" mean to you? Since then, I often ask candidates the same question at the end of interviews. Not to evaluate — more out of curiosity.
The answer is almost always the same: readable, extensible, testable. SOLID, DRY, clean architecture. Juniors, mids, seniors — almost everyone says the same thing.
I used to think the same way. I'd agonize over layer structure, debate patterns, refactor before the feature even worked. It felt like the "right" way to code.
Now, with more experience, architecture just happens. You set up a foundation, work within it, adjust as you go. You don't overthink — you just know what fits. And once that's no longer something you struggle with, the real question surfaces: how fast can I deliver this feature? Not "is this abstraction elegant enough" but "is this in prod and solving the user's problem."
AI is reinforcing this mindset. An LLM can understand your codebase and write new code within its patterns. The architecture doesn't suffer — but the delivery speed multiplies.
That said — in real production work, AI doesn't magically make everything 10x faster. The bottleneck was never really the code itself. It's communication: unclear requirements, waiting for designs, going back and forth with the client. AI eliminates the slowest part of coding, but it exposes what was always the real problem — everything around the code. Which only reinforces my point: obsessing over code perfection was always misplaced energy. But that's a topic for another post.
So if someone asked me that same interview question today, I'd answer:good code is code that solved the problem, reached the user, and did it on time . Cleanliness is a means, not an end.
Once, at one of my first interviews for a mobile dev position, I was asked: what does "good code" mean to you? Since then, I often ask candidates the same question at the end of interviews. Not to evaluate — more out of curiosity.
The answer is almost always the same: readable, extensible, testable. SOLID, DRY, clean architecture. Juniors, mids, seniors — almost everyone says the same thing.
I used to think the same way. I'd agonize over layer structure, debate patterns, refactor before the feature even worked. It felt like the "right" way to code.
Now, with more experience, architecture just happens. You set up a foundation, work within it, adjust as you go. You don't overthink — you just know what fits. And once that's no longer something you struggle with, the real question surfaces: how fast can I deliver this feature? Not "is this abstraction elegant enough" but "is this in prod and solving the user's problem."
AI is reinforcing this mindset. An LLM can understand your codebase and write new code within its patterns. The architecture doesn't suffer — but the delivery speed multiplies.
That said — in real production work, AI doesn't magically make everything 10x faster. The bottleneck was never really the code itself. It's communication: unclear requirements, waiting for designs, going back and forth with the client. AI eliminates the slowest part of coding, but it exposes what was always the real problem — everything around the code. Which only reinforces my point: obsessing over code perfection was always misplaced energy. But that's a topic for another post.
So if someone asked me that same interview question today, I'd answer:
👍3❤2🔥2
A while back I started diving into system design.
I got curious about how large-scale modern systems work, how and why their architecture is shaped the way it is. Decided to step outside the mobile dev bubble (wrote about that in my previous post).
I love learning and consume a ton of educational content now: books, conference talks, articles, all mixed together. But what really clicks for me is smart people who explain complex things simply.
So here are 3 lectures I want to recommend: Oleg Bunin's talks from HighLoad++ 2017 (1, 2, 3) as a solid foundation for system design. He walks through different approaches to scaling high-load systems one by one, then gradually moves into practice. Sure, some things are dated by now, but the fundamentals hold up.
I know that at least some of my friends who are really cool engineers are reading this. If you know similar resources that explain system design in a clear way, please share, I'd really appreciate it 🙏
Fun fact: back then (in 2017) VK had only about 20 developers 🫡
I got curious about how large-scale modern systems work, how and why their architecture is shaped the way it is. Decided to step outside the mobile dev bubble (wrote about that in my previous post).
I love learning and consume a ton of educational content now: books, conference talks, articles, all mixed together. But what really clicks for me is smart people who explain complex things simply.
So here are 3 lectures I want to recommend: Oleg Bunin's talks from HighLoad++ 2017 (1, 2, 3) as a solid foundation for system design. He walks through different approaches to scaling high-load systems one by one, then gradually moves into practice. Sure, some things are dated by now, but the fundamentals hold up.
I know that at least some of my friends who are really cool engineers are reading this. If you know similar resources that explain system design in a clear way, please share, I'd really appreciate it 🙏
Fun fact: back then (in 2017) VK had only about 20 developers 🫡
YouTube
Разработка и проектирование высоконагруженных систем (часть 1) / Олег Бунин (Онтико)
Крупнейшая профессиональная конференция для разработчиков высоконагруженных систем Saint HighLoad++ 2026
Подробнее: https://clck.ru/3QZHTb
Июнь, 2026.
Санкт-Петербург, DESIGN DISTRICT DAA in SPB
--------
Учебный день
Часть 2: https://youtu.be/sCm4qUw28y4…
Подробнее: https://clck.ru/3QZHTb
Июнь, 2026.
Санкт-Петербург, DESIGN DISTRICT DAA in SPB
--------
Учебный день
Часть 2: https://youtu.be/sCm4qUw28y4…
❤1🔥1