Some thoughts on this channel
Hello, my friends. It's been about a month since I've started this channel. And there are already 10 posts in here. These posts mostly are about good habits + efficiency. I appreciate all of you who were reading them. Hope it was valuable.
Also wanted to add that I fell in love with writing. Although, it's super hard for me. I still spend plenty of time writing one post. Partly cause it's hard to put my thoughts on paper, partly due to the fact that English is not my native language. No pain, no gain)
I think it's time to introduce new topics/rubrics. Maybe, make this channel a bit more technical, a bit more about Flutter and mobile development in general. Since there will be more topics, I want to add more structure by using hashtags. #efficiency, #habits, #career, #learninpublic, #books, #dev, #flutter, #thoughts and more.
I've recently written about learning in public and its benefits. Yesterday, I set a goal (actually, goals) for myself until the end of the year. It's connected to Flutter and animations. From now on I'll post my progress here under the hashtag #learninpublic. Wish me luck!
Hello, my friends. It's been about a month since I've started this channel. And there are already 10 posts in here. These posts mostly are about good habits + efficiency. I appreciate all of you who were reading them. Hope it was valuable.
Also wanted to add that I fell in love with writing. Although, it's super hard for me. I still spend plenty of time writing one post. Partly cause it's hard to put my thoughts on paper, partly due to the fact that English is not my native language. No pain, no gain)
I think it's time to introduce new topics/rubrics. Maybe, make this channel a bit more technical, a bit more about Flutter and mobile development in general. Since there will be more topics, I want to add more structure by using hashtags. #efficiency, #habits, #career, #learninpublic, #books, #dev, #flutter, #thoughts and more.
I've recently written about learning in public and its benefits. Yesterday, I set a goal (actually, goals) for myself until the end of the year. It's connected to Flutter and animations. From now on I'll post my progress here under the hashtag #learninpublic. Wish me luck!
👍1
6 invaluable things I would tell myself when I was new to coding
1. Don't be a perfectionist
I've always considered myself a bit of a perfectionist and thought it's cool. No matter what, I've tried to do something in the best possible way, cover all possible and impossible use cases. Sometimes it led to horrible procrastination. In one case, it was a fear that I couldn't do it perfectly that made me put off the task. But most of the time, I was polishing everything up again and again just until the deadline instead of iterating several times and fixing not-so-obvious bugs before the deadline. I'm still trying to find a "perfect" balance.
2.Don't be afraid to go deeper into tools you are using
Just don't use everything as a black box. For example, if you use Flutter for building mobile apps, you won't be able to create a robust app without knowing some framework's internals. You can easily block the UI thread by doing complex calculations, so the user will think that the app is broken. If you knew that you should have used another isolate (because all your code by default runs in UI thread) for this kind of task, you'd be better off.
3. Learn how to debug, please
Yes, yes. Debugging is not inserting print statements in any situation. It's logging. Learn how to use breakpoints, so you can inspect the entire program state, not just the values you thought to print out in advance. This can massively speed up the bug-fixing process.
4. Bugs are inevitable
"If debugging is the process of removing bugs, then programming must be the process of putting them in" - Edsger Dijkstra. We are human beings. We make mistakes. Sure, there are all sorts of techniques to decrease the number of defects in software, but none of them can prove the absence of bugs.
5. Write code every day
Every day is just another opportunity to learn something new. Consistent practice makes perfect. This guy has managed to do it, so you also can.
6. Use code generation whenever possible
I'll never write another toJson/fromJson method. There is just no reason to write more code when you can write a short description of what you need, and a generator will be willing to make it happen.
#career #dev
1. Don't be a perfectionist
I've always considered myself a bit of a perfectionist and thought it's cool. No matter what, I've tried to do something in the best possible way, cover all possible and impossible use cases. Sometimes it led to horrible procrastination. In one case, it was a fear that I couldn't do it perfectly that made me put off the task. But most of the time, I was polishing everything up again and again just until the deadline instead of iterating several times and fixing not-so-obvious bugs before the deadline. I'm still trying to find a "perfect" balance.
2.Don't be afraid to go deeper into tools you are using
Just don't use everything as a black box. For example, if you use Flutter for building mobile apps, you won't be able to create a robust app without knowing some framework's internals. You can easily block the UI thread by doing complex calculations, so the user will think that the app is broken. If you knew that you should have used another isolate (because all your code by default runs in UI thread) for this kind of task, you'd be better off.
3. Learn how to debug, please
Yes, yes. Debugging is not inserting print statements in any situation. It's logging. Learn how to use breakpoints, so you can inspect the entire program state, not just the values you thought to print out in advance. This can massively speed up the bug-fixing process.
4. Bugs are inevitable
"If debugging is the process of removing bugs, then programming must be the process of putting them in" - Edsger Dijkstra. We are human beings. We make mistakes. Sure, there are all sorts of techniques to decrease the number of defects in software, but none of them can prove the absence of bugs.
5. Write code every day
Every day is just another opportunity to learn something new. Consistent practice makes perfect. This guy has managed to do it, so you also can.
6. Use code generation whenever possible
I'll never write another toJson/fromJson method. There is just no reason to write more code when you can write a short description of what you need, and a generator will be willing to make it happen.
#career #dev
Server-Driven UI (SDUI)
In a traditional world, data is driven by the backend, and the UI is driven by each сlient (web, iOS, and Android).
Let's take products listing. You get a JSON with data like: [{"title": "iPhone", "price": 999}, {"title": "MacBook", "price": 1999}, .....]. The client parses this JSON into List<Product> and shows products to a user with predefined UI logic which is hardcoded on the client.
This comes with a few issues.
The most obvious one for me is the versioning problem, which applies only to native apps. If we do things this way, each time we want to add a new feature to our listing page, we need to release a new version of the app for each platform. Most probably, you'll have users that always protract with updates.
This leads to another problem - A/B testing is harder. It's more difficult to validate ideas and extract data from users’ interactions, which could be used to conclude important things about the product.
Many big fast-growing companies like Airbnb, Ozon, Avito have faced these problems and created tools to overcome them.
Let's take Avito - the service where you can sell and buy literally anything. If a user wants to place an ad to sell a flat, the app will show input fields like address, floor, number of rooms, square meters, etc. If a user is selling a car, he sees fields like model, year, mileage.
Okay, you've, as a good developer, foreseen every possible type of product and written a huge amount of complex logic on the client to show required fields based on the selected product type. But the world is constantly changing, and now your users want to sell NFT tokens here and now. What will you do?
The first solution is to add another piece of logic on the client-side and release a brand-new version. I've already mentioned the problems of this approach.
The next one that comes to my mind is to show a WebView. The thing is nobody likes them. They don't offer native UX and often have performance issues.
And the last one is to add a new type of product with some rules for input fields on your backend (from the admin panel, for example) and send it to the client so the client can render the necessary fields. This strategy is called Server(Backend)-Driven UI.
Of course, it's not perfect either.
It's hard to build from scratch and maintain, which makes it expensive. And maybe one day, you'll like to add some fancy type of field or section, so you'll end up releasing a new version.
#dev
In a traditional world, data is driven by the backend, and the UI is driven by each сlient (web, iOS, and Android).
Let's take products listing. You get a JSON with data like: [{"title": "iPhone", "price": 999}, {"title": "MacBook", "price": 1999}, .....]. The client parses this JSON into List<Product> and shows products to a user with predefined UI logic which is hardcoded on the client.
This comes with a few issues.
The most obvious one for me is the versioning problem, which applies only to native apps. If we do things this way, each time we want to add a new feature to our listing page, we need to release a new version of the app for each platform. Most probably, you'll have users that always protract with updates.
This leads to another problem - A/B testing is harder. It's more difficult to validate ideas and extract data from users’ interactions, which could be used to conclude important things about the product.
Many big fast-growing companies like Airbnb, Ozon, Avito have faced these problems and created tools to overcome them.
Let's take Avito - the service where you can sell and buy literally anything. If a user wants to place an ad to sell a flat, the app will show input fields like address, floor, number of rooms, square meters, etc. If a user is selling a car, he sees fields like model, year, mileage.
Okay, you've, as a good developer, foreseen every possible type of product and written a huge amount of complex logic on the client to show required fields based on the selected product type. But the world is constantly changing, and now your users want to sell NFT tokens here and now. What will you do?
The first solution is to add another piece of logic on the client-side and release a brand-new version. I've already mentioned the problems of this approach.
The next one that comes to my mind is to show a WebView. The thing is nobody likes them. They don't offer native UX and often have performance issues.
And the last one is to add a new type of product with some rules for input fields on your backend (from the admin panel, for example) and send it to the client so the client can render the necessary fields. This strategy is called Server(Backend)-Driven UI.
Of course, it's not perfect either.
It's hard to build from scratch and maintain, which makes it expensive. And maybe one day, you'll like to add some fancy type of field or section, so you'll end up releasing a new version.
#dev
Cloud computing or all kinds of *aaS
Initially, I wanted to write a post about Serverless. I've started researching and found out that my understanding of Serverless is not clear, at least in terms. The biggest discovery for me was that Serverless and Cloud are not interchangeable words. Therefore I've decided to make a quick overview of existing approaches before diving into one of them.
We will start with the Big Three of cloud service models: IaaS, PaaS, SaaS, i.e., Infrastructure as a Service, Platform as a service, and Software as a service. Big companies like Amazon, Microsoft, Google cover all of them. Google Cloud is IaaS, Google App Engine is PaaS, Google Drive and other services for end-users are SaaS.
IaaS provides users with hardware — servers, storage, network as an on-demand service. It gives a lot of flexibility, but at the same time, it requires users to install and configure needed software on their own.
PaaS offers an infrastructure, OS, middleware, database management + some additional software to develop and deploy applications. Probably, you've used Heroku to host your website for free. It's one of the first platforms of this kind. Another good example is Google App Engine. It is a product that provides Web app developers and enterprises with access to Google's scalable hosting and Internet service. The App Engine has limited language support. You're allowed to store data only in Google Cloud Storage services and use the Google query language. We are losing flexibility...huh?
SaaS is a way of delivering applications over the Internet—as a service. Instead of installing and maintaining software, you simply access it via the Internet, freeing yourself from complex software and hardware management. Google Drive, DropBox, Zoom, all kinds of CRM/ERP solutions, you name it.
Before the Serverless the most effective way to build SaaS applications was to develop microservices, deploy them on a Platform as a Service and let the PaaS manage a lot of things. Serverless is just another degree of automation that lies between PaaS and SaaS. It usually includes two concepts: Backend as a Service (BaaS) and Functions as a Service (FaaS).
BaaS makes your app a "rich client." You are not building REST-APIs anymore. Now your client application talks to the database directly with an authentication layer in front of the database. Google has a Firebase platform, and Amazon has Amplify with Cognito for authentication purposes.
With FaaS you're still able to build REST API, but, unlike traditional architectures, server-side logic consists of independent functions that run in stateless containers that are event-triggered, ephemeral (may only last for one invocation), and fully managed by a third party. AWS Lambda is one of the most popular implementations of a Functions-as-a-Service platform.
You can use just one of them or both at the same time. For example, you're building a chat app with Firebase (BaaS), and you want to send a push notification to users that receive the message. You add this message to your database on the client, and this event triggers a cloud function (FaaS) responsible for sending push notifications to specified users.
There are two big benefits when using one of these as-a-service models:
- Faster time to market. You don't need to reinvent the wheel and manage it.
- Resources sharing lowers costs. In some cases, you may even have free monthly/weekly quotas.
The main drawbacks are:
- Vendor Dependency. You're playing by their rules now.
- It may be hard to integrate with existing infrastructure.
- You may face security issues.
If something is not clear, look at the pictures below.
#learninpublic #dev
Initially, I wanted to write a post about Serverless. I've started researching and found out that my understanding of Serverless is not clear, at least in terms. The biggest discovery for me was that Serverless and Cloud are not interchangeable words. Therefore I've decided to make a quick overview of existing approaches before diving into one of them.
We will start with the Big Three of cloud service models: IaaS, PaaS, SaaS, i.e., Infrastructure as a Service, Platform as a service, and Software as a service. Big companies like Amazon, Microsoft, Google cover all of them. Google Cloud is IaaS, Google App Engine is PaaS, Google Drive and other services for end-users are SaaS.
IaaS provides users with hardware — servers, storage, network as an on-demand service. It gives a lot of flexibility, but at the same time, it requires users to install and configure needed software on their own.
PaaS offers an infrastructure, OS, middleware, database management + some additional software to develop and deploy applications. Probably, you've used Heroku to host your website for free. It's one of the first platforms of this kind. Another good example is Google App Engine. It is a product that provides Web app developers and enterprises with access to Google's scalable hosting and Internet service. The App Engine has limited language support. You're allowed to store data only in Google Cloud Storage services and use the Google query language. We are losing flexibility...huh?
SaaS is a way of delivering applications over the Internet—as a service. Instead of installing and maintaining software, you simply access it via the Internet, freeing yourself from complex software and hardware management. Google Drive, DropBox, Zoom, all kinds of CRM/ERP solutions, you name it.
Before the Serverless the most effective way to build SaaS applications was to develop microservices, deploy them on a Platform as a Service and let the PaaS manage a lot of things. Serverless is just another degree of automation that lies between PaaS and SaaS. It usually includes two concepts: Backend as a Service (BaaS) and Functions as a Service (FaaS).
BaaS makes your app a "rich client." You are not building REST-APIs anymore. Now your client application talks to the database directly with an authentication layer in front of the database. Google has a Firebase platform, and Amazon has Amplify with Cognito for authentication purposes.
With FaaS you're still able to build REST API, but, unlike traditional architectures, server-side logic consists of independent functions that run in stateless containers that are event-triggered, ephemeral (may only last for one invocation), and fully managed by a third party. AWS Lambda is one of the most popular implementations of a Functions-as-a-Service platform.
You can use just one of them or both at the same time. For example, you're building a chat app with Firebase (BaaS), and you want to send a push notification to users that receive the message. You add this message to your database on the client, and this event triggers a cloud function (FaaS) responsible for sending push notifications to specified users.
There are two big benefits when using one of these as-a-service models:
- Faster time to market. You don't need to reinvent the wheel and manage it.
- Resources sharing lowers costs. In some cases, you may even have free monthly/weekly quotas.
The main drawbacks are:
- Vendor Dependency. You're playing by their rules now.
- It may be hard to integrate with existing infrastructure.
- You may face security issues.
If something is not clear, look at the pictures below.
#learninpublic #dev
Read the source
What is the best way to become a better writer? Reading more. The same concept can be applied to programming.
I've been reading a lot of source code recently. Of course, not for fun. I had a troublesome task I'd never done before. Therefore I didn't know where to start.
So I've git-cloned an open-source library that solved a similar problem, and decided to adapt it to my needs. Little did I know what awaited me. I wanted to take the path of least resistance but found myself reading and understanding the code written by a stranger. Luckily, the package was small and relatively simple. However, I've managed to learn a lot of new things and changed my view on this topic.
Here is how reading sources may benefit you as a developer:
- It may help you to learn from gurus. Let's imagine you know a skilled programmer, but he is not as public as he could be. There is no conference with him on youtube you could watch or blog you could read. However, he contributes to open-source. The only way to learn from him is to read his code and try to understand something.
- Sometimes it's easier and faster to read the sources than look through docs or watch a tutorial on Youtube. Moreover, library creators often leave many comments in their code.
- You'll learn how popular libraries work under the hood and will be able to choose the most appropriate one. I often see heated debates about state management libraries/approaches in Flutter. How one is 1000 times faster and more convenient than another. Hello, GetX versus anything else. Everything in Dart/Flutter world is open-source. So try to understand how does it work.
- You develop a crucial skill - reading code. It's not a secret that an average developer spends more time reading code than writing. So, read more code to read code more efficiently.
- You may start contributing to open-source. Many companies appreciate it when hiring a developer. Maybe you'll add a new feature that many people need or fix an annoying bug when the maintainer has no time for it.
CAUTION! You can also face suboptimal code when sneaking through GitHub repositories. How to distinguish the good from the bad? I think you should know the basic "code smells" and have a bit of experience to trust your guts.
#career #dev #efficiency #thoughts
What is the best way to become a better writer? Reading more. The same concept can be applied to programming.
I've been reading a lot of source code recently. Of course, not for fun. I had a troublesome task I'd never done before. Therefore I didn't know where to start.
So I've git-cloned an open-source library that solved a similar problem, and decided to adapt it to my needs. Little did I know what awaited me. I wanted to take the path of least resistance but found myself reading and understanding the code written by a stranger. Luckily, the package was small and relatively simple. However, I've managed to learn a lot of new things and changed my view on this topic.
Here is how reading sources may benefit you as a developer:
- It may help you to learn from gurus. Let's imagine you know a skilled programmer, but he is not as public as he could be. There is no conference with him on youtube you could watch or blog you could read. However, he contributes to open-source. The only way to learn from him is to read his code and try to understand something.
- Sometimes it's easier and faster to read the sources than look through docs or watch a tutorial on Youtube. Moreover, library creators often leave many comments in their code.
- You'll learn how popular libraries work under the hood and will be able to choose the most appropriate one. I often see heated debates about state management libraries/approaches in Flutter. How one is 1000 times faster and more convenient than another. Hello, GetX versus anything else. Everything in Dart/Flutter world is open-source. So try to understand how does it work.
- You develop a crucial skill - reading code. It's not a secret that an average developer spends more time reading code than writing. So, read more code to read code more efficiently.
- You may start contributing to open-source. Many companies appreciate it when hiring a developer. Maybe you'll add a new feature that many people need or fix an annoying bug when the maintainer has no time for it.
CAUTION! You can also face suboptimal code when sneaking through GitHub repositories. How to distinguish the good from the bad? I think you should know the basic "code smells" and have a bit of experience to trust your guts.
#career #dev #efficiency #thoughts
How to pass a test task
Hi there. I've been checking a lot of pre-employment test tasks recently as a part of my job and noticed that all junior developers fall into similar traps. And here is a little post on what you should pay attention to, so the reviewer will approve your code, and you'll get more chances to land the job.
Usually, test tasks for mobile developers look like a simple app that an average junior developer can create in one weekend/week. Some companies may place greater emphasis on the UI part, some - on client-server communication or something more specific to their current project. The checklist below is a must-have in any of these cases.
Two main things I'm looking for in a test task while reviewing are the usage of the stack we use in our company and code cleanliness + overall tidiness.
Why? I want to be sure that my potential colleague will start delivering new features ASAP, and his/her code will be maintainable.
Here is a full checklist:
1. Reuse your code. Try to follow DRY and SOLID principles.
2. Don't overthink architecture: divide your code into well-defined layers. If you have no idea how to do it, ask somebody more experienced from the community.
3. Use the company's tech stack. I often see companies mention some libraries and approaches in their job requirements section. Show that you know them.
4. No commented out code, no logs. That's it.
5. Use linters. It may help you to follow the style guides of the language and/or framework. It annoys me when I see files like SomeUsefulClass.dart instead of some_useful_class.dart, or functions returning dynamics instead of defined types.
6. Don't forget about basic Dependency Injection
7. Think about basic UI/UX principles: no fancy fonts, no tiny/gigantic font sizes, no colors that contradict each other. If you are not a designer and Figma was not provided, try to make it as minimalistic as possible. When waiting for the response from the server, make the user know that something is going on - show a loading indicator. If something went wrong, show a clear error message. Remember, "An error occurred" is a bad one.
8. Run your code before submitting it. Don't waste the reviewer's time making him git clone, build and run your app only to see that it crushes.
9. Bonus tip: write a clear Readme. Just a basic description of the app is enough. Maybe nobody will notice it, but I always do.
If you have something to add, write it in the comments.
If you're a junior looking for a job, break a leg🍀
#career #dev
Hi there. I've been checking a lot of pre-employment test tasks recently as a part of my job and noticed that all junior developers fall into similar traps. And here is a little post on what you should pay attention to, so the reviewer will approve your code, and you'll get more chances to land the job.
Usually, test tasks for mobile developers look like a simple app that an average junior developer can create in one weekend/week. Some companies may place greater emphasis on the UI part, some - on client-server communication or something more specific to their current project. The checklist below is a must-have in any of these cases.
Two main things I'm looking for in a test task while reviewing are the usage of the stack we use in our company and code cleanliness + overall tidiness.
Why? I want to be sure that my potential colleague will start delivering new features ASAP, and his/her code will be maintainable.
Here is a full checklist:
1. Reuse your code. Try to follow DRY and SOLID principles.
2. Don't overthink architecture: divide your code into well-defined layers. If you have no idea how to do it, ask somebody more experienced from the community.
3. Use the company's tech stack. I often see companies mention some libraries and approaches in their job requirements section. Show that you know them.
4. No commented out code, no logs. That's it.
5. Use linters. It may help you to follow the style guides of the language and/or framework. It annoys me when I see files like SomeUsefulClass.dart instead of some_useful_class.dart, or functions returning dynamics instead of defined types.
6. Don't forget about basic Dependency Injection
7. Think about basic UI/UX principles: no fancy fonts, no tiny/gigantic font sizes, no colors that contradict each other. If you are not a designer and Figma was not provided, try to make it as minimalistic as possible. When waiting for the response from the server, make the user know that something is going on - show a loading indicator. If something went wrong, show a clear error message. Remember, "An error occurred" is a bad one.
8. Run your code before submitting it. Don't waste the reviewer's time making him git clone, build and run your app only to see that it crushes.
9. Bonus tip: write a clear Readme. Just a basic description of the app is enough. Maybe nobody will notice it, but I always do.
If you have something to add, write it in the comments.
If you're a junior looking for a job, break a leg🍀
#career #dev
Mental programming by Kirill Mokevnin (2021). Easy to follow rules to write good code.
1. There is a difference between understanding the code and understanding the problem it solves. Good code should have both.
2. If you are unsure if a variable or method name fits your needs, send it to a chat and ask people what they expect from it.
3. Strings. There are no checks for strings. Therefore, if there is code like
What is a solution? Keep such checks in one place.
There are two possible ways to do it:
1) Method:
2) Enum:
4. Don't save on variables. Oneliners aren't cool if they prevent you from understanding the logic.
A popular example from C language:
5. One vs Many in variable naming.
If I see a variable named
6. Semantics. Make your code meaningful.
Example:
7. Null object pattern
In some cases instead of writing checks like
"We should use the Null Object Pattern when a Client would otherwise check for null just to skip execution or perform a default action. In such cases, we may encapsulate the neutral logic within a null object and return that to the client instead of the null value. This way client's code no longer needs to be aware if a given instance is null or not."
For the example above it could be
where Guest is a null object.
8. Command-Query separation
"It states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer."
Example:
*This example doesn't apply to languages with null safety like Dart and Kotlin
#dev
1. There is a difference between understanding the code and understanding the problem it solves. Good code should have both.
2. If you are unsure if a variable or method name fits your needs, send it to a chat and ask people what they expect from it.
3. Strings. There are no checks for strings. Therefore, if there is code like
if (order.status == 'delivering') {...}, and you decide to rename a status label, you should manually find all the places, where you've written such checks and fix them. What is a solution? Keep such checks in one place.
There are two possible ways to do it:
1) Method:
order.isDelivering()2) Enum:
order.status == OrderStatus.delivering4. Don't save on variables. Oneliners aren't cool if they prevent you from understanding the logic.
A popular example from C language:
while (*dest++ = *src++);5. One vs Many in variable naming.
If I see a variable named
attributes, then I expect it to store some collection, not an individual object.6. Semantics. Make your code meaningful.
Example:
if (!items.children) {...}
Do you have any clue of what did we just checked? Me neither.7. Null object pattern
In some cases instead of writing checks like
if (user != null && user.isAdmin()) {
user.doSomething();
}*,
you can use Null Object Pattern. "We should use the Null Object Pattern when a Client would otherwise check for null just to skip execution or perform a default action. In such cases, we may encapsulate the neutral logic within a null object and return that to the client instead of the null value. This way client's code no longer needs to be aware if a given instance is null or not."
For the example above it could be
final user = cond ? AdminUser() : Guest(), where Guest is a null object.
8. Command-Query separation
"It states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer."
Example:
user.isValid() - predicate that returns boolean. We don't expect it to change anything. If it somehow modifies our state under the hood, it'll be almost impossible to find the bug when we face some weird behavior.*This example doesn't apply to languages with null safety like Dart and Kotlin
#dev
YouTube
Мокевнин Кирилл, Хекслет - Ментальное программирование 3
Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.
Caching strategies
Why do we need caching? It's simple. People don't like loaders*. Moreover, people don't like waiting. So, caching some data to instantly show it next time a user asks for it without requesting the server increases app's UX. Which increases user retention. Which increases app's profit.
I have once stumbled upon a problem related to caching and cache invalidation in a mobile app. My main problem was that I'd never done it before and tried to reinvent the wheel. Luckily, my caching strategy was not so tricky. The cache had an expiration date, so I could invalidate it after a day/week/month, and the app could force an update from the server if needed by the "pull to refresh" thing.
After a while, I've found a talk from a mobile conference about different caching strategies. I'll shortly describe all of them, so you don't need to waste 30 minutes of your precious time watching the video. If you're interested in the theme or feel that something is still unclear after reading the post, then go to YouTube and watch the video (it is not boring at all, I promise).
Thanks to the guy who has even drawn block schemes for every strategy. I'll attach them in the comments.
Okay, let's start.
1. Lazy cache
The most basic one. If user request's some data, we try to find it in cache. If it is there, give it to user. If not - make a request to the server and update the cache with data from successfull response.
Pros:
- easy to implement
- instant data delivery
- cached data is independent of internet connection
Cons:
- no cache invalidation
When to use it:
- apps with immutable data that you should upload once a while like book readers, offline apps, etc.
2. Synchronized cache
The same thing as a previous one, but there are two new steps for invalidation. Local (by expiration date for ex.) and server (by status code 304 NOT MODIFIED for ex.) invalidation. If cache is valid we return data to the user.
Pros:
- faster delivery time for up to date data
- invalidation
Cons:
- dependent of connection
When to use:
- apps with not idempotent data*** where user can't add or edit this data. For example: news and booking apps
3. Write-through cache
The most difficult one to implement. However, the reading process is the same as in synchronized cache. But when we apply some changes, we need to synchronize them with our server database.
Pros:
- faster delivery time for up to date data
- invalidation
- full synchronization with server
Cons:
- dependent of connection
- after failed write we should go back to the initial state
- complex implementation
When to use:
- messenger is a best example
4. LRU cache
It speaks for itself. Least recently used cache is removed when we are out of cache memory, so we can put new piece of data in the cache. However, the invalidation now is in write process. MRU and other algorithms can be used.
Pros:
- instant data delivery
- cached data is independent of internet connection
- customizable invalidation mechanism
- not inflating the size of cache data
Cons:
- complex implementation
- you should be careful with invalidation. For example, you may remove some cached data, that user will need in a second.
When to use:
- apps with heavy content like instagram
* those annoying spinning things, which indicate that we are waiting for data from the server
** if there is no connection, we can't properly invalidate our cache
*** the data may update if you refresh the page
#dev
Why do we need caching? It's simple. People don't like loaders*. Moreover, people don't like waiting. So, caching some data to instantly show it next time a user asks for it without requesting the server increases app's UX. Which increases user retention. Which increases app's profit.
I have once stumbled upon a problem related to caching and cache invalidation in a mobile app. My main problem was that I'd never done it before and tried to reinvent the wheel. Luckily, my caching strategy was not so tricky. The cache had an expiration date, so I could invalidate it after a day/week/month, and the app could force an update from the server if needed by the "pull to refresh" thing.
After a while, I've found a talk from a mobile conference about different caching strategies. I'll shortly describe all of them, so you don't need to waste 30 minutes of your precious time watching the video. If you're interested in the theme or feel that something is still unclear after reading the post, then go to YouTube and watch the video (it is not boring at all, I promise).
Thanks to the guy who has even drawn block schemes for every strategy. I'll attach them in the comments.
Okay, let's start.
1. Lazy cache
The most basic one. If user request's some data, we try to find it in cache. If it is there, give it to user. If not - make a request to the server and update the cache with data from successfull response.
Pros:
- easy to implement
- instant data delivery
- cached data is independent of internet connection
Cons:
- no cache invalidation
When to use it:
- apps with immutable data that you should upload once a while like book readers, offline apps, etc.
2. Synchronized cache
The same thing as a previous one, but there are two new steps for invalidation. Local (by expiration date for ex.) and server (by status code 304 NOT MODIFIED for ex.) invalidation. If cache is valid we return data to the user.
Pros:
- faster delivery time for up to date data
- invalidation
Cons:
- dependent of connection
When to use:
- apps with not idempotent data*** where user can't add or edit this data. For example: news and booking apps
3. Write-through cache
The most difficult one to implement. However, the reading process is the same as in synchronized cache. But when we apply some changes, we need to synchronize them with our server database.
Pros:
- faster delivery time for up to date data
- invalidation
- full synchronization with server
Cons:
- dependent of connection
- after failed write we should go back to the initial state
- complex implementation
When to use:
- messenger is a best example
4. LRU cache
It speaks for itself. Least recently used cache is removed when we are out of cache memory, so we can put new piece of data in the cache. However, the invalidation now is in write process. MRU and other algorithms can be used.
Pros:
- instant data delivery
- cached data is independent of internet connection
- customizable invalidation mechanism
- not inflating the size of cache data
Cons:
- complex implementation
- you should be careful with invalidation. For example, you may remove some cached data, that user will need in a second.
When to use:
- apps with heavy content like instagram
* those annoying spinning things, which indicate that we are waiting for data from the server
** if there is no connection, we can't properly invalidate our cache
*** the data may update if you refresh the page
#dev
YouTube
Дмитрий Васильев — Как кэшировать информацию в Android-приложении и не стрелять себе в ногу
Подробнее о конференции Mobius: https://jrg.su/ojGU3B
— —
. . .
. Дмитрий расскажет, чем руководствоваться при выборе предпочтительной стратегии кэширования для вашего проекта, и поделится опытом своей команды в реализации по-настоящему быстрого и гибкого…
— —
. . .
. Дмитрий расскажет, чем руководствоваться при выборе предпочтительной стратегии кэширования для вашего проекта, и поделится опытом своей команды в реализации по-настоящему быстрого и гибкого…
The Broken Window Theory or Why Technical Debt is an Evil
Have you ever heard about the broken windows theory?
It states that any visible signs of crime and civil disorder, such as broken windows, vandalism, loitering, public drinking, create an urban environment that promotes even more crime and disorder.
"One broken window, left unrepaired for any substantial length of time, instills in the inhabitants of the building a sense of abandonment—a sense that the powers that be don’t care about the building. So another window gets broken. People start littering. Graffiti appears. Serious structural damage begins. In a relatively short period, the building becomes damaged beyond the owner’s desire to fix it, and the sense of abandonment becomes reality." - Andrew Hunt & David Thomas in "Pragmatic Programmer"
Therefore, we may conclude that policing these relatively small misbehaviors will decrease or prevent an increase of the crime rate in the area.
I hope you've already noticed where I'm going.
If you leave "broken windows" (bad designs, wrong decisions, or poor code) in your codebase, very soon it'll become a "dangerous place to live in". So, don’t leave them unrepaired. Fix them as soon as they are discovered, otherwise, all of a sudden, you'll need to get a dumpster, or move to another neighborhood.
Easier said than done, yeah?
#dev #thoughts
Have you ever heard about the broken windows theory?
It states that any visible signs of crime and civil disorder, such as broken windows, vandalism, loitering, public drinking, create an urban environment that promotes even more crime and disorder.
"One broken window, left unrepaired for any substantial length of time, instills in the inhabitants of the building a sense of abandonment—a sense that the powers that be don’t care about the building. So another window gets broken. People start littering. Graffiti appears. Serious structural damage begins. In a relatively short period, the building becomes damaged beyond the owner’s desire to fix it, and the sense of abandonment becomes reality." - Andrew Hunt & David Thomas in "Pragmatic Programmer"
Therefore, we may conclude that policing these relatively small misbehaviors will decrease or prevent an increase of the crime rate in the area.
I hope you've already noticed where I'm going.
If you leave "broken windows" (bad designs, wrong decisions, or poor code) in your codebase, very soon it'll become a "dangerous place to live in". So, don’t leave them unrepaired. Fix them as soon as they are discovered, otherwise, all of a sudden, you'll need to get a dumpster, or move to another neighborhood.
Easier said than done, yeah?
#dev #thoughts
👍5
Stop using those annoying spinners
I've been catching myself thinking that loading spinners really piss me off lately. It's okay when I see them while logging in to some service, but it becomes a living hell when I see them everywhere afterward. In some mobile apps, you may encounter them on each and every screen. Moreover, I've seen a web app with 10-15 different sections on one screen with 10-15 spinners. One for each section.
I do understand why people use them. It is the easiest way to show that something is loading. And it's even worse when you don't give your user any feedback. But these spinners have some serious flaws.
In The Psychology of Waiting Lines, David H. Maister describes the psychology of queueing. The concepts from his research can be applied to any situation when people are forced to wait for something.
Here are my three takeaways:
1. Unexplained waits feel longer than explained waits.
2. Unoccupied time feels longer than occupied time.
3. Anxiety makes wait feel longer.
And now you can see why bare loading spinners are garbage:
1. They don't explain to us what we are waiting for.
2. We can only watch at the spinning wheel, which is boring. You can compare it to looking at the clock.
3. We don't know when it'll end.
Here is what you can do to fix it:
- Explain the wait. Put some text like: "We are looking for available tickets so you can forget about your work and chill out on the Miami beach. This might take up to a minute." below the spinner.
- Occupy your user with additional information, a short survey, fan fact, or motivational quote.
- Show progress indicator, which will display the actual progress. You can estimate the speed of the progress bar using historical data if you aren't able to get real-time feedback from the application.
- Remove the spinner if it is a placeholder for other content. You might have noticed how Google, Facebook, Instagram, and other big services handle such situations. Google shows low-quality images while high-quality ones are on their way. Facebook and Instagram often use Skeleton UI*. Facebook has even developed an open-source library Shimmer for Android and iOS that make these skeleton screens even more appealing.
*A skeleton screen is a UI that doesn't contain actual content; instead, it shows the loading elements of a page in a shape similar to the actual content.
#dev #thoughts
I've been catching myself thinking that loading spinners really piss me off lately. It's okay when I see them while logging in to some service, but it becomes a living hell when I see them everywhere afterward. In some mobile apps, you may encounter them on each and every screen. Moreover, I've seen a web app with 10-15 different sections on one screen with 10-15 spinners. One for each section.
I do understand why people use them. It is the easiest way to show that something is loading. And it's even worse when you don't give your user any feedback. But these spinners have some serious flaws.
In The Psychology of Waiting Lines, David H. Maister describes the psychology of queueing. The concepts from his research can be applied to any situation when people are forced to wait for something.
Here are my three takeaways:
1. Unexplained waits feel longer than explained waits.
2. Unoccupied time feels longer than occupied time.
3. Anxiety makes wait feel longer.
And now you can see why bare loading spinners are garbage:
1. They don't explain to us what we are waiting for.
2. We can only watch at the spinning wheel, which is boring. You can compare it to looking at the clock.
3. We don't know when it'll end.
Here is what you can do to fix it:
- Explain the wait. Put some text like: "We are looking for available tickets so you can forget about your work and chill out on the Miami beach. This might take up to a minute." below the spinner.
- Occupy your user with additional information, a short survey, fan fact, or motivational quote.
- Show progress indicator, which will display the actual progress. You can estimate the speed of the progress bar using historical data if you aren't able to get real-time feedback from the application.
- Remove the spinner if it is a placeholder for other content. You might have noticed how Google, Facebook, Instagram, and other big services handle such situations. Google shows low-quality images while high-quality ones are on their way. Facebook and Instagram often use Skeleton UI*. Facebook has even developed an open-source library Shimmer for Android and iOS that make these skeleton screens even more appealing.
*A skeleton screen is a UI that doesn't contain actual content; instead, it shows the loading elements of a page in a shape similar to the actual content.
#dev #thoughts
👍4
Sentry
Today I want to tell you about an amazing tool I didn't know existed when I was starting out as a developer. Luckily, I got acquainted with it as soon as I got into a company with numerous web and mobile apps in production.
Its main purpose is to track errors in your apps. In other words, if the app throws some weird exception in production, you instantly get notified and receive a stack trace*. So, you can see when and why your app crashes and release a patch before all of your users abandon you.
Moreover, there is another feature, that I didn't have a chance to benefit from. It is performance monitoring. Sentry allows you to measure metrics like throughput, latency, failure rate, number of users impacted, and user misery. On top of that, you get a lot of graphs that visualize these metrics, so you're able to keep an eye on changes in performance over time.
What I especially love about Sentry is that there is a well documented library for almost every platform (language/framework/library) which allows you to use it in all of your projects both on frontend and backend. The second thing is that it has a free plan, so you can always try it out if there is no need for third-party integrations or other team members to join.
*In Flutter you can also get info about recent screen transitions
#dev
Today I want to tell you about an amazing tool I didn't know existed when I was starting out as a developer. Luckily, I got acquainted with it as soon as I got into a company with numerous web and mobile apps in production.
Its main purpose is to track errors in your apps. In other words, if the app throws some weird exception in production, you instantly get notified and receive a stack trace*. So, you can see when and why your app crashes and release a patch before all of your users abandon you.
Moreover, there is another feature, that I didn't have a chance to benefit from. It is performance monitoring. Sentry allows you to measure metrics like throughput, latency, failure rate, number of users impacted, and user misery. On top of that, you get a lot of graphs that visualize these metrics, so you're able to keep an eye on changes in performance over time.
What I especially love about Sentry is that there is a well documented library for almost every platform (language/framework/library) which allows you to use it in all of your projects both on frontend and backend. The second thing is that it has a free plan, so you can always try it out if there is no need for third-party integrations or other team members to join.
*In Flutter you can also get info about recent screen transitions
#dev
Sentry
Application Performance Monitoring & Error Tracking Software
Application performance monitoring for developers & software teams to see errors clearer, solve issues faster & continue learning continuously. Get started at sentry.io.
👍4
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
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
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
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