🔧 Understanding Redis Pipelining: Optimizing Data Processing Efficiency 🚀
In the realm of Redis, a powerful in-memory data structure store, Redis Pipelining stands out as a valuable technique for enhancing performance by reducing the round-trip time (RTT) during data operations. Let's delve into the concepts and workings of Redis Pipelining to grasp how it can turbocharge your application's data processing capabilities.
🔍 What is Redis Pipelining?
Redis Pipelining is a technique that allows multiple commands to be batched and sent to the Redis server in a single network round trip. Rather than sending each command individually and waiting for the response before issuing the next one, Redis Pipelining queues up commands and sends them collectively, enabling efficient and high-speed data processing.
⚙️ Request/Response Protocols and Round Trip Time (RTT)
Traditional client-server interactions involve a request-response model where each command incurs an RTT for communication. With Redis Pipelining, multiple commands are bundled together in a pipeline, minimizing the back-and-forth latency typically seen in individual command executions. This reduction in RTT translates to significant performance improvements, especially when dealing with bulk operations or transactional workflows.
⌨️ Commands and Syntax of Redis Pipelining
Redis Pipelining employs a straightforward syntax for queuing commands within a pipeline. By using the
🌟 Pros of Redis Pipelining
1. Reduced Latency: Redis Pipelining reduces the effects of network latencies by batching the requests and therefore allows for faster response times.
2. Throughput: In this way, Redis becomes an even better solution for a variety of application processes by which it enables hundreds or thousands of operations per second.
3. Atomic Transactions: The data is always consistent as all commands within a pipeline are carried out atomically.
⚠️ Cons of Redis Pipelining
1. Complexity: Synchronous Redis interactions may seem trivial as compared to implementing pipelines that are quite complex, especially with error handling.
2. Limited atomicity: While grouped commands are executed atomically, transactions are not supported within pipelines.
3. Memory Consumption: If several commands are queued and not done quickly, pipelining may use up much memory on the side of clients.
🔚 Conclusion
Redis Pipelining emerges as a powerful tool for optimizing data processing and enhancing application performance. By leveraging the batching capability of pipelines, developers can streamline interactions with Redis, reduce latency, and boost overall efficiency. Understanding the nuances of Redis Pipelining empowers developers to architect high-performance systems that excel in speed and responsiveness.
#Redis
#RedisPipelines
In the realm of Redis, a powerful in-memory data structure store, Redis Pipelining stands out as a valuable technique for enhancing performance by reducing the round-trip time (RTT) during data operations. Let's delve into the concepts and workings of Redis Pipelining to grasp how it can turbocharge your application's data processing capabilities.
🔍 What is Redis Pipelining?
Redis Pipelining is a technique that allows multiple commands to be batched and sent to the Redis server in a single network round trip. Rather than sending each command individually and waiting for the response before issuing the next one, Redis Pipelining queues up commands and sends them collectively, enabling efficient and high-speed data processing.
⚙️ Request/Response Protocols and Round Trip Time (RTT)
Traditional client-server interactions involve a request-response model where each command incurs an RTT for communication. With Redis Pipelining, multiple commands are bundled together in a pipeline, minimizing the back-and-forth latency typically seen in individual command executions. This reduction in RTT translates to significant performance improvements, especially when dealing with bulk operations or transactional workflows.
⌨️ Commands and Syntax of Redis Pipelining
Redis Pipelining employs a straightforward syntax for queuing commands within a pipeline. By using the
pipeline() method in Redis python client, developers can append commands to the pipeline and execute them in a single batch operation. The syntax is simple and intuitive, offering a seamless way to streamline data interactions with Redis.🌟 Pros of Redis Pipelining
1. Reduced Latency: Redis Pipelining reduces the effects of network latencies by batching the requests and therefore allows for faster response times.
2. Throughput: In this way, Redis becomes an even better solution for a variety of application processes by which it enables hundreds or thousands of operations per second.
3. Atomic Transactions: The data is always consistent as all commands within a pipeline are carried out atomically.
⚠️ Cons of Redis Pipelining
1. Complexity: Synchronous Redis interactions may seem trivial as compared to implementing pipelines that are quite complex, especially with error handling.
2. Limited atomicity: While grouped commands are executed atomically, transactions are not supported within pipelines.
3. Memory Consumption: If several commands are queued and not done quickly, pipelining may use up much memory on the side of clients.
🔚 Conclusion
Redis Pipelining emerges as a powerful tool for optimizing data processing and enhancing application performance. By leveraging the batching capability of pipelines, developers can streamline interactions with Redis, reduce latency, and boost overall efficiency. Understanding the nuances of Redis Pipelining empowers developers to architect high-performance systems that excel in speed and responsiveness.
#Redis
#RedisPipelines
🌟 Exploring the Power of the Reload Module in Python! 🐍
The
Here's a quick example showcasing the usage of the
Some common use cases of the
1. Interactive Development: Quickly update code in a REPL session without restarting it.
2. Hot Reloading: Dynamically reload web server components without interrupting service.
3. Plugin Systems: Enable users to extend functionality on-the-fly by reloading plugins.
Remember to use
#Python
The
reload module is a hidden gem in Python that allows you to dynamically reload a previously imported module. This can be extremely handy during development and debugging phases where you want to update your code without restarting your entire application. 🛠️Here's a quick example showcasing the usage of the
reload module:import my_moduleBy utilizing the
import importlib
# Let's assume you have made changes to my_module and want to reload it
importlib.reload(my_module)
reload module, you can seamlessly incorporate changes to your modules during runtime, leading to a more fluid and efficient development process. 🔄Some common use cases of the
reload module include:1. Interactive Development: Quickly update code in a REPL session without restarting it.
2. Hot Reloading: Dynamically reload web server components without interrupting service.
3. Plugin Systems: Enable users to extend functionality on-the-fly by reloading plugins.
Remember to use
reload responsibly, as it can lead to unexpected behavior if not applied correctly. Stay curious, experiment, and embrace the power of reload in your Python projects! 💡#Python
👍1
سلام دوستان
برای اولین بار تصمیم گرفتم که به زبان فارسی هم پست فنی بزارم و احتمالن از این به بعد بیشتر اینکار رو انجام میدم و سعی دارم امسال رو روی محتوای فارسی بیشتر کار کنم تا دوستان بیشتری بتونن استفاده کنن و محتوا بیشتر دیده بشه
ممنون میشم اگر شماهم فکر میکنید مطالب مفید هست کانال رو حمایت کنید تا مخاطب بیشتری داشته باشیم و اشتراک دانش رو قوی تر ادامه بدیم
@Pythonic_Dev
برای اولین بار تصمیم گرفتم که به زبان فارسی هم پست فنی بزارم و احتمالن از این به بعد بیشتر اینکار رو انجام میدم و سعی دارم امسال رو روی محتوای فارسی بیشتر کار کنم تا دوستان بیشتری بتونن استفاده کنن و محتوا بیشتر دیده بشه
ممنون میشم اگر شماهم فکر میکنید مطالب مفید هست کانال رو حمایت کنید تا مخاطب بیشتری داشته باشیم و اشتراک دانش رو قوی تر ادامه بدیم
@Pythonic_Dev
👍8❤3👎1
موضوعی که میخوایم امروز باهم برسیش کنیم یه تکنیک داخل کامپیوتر ساینس هست به نام Reference Counting
داستان از این قرار هست که هر موقع شما یک ابجکتی میسازید ابجکت شما یک ادرسی داره داخل مموری و منظور از reference count هم تعداد رفرنس هایی هست که به اون ادرس داخل مموری اشاره میکنند
میدونم توضیحات یک مقدار گیج کننده هست پس با یک نمونه کد مثال میزنم
الان ما داخل این کد یک ابجکت استرینگ ساختیم و بعد ایدی اش رو پرینت گرفتیم که میشه گفت ایدی اش همون ادرسش داخل مموری هست
و الان متغیر value یک اشاره کننده به اون مقدار داخل مموری هست و الان reference count اون دیتا 1 هست و اگر به عنوان مثال ما بیایم و همچین چیزی بگیم
یک رفرنس دیگه نسبت به اون ابجکت داخل مموری ساختیم و reference count اون ابجکت رو کردیم 2
اینجا دقت کنید که ما دیتای 'pythonic_dev' رو ندادیم به value2 صرفا گفتیم که value2 هم به همون چیزی اشاره کنه که value اشاره میکنه یعنی الان اگر id متغیر value2 رو پرینت بگیریم میبینیم که ایدی هاشون برابر هست یعنی هر دو به یک ابجکت داخل مموری اشاره میکنند
حالا مسله دیگه ای که هست اینه که اگر ما بیایم و یک مقدار دیگه برای value تعریف بکنیم
دیگه متغیر value به ابجکت مورد نظر ما اشاره نمیکنه و اتفاقی که میوفته reference count ابجکت ما میشه 1 و تنها رفرنسی که بهش اشاره میکنه value2 هست
حالا سوالی که مطرح میشه اینه که اگر ما بیایم و value2 رو مقدارش رو عوض بکنیم یا اصلا دلیتش بکنیم مثل
چه اتفاقی میوفته خب دقیقن نکته اصلی داستان همین جا است وقتی که رفرنس هایی که به یک ابجکت داخل مموری اشاره میکنند همه از بین برن مموری منیجر پایتون متوجه میشه و اون ابجکت رو کلا از مموری پاک میکنه و اون فضایی که برای اون ابجکت استفاده میشد حالا دوباره قابل استفاده است
در پست های اینده به gc و اینکه کجا reference counting کار نمیکنه هم اشاره میکنم
#ReferenceCounting
@Pythonic_Dev
داستان از این قرار هست که هر موقع شما یک ابجکتی میسازید ابجکت شما یک ادرسی داره داخل مموری و منظور از reference count هم تعداد رفرنس هایی هست که به اون ادرس داخل مموری اشاره میکنند
میدونم توضیحات یک مقدار گیج کننده هست پس با یک نمونه کد مثال میزنم
value = 'pythonic_dev'
print(id(value)) #131241123
الان ما داخل این کد یک ابجکت استرینگ ساختیم و بعد ایدی اش رو پرینت گرفتیم که میشه گفت ایدی اش همون ادرسش داخل مموری هست
و الان متغیر value یک اشاره کننده به اون مقدار داخل مموری هست و الان reference count اون دیتا 1 هست و اگر به عنوان مثال ما بیایم و همچین چیزی بگیم
value2 = value
یک رفرنس دیگه نسبت به اون ابجکت داخل مموری ساختیم و reference count اون ابجکت رو کردیم 2
اینجا دقت کنید که ما دیتای 'pythonic_dev' رو ندادیم به value2 صرفا گفتیم که value2 هم به همون چیزی اشاره کنه که value اشاره میکنه یعنی الان اگر id متغیر value2 رو پرینت بگیریم میبینیم که ایدی هاشون برابر هست یعنی هر دو به یک ابجکت داخل مموری اشاره میکنند
حالا مسله دیگه ای که هست اینه که اگر ما بیایم و یک مقدار دیگه برای value تعریف بکنیم
value = 1
دیگه متغیر value به ابجکت مورد نظر ما اشاره نمیکنه و اتفاقی که میوفته reference count ابجکت ما میشه 1 و تنها رفرنسی که بهش اشاره میکنه value2 هست
حالا سوالی که مطرح میشه اینه که اگر ما بیایم و value2 رو مقدارش رو عوض بکنیم یا اصلا دلیتش بکنیم مثل
del value2
چه اتفاقی میوفته خب دقیقن نکته اصلی داستان همین جا است وقتی که رفرنس هایی که به یک ابجکت داخل مموری اشاره میکنند همه از بین برن مموری منیجر پایتون متوجه میشه و اون ابجکت رو کلا از مموری پاک میکنه و اون فضایی که برای اون ابجکت استفاده میشد حالا دوباره قابل استفاده است
در پست های اینده به gc و اینکه کجا reference counting کار نمیکنه هم اشاره میکنم
#ReferenceCounting
@Pythonic_Dev
👍6❤3
سلام خدمت همه دوستان
چند روز پیش درگیر طراحی بخشی از دیتابیس یک پروژه و نوشتن 2 تا کوعری نسبتا پیچیده بودم که گفتم تجربه جالبی شده و خوبه که به اشتراک بزارمش
اگر توسعه دهنده بک اند هستید و یا کلا به موضوعات مرتبط با پایگاه داده، نرمالایزیشن و بهینهسازی کوئریها علاقهمند هستید و دنبال راهکارهای خلاقانه برای مدلسازی داده هستید، ممنون میشم پست رو بخونید
برای همین داخل یکی از ریپازیتوی های گیت هابم که مخصوص یکسری از پست ها هست یک فایل md نوشتم با نمونه کد django orm و SQL
خیلی خوشحال میشم که نظرتون رو راجب دیزاین و کوعری ها و کلا پستی که نوشتم بدونم فقط خواهشی که دارم اینه که قبل از اینکه نظری یا انتقادی بدید همه پست رو بخونید چون در ابتدا یکسری کار میکنم که شاید در نگاه اول درست نباشه ولی در انتها دلیلش رو بیان میکنم
لینک پست
چند روز پیش درگیر طراحی بخشی از دیتابیس یک پروژه و نوشتن 2 تا کوعری نسبتا پیچیده بودم که گفتم تجربه جالبی شده و خوبه که به اشتراک بزارمش
اگر توسعه دهنده بک اند هستید و یا کلا به موضوعات مرتبط با پایگاه داده، نرمالایزیشن و بهینهسازی کوئریها علاقهمند هستید و دنبال راهکارهای خلاقانه برای مدلسازی داده هستید، ممنون میشم پست رو بخونید
برای همین داخل یکی از ریپازیتوی های گیت هابم که مخصوص یکسری از پست ها هست یک فایل md نوشتم با نمونه کد django orm و SQL
خیلی خوشحال میشم که نظرتون رو راجب دیزاین و کوعری ها و کلا پستی که نوشتم بدونم فقط خواهشی که دارم اینه که قبل از اینکه نظری یا انتقادی بدید همه پست رو بخونید چون در ابتدا یکسری کار میکنم که شاید در نگاه اول درست نباشه ولی در انتها دلیلش رو بیان میکنم
لینک پست
GitHub
Pythonic_Dev-Posts/SQLChallenge-AttributeFilter at main · Cmatrix1/Pythonic_Dev-Posts
Collection of data, photos and text of my Telegram channel posts - Cmatrix1/Pythonic_Dev-Posts
❤4
سلام خدمت همه دوستان
من برگشتم با یکسری پست های جدید
اخیرا شروع به خوندن کتاب Designing Data-Intensive Applications کردم و قصد دارم بعد از مطالعه هر فصل یک خلاصه ای از اون رو در قالب یک پست یا مقاله جا بدم
مقاله اول رو در باب خلاصه فصل اول نوشتم
در ابتدا قصد داشتم به صورت کامل فارسی بنویسم ولی از یه جایی به بعد دیگه حوصله ترجمه اش رو نداشتم و فقط یک توضیح ساده و کلی به فارسی نوشتم و انگلیسی ادامه دادم
مقالات رو به صورت فایل md خواهم نوشت و روی گیت هاب منتشر میکنم و البته لینکش رو اینجا براتون میزارم و هر قسمت رو که بنویسم اینجا اعلام میکنم
خوشحال میشم نظرتون رو بدونم و اگر دوست داشتید میتونید روی گیت هاب کانتربیوت کنید
لینک خلاصه فصل اول کتاب Designing Data-Intensive Applications
من برگشتم با یکسری پست های جدید
اخیرا شروع به خوندن کتاب Designing Data-Intensive Applications کردم و قصد دارم بعد از مطالعه هر فصل یک خلاصه ای از اون رو در قالب یک پست یا مقاله جا بدم
مقاله اول رو در باب خلاصه فصل اول نوشتم
در ابتدا قصد داشتم به صورت کامل فارسی بنویسم ولی از یه جایی به بعد دیگه حوصله ترجمه اش رو نداشتم و فقط یک توضیح ساده و کلی به فارسی نوشتم و انگلیسی ادامه دادم
مقالات رو به صورت فایل md خواهم نوشت و روی گیت هاب منتشر میکنم و البته لینکش رو اینجا براتون میزارم و هر قسمت رو که بنویسم اینجا اعلام میکنم
خوشحال میشم نظرتون رو بدونم و اگر دوست داشتید میتونید روی گیت هاب کانتربیوت کنید
لینک خلاصه فصل اول کتاب Designing Data-Intensive Applications
👍6❤2👎1
You know they say economists know the price of everything and the value of nothing? Well, programmers know the benefits of everything and the trade-offs of nothing.
-- Rich Hickey
-- Rich Hickey
❤2
Applying Clean Code Principles: Refactoring for Better Structure
I recently refactored the keyboard layouts in a Telegram bot to improve clarity and maintainability. The original procedural approach worked but became difficult to manage as the project grew. By switching to an Enum-based, object-oriented structure, I made the code more readable, easier to maintain, and scalable for future features. This change not only cleaned up the code but also made it more resilient to updates. Check out the before and after below!
I recently refactored the keyboard layouts in a Telegram bot to improve clarity and maintainability. The original procedural approach worked but became difficult to manage as the project grew. By switching to an Enum-based, object-oriented structure, I made the code more readable, easier to maintain, and scalable for future features. This change not only cleaned up the code but also made it more resilient to updates. Check out the before and after below!
👍5❤3
دپندنسی اینجکشن ( Dependency Injection )
یک دیزاین پترن عالی برای مدیریت وابستگی کمک میکنه یک پروژه انعطافپذیرتر، قابل نگهداریتر و تستپذیرتر داشته باشیم
تعریفش به صورت خلاصه هم میشه به جای اینکه کلاسها و توابع وابستگیها رو بهصورت داخلی ایجاد کنیم با استفاده از این دیزاین پترن میتونیم اونارو از بیرون بهشون بدیم. (مثال هارو ببینید برای بهتر متوجه شدن)
از مزایای این دیزان پترن میشه اشاره کرد به
1. تست پذیری بیشتر چون شما میتونید کلاس های ماک شده خودتون رو بدید برای تست کردن کلاس مورد نظر خودتون مثلا اینجا میتونید کلاس دیتابیس in memory ای که خودتون ماک کردید رو بدید و دیگه کانکشن اضافه نسازید
2. راحت تر شدن تغییرات از اونجایی که کلاس ها دپندنسی های خودشون رو کنترل نمی کنند راحت تر میشه اونارو تغییر داد درصورت ثابت موندن interface اشون مثلا داخل این مثال ما میتونیم روند کار متد connect رو تغییر بدیم و به جای اینکه به sql وصل بشیم به redis وصل بشیم بدون اینکه تغییری داخل UserService بدیم
3. و اخرین ویژگی که به ذهنم میرسه اینه که کد شما اصل SRP رو حفظ میکنه و هر بخش کاری که باید انجام بده رو انجام میده مثلا اینجا داخل مثالی که از DI استفاده میشه دیگه نیازی به instantiate کردن دیتابیس داخل UserService نیست
این دیزاین پترن رو بهتره داخل پروژه هایی استفاده کنید که پیچدگی زیادی دارن و وابستگی زیادی بین بخش های مختلف وجود داره و البته برای زمان هایی که میخواید بین implement های مختلف جا به جا بشید هم کاربردیه مثل همین مثال دیتابیس SQL و Redis ای که گفتم
یک دیزاین پترن عالی برای مدیریت وابستگی کمک میکنه یک پروژه انعطافپذیرتر، قابل نگهداریتر و تستپذیرتر داشته باشیم
تعریفش به صورت خلاصه هم میشه به جای اینکه کلاسها و توابع وابستگیها رو بهصورت داخلی ایجاد کنیم با استفاده از این دیزاین پترن میتونیم اونارو از بیرون بهشون بدیم. (مثال هارو ببینید برای بهتر متوجه شدن)
از مزایای این دیزان پترن میشه اشاره کرد به
1. تست پذیری بیشتر چون شما میتونید کلاس های ماک شده خودتون رو بدید برای تست کردن کلاس مورد نظر خودتون مثلا اینجا میتونید کلاس دیتابیس in memory ای که خودتون ماک کردید رو بدید و دیگه کانکشن اضافه نسازید
2. راحت تر شدن تغییرات از اونجایی که کلاس ها دپندنسی های خودشون رو کنترل نمی کنند راحت تر میشه اونارو تغییر داد درصورت ثابت موندن interface اشون مثلا داخل این مثال ما میتونیم روند کار متد connect رو تغییر بدیم و به جای اینکه به sql وصل بشیم به redis وصل بشیم بدون اینکه تغییری داخل UserService بدیم
3. و اخرین ویژگی که به ذهنم میرسه اینه که کد شما اصل SRP رو حفظ میکنه و هر بخش کاری که باید انجام بده رو انجام میده مثلا اینجا داخل مثالی که از DI استفاده میشه دیگه نیازی به instantiate کردن دیتابیس داخل UserService نیست
این دیزاین پترن رو بهتره داخل پروژه هایی استفاده کنید که پیچدگی زیادی دارن و وابستگی زیادی بین بخش های مختلف وجود داره و البته برای زمان هایی که میخواید بین implement های مختلف جا به جا بشید هم کاربردیه مثل همین مثال دیتابیس SQL و Redis ای که گفتم
👍5
🔍 نگاهی عمیقتر به ولیدیشن (Validation) در توسعه نرمافزار
ولیدیشن به زبان ساده به معنی اعتبارسنجی دادههای ورودی سیستم قبل از اجرای عملیات داخل سیستم هست.
🔑 انواع Validation
1. Syntax Validation
سادهترین نوع ولیدیشن سینتکس ولیدیشن بررسی میکنه که آیا ساختار دیتای ورودی صحت داره یا نه. مثلاً:
اینجا سینتکس ولیدیشن بررسی میکنه که:
- order_id باید عدد باشد.
- sku باید رشته باشد.
- quantity باید یک عدد غیرمنفی باشد.
✅ نکته مهم اینکه این نوع ولیدیشن باید در لایههای اولیه مثل کنترلرهای سیستم شما انجام بشه تا از ورود دیتای اشتباه به لاجیک جلوگیری بشه.
2. Semantic Validation
ولیدیشن معنایی به مفهوم دیتای مرتبط هست. گاهی اوقات حتی اگر سینتکس دیتا درست باشه، ممکن است هنوز در زمینه تجاری منطقی نباشه.
مثلاً اگر شما لاجیکی برای تخصیص موجودی داشته باشید:
اینجا سیستم باید بررسی کنه که:
- آیا SKU-001 وجود داره؟
- آیا به اندازه کافی موجودی برای تخصیص ۱۰ واحد وجود داره؟
✅ اینجا حتی اگر سینتکس دیتا درست باشه باید در زمینه کسب و کار هم منطقی باشه.
3. Pragmatic Validation
ولیدیشن کاربردی بررسی میکنه که آیا این اکشن ممکن هست یا مجاز هست با توجه به وضعیت فعلی سیستم. مثلاً:
- اگر انبار تعطیل باشه نباید سفارشی پردازش بشه.
- یا اگر یک کد تخفیف منقضی شده باید اعمال اون روی سفارش ناموفق باشه.
یک مثال دیگر:
شما ممکن است اکشنی مثل:
داشته باشید. ولیدیشن سینتکس و معنایی درست هستند، اما اگر قانون بیزینس شما بگه "مشتری نمیتونه بیش از ۲۰ محصول در یک بار سفارش بده"، این اکشن در ولیدیشن کاربردی ناموفق میشه.
🧠 Common Validation Patterns
1. Declarative Validation
فرض کنید یک لیست از قوانین دارید مانند:
- order_id باید یک عدد صحیح باشد.
- quantity باید غیرمنفی باشد.
این قوانین را میتوان بهصورت Declarative از قبل تعریف کرد. در پایتون، میتوانید از چیزی مثل pydantic برای تعریف ورودیهای مورد انتظار استفاده کنید.
2. Postel’s Law (Tolerant Reader Pattern)
این قانون میگه:
Be conservative in what you send, but liberal in what you accept.
یعنی "در آنچه ارسال میکنید محافظهکار باشید، اما در آنچه دریافت میکنید آزاد باشید." یا به عبارت سادهتر، سیستم شما باید در پذیرش فیلدهای اضافی یا ناشناخته انعطافپذیر باشه.
برای مثال، اگر سیستم شما فقط به
میتونید فیلد اضافی (
🏁 جمعبندی
- ولیدیشن Syntax بررسی میکنه که آیا قالب دادهها صحیح هست یا نه.
- ولیدیشن Semantic بررسی میکنه که دادهها در زمینه بیزینس شما معنیدار هستند.
- ولیدیشن Pragmatic بررسی میکند که آیا عمل منطقی و با توجه به وضعیت فعلی سیستم امکانپذیر هست.
- از ولیدیشن declarative برای اعمال قوانین استفاده کنید و از Tolerant Reader Pattern برای انعطافپذیری بیشتر استفاده کنید
ولیدیشن به زبان ساده به معنی اعتبارسنجی دادههای ورودی سیستم قبل از اجرای عملیات داخل سیستم هست.
🔑 انواع Validation
1. Syntax Validation
سادهترین نوع ولیدیشن سینتکس ولیدیشن بررسی میکنه که آیا ساختار دیتای ورودی صحت داره یا نه. مثلاً:
{
"order_id": 123,
"sku": "ABC-123",
"quantity": 5
}اینجا سینتکس ولیدیشن بررسی میکنه که:
- order_id باید عدد باشد.
- sku باید رشته باشد.
- quantity باید یک عدد غیرمنفی باشد.
✅ نکته مهم اینکه این نوع ولیدیشن باید در لایههای اولیه مثل کنترلرهای سیستم شما انجام بشه تا از ورود دیتای اشتباه به لاجیک جلوگیری بشه.
2. Semantic Validation
ولیدیشن معنایی به مفهوم دیتای مرتبط هست. گاهی اوقات حتی اگر سینتکس دیتا درست باشه، ممکن است هنوز در زمینه تجاری منطقی نباشه.
مثلاً اگر شما لاجیکی برای تخصیص موجودی داشته باشید:
allocate("SKU-001", quantity=10)اینجا سیستم باید بررسی کنه که:
- آیا SKU-001 وجود داره؟
- آیا به اندازه کافی موجودی برای تخصیص ۱۰ واحد وجود داره؟
✅ اینجا حتی اگر سینتکس دیتا درست باشه باید در زمینه کسب و کار هم منطقی باشه.
3. Pragmatic Validation
ولیدیشن کاربردی بررسی میکنه که آیا این اکشن ممکن هست یا مجاز هست با توجه به وضعیت فعلی سیستم. مثلاً:
- اگر انبار تعطیل باشه نباید سفارشی پردازش بشه.
- یا اگر یک کد تخفیف منقضی شده باید اعمال اون روی سفارش ناموفق باشه.
یک مثال دیگر:
شما ممکن است اکشنی مثل:
allocate("SKU-001", quantity=50)داشته باشید. ولیدیشن سینتکس و معنایی درست هستند، اما اگر قانون بیزینس شما بگه "مشتری نمیتونه بیش از ۲۰ محصول در یک بار سفارش بده"، این اکشن در ولیدیشن کاربردی ناموفق میشه.
🧠 Common Validation Patterns
1. Declarative Validation
فرض کنید یک لیست از قوانین دارید مانند:
- order_id باید یک عدد صحیح باشد.
- quantity باید غیرمنفی باشد.
این قوانین را میتوان بهصورت Declarative از قبل تعریف کرد. در پایتون، میتوانید از چیزی مثل pydantic برای تعریف ورودیهای مورد انتظار استفاده کنید.
from pydantic import BaseModel, Field
class Order(BaseModel):
order_id: int
sku: str
quantity: int = Field(ge=0)
2. Postel’s Law (Tolerant Reader Pattern)
این قانون میگه:
Be conservative in what you send, but liberal in what you accept.
یعنی "در آنچه ارسال میکنید محافظهکار باشید، اما در آنچه دریافت میکنید آزاد باشید." یا به عبارت سادهتر، سیستم شما باید در پذیرش فیلدهای اضافی یا ناشناخته انعطافپذیر باشه.
برای مثال، اگر سیستم شما فقط به
order_id و quantity نیاز دارد، اما این را دریافت کند:{
"order_id": 123,
"quantity": 5,
"promo_code": "DISCOUNT20"
}میتونید فیلد اضافی (
promo_code) را نادیده بگیرید به جای اینکه کل درخواست را رد کنید. این کار سیستم شما را در برابر تغییرات انعطافپذیر میکنه.🏁 جمعبندی
- ولیدیشن Syntax بررسی میکنه که آیا قالب دادهها صحیح هست یا نه.
- ولیدیشن Semantic بررسی میکنه که دادهها در زمینه بیزینس شما معنیدار هستند.
- ولیدیشن Pragmatic بررسی میکند که آیا عمل منطقی و با توجه به وضعیت فعلی سیستم امکانپذیر هست.
- از ولیدیشن declarative برای اعمال قوانین استفاده کنید و از Tolerant Reader Pattern برای انعطافپذیری بیشتر استفاده کنید
👍4❤2
📘 Chapter 1: Getting to Know Asyncio
🔄 What is
🖥️ I/O-bound vs. CPU-bound Tasks
- I/O-bound: Tasks that wait for input/output, such as web requests or database queries. These tasks benefit greatly from
- CPU-bound: Tasks that use lots of computational power (like math calculations).
⚙️ Concurrency, Parallelism, and Multitasking
- Concurrency: When multiple tasks appear to be running at the same time by taking turns. For example, while one task is waiting for a file to download, another task can start.
- Parallelism: When tasks are literally running at the same time on multiple CPU cores.
- Multitasking: Managing several tasks at once. This can be preemptive (the OS decides when to switch between tasks) or cooperative (tasks decide when to yield control).
🔄 Processes vs. Threads
- Processes: Independent units that do not share memory. They are good for CPU-bound tasks but use more resources.
- Threads: Lighter-weight than processes and share memory within the same program. However, Python’s Global Interpreter Lock (GIL) prevents threads from running Python code at the same time (no parallel execution). Still, threads are useful for I/O-bound tasks.
🔐 Global Interpreter Lock (GIL)
- GIL is a mechanism in Python that allows only one thread to execute Python bytecode at a time, even on multi-core systems.
- This makes multithreading less useful for CPU-bound operations but still beneficial for I/O-bound tasks because I/O releases the GIL.
⚡ Single-threaded Concurrency
📬 What is a Socket?
A socket is a low-level connection to send and receive data over a network. By default, sockets are blocking, meaning they make the program wait while they communicate. Non-blocking sockets allow the program to continue executing other tasks while waiting for a response. This is key to how
🔄 Event Loop
- An event loop is a core part of how
- Tasks that involve I/O can pause and free up the loop to run other tasks, making programs more efficient.
🕹️ How It Works:
1. Tasks are submitted to the event loop.
2. The loop starts running tasks. If a task hits an I/O operation (like a web request), the task pauses.
3. The operating system watches the socket and informs the event loop when the I/O is complete.
4. The event loop resumes the paused task and continues processing.
🤔 Why Use
- Improves performance for programs that do a lot of waiting (web servers, file reading).
- Lightweight and doesn’t need multiple threads or processes to handle concurrency.
- Efficient resource utilization: While waiting for slow I/O operations, the CPU can continue working on other tasks, leading to faster overall execution.
🚀 Key Takeaways:
-
- It does not remove Python's GIL but makes it less of an issue by focusing on I/O tasks.
- Non-blocking I/O and the event loop allow tasks to pause and resume, making concurrency efficient even with just one thread.
#PythonConcurrencyWithAsyncio
#Chapter_01
#Notes #Book
🔄 What is
asyncio?asyncio is a Python library introduced in version 3.4 that allows you to run I/O-bound tasks concurrently. Rather than making your code wait for slow operations, asyncio allows multiple tasks to run "in parallel" by pausing tasks when they’re waiting for I/O. This allows Python to work on other tasks in the meantime.🖥️ I/O-bound vs. CPU-bound Tasks
- I/O-bound: Tasks that wait for input/output, such as web requests or database queries. These tasks benefit greatly from
asyncio as it allows them to pause and let other tasks run while waiting.- CPU-bound: Tasks that use lots of computational power (like math calculations).
asyncio isn't designed for CPU-heavy tasks.⚙️ Concurrency, Parallelism, and Multitasking
- Concurrency: When multiple tasks appear to be running at the same time by taking turns. For example, while one task is waiting for a file to download, another task can start.
- Parallelism: When tasks are literally running at the same time on multiple CPU cores.
- Multitasking: Managing several tasks at once. This can be preemptive (the OS decides when to switch between tasks) or cooperative (tasks decide when to yield control).
asyncio uses cooperative multitasking, meaning tasks "cooperate" by pausing when they reach I/O.🔄 Processes vs. Threads
- Processes: Independent units that do not share memory. They are good for CPU-bound tasks but use more resources.
- Threads: Lighter-weight than processes and share memory within the same program. However, Python’s Global Interpreter Lock (GIL) prevents threads from running Python code at the same time (no parallel execution). Still, threads are useful for I/O-bound tasks.
🔐 Global Interpreter Lock (GIL)
- GIL is a mechanism in Python that allows only one thread to execute Python bytecode at a time, even on multi-core systems.
- This makes multithreading less useful for CPU-bound operations but still beneficial for I/O-bound tasks because I/O releases the GIL.
⚡ Single-threaded Concurrency
asyncio achieves concurrency without needing multiple threads by using non-blocking I/O and an event loop. 📬 What is a Socket?
A socket is a low-level connection to send and receive data over a network. By default, sockets are blocking, meaning they make the program wait while they communicate. Non-blocking sockets allow the program to continue executing other tasks while waiting for a response. This is key to how
asyncio achieves concurrency with just one thread.🔄 Event Loop
- An event loop is a core part of how
asyncio works. It’s a loop that runs tasks, pausing and resuming them as necessary. The event loop checks if tasks are waiting on I/O and either runs them or pauses them until they’re ready.- Tasks that involve I/O can pause and free up the loop to run other tasks, making programs more efficient.
🕹️ How It Works:
1. Tasks are submitted to the event loop.
2. The loop starts running tasks. If a task hits an I/O operation (like a web request), the task pauses.
3. The operating system watches the socket and informs the event loop when the I/O is complete.
4. The event loop resumes the paused task and continues processing.
🤔 Why Use
asyncio?- Improves performance for programs that do a lot of waiting (web servers, file reading).
- Lightweight and doesn’t need multiple threads or processes to handle concurrency.
- Efficient resource utilization: While waiting for slow I/O operations, the CPU can continue working on other tasks, leading to faster overall execution.
🚀 Key Takeaways:
-
asyncio is ideal for I/O-bound tasks and allows you to write concurrent programs using a single thread.- It does not remove Python's GIL but makes it less of an issue by focusing on I/O tasks.
- Non-blocking I/O and the event loop allow tasks to pause and resume, making concurrency efficient even with just one thread.
#PythonConcurrencyWithAsyncio
#Chapter_01
#Notes #Book
❤4👍1
📘 Chapter 2: *Asyncio Basics* 🚀
Chapter 2 delves into the foundational aspects of asyncio in Python, focusing on how it enables single-threaded concurrency using coroutines, tasks, and event loops. Here’s a breakdown:
🌀 2.1 Introducing Coroutines
- Coroutines are special Python functions that can pause and resume execution when encountering a potentially long-running task.
- When a coroutine pauses to wait for an operation, other tasks can run concurrently, providing concurrency. 💡
- `async` and `await` are the two essential keywords:
-
-
⚙️ Example of Creating a Coroutine
This is similar to a normal Python function but can pause its execution.
⏳ 2.2 Introducing Long-Running Coroutines with `sleep`
- Asyncio’s
- When
⚙️ Example of Using
This coroutine pauses for 1 second before returning "Hello World!". During that second, other coroutines can run concurrently.
🔄 2.3 Running Concurrently with Tasks
- A task is a wrapper around a coroutine that schedules it to run on the event loop 🕑.
- Tasks allow coroutines to be run concurrently, as they don’t block the event loop, unlike
⚙️ Example of Creating a Task
Here, the task
⛔ 2.4 Canceling Tasks and Setting Timeouts
- Tasks can be canceled using
⚙️ Example of Cancelling a Task
💼 2.5 Tasks, Coroutines, Futures, and Awaitables
- Futures represent a value that will be available in the future but might not exist yet. They are used internally in asyncio and can be awaited 🎯.
- Coroutines and tasks can both be used in
⚙️ Example of Working with Futures
⏱️ 2.6 Measuring Coroutine Execution Time with Decorators
- By using decorators, we can measure the execution time of coroutines for performance analysis. ⌛
⚠️ 2.7 Pitfalls of Coroutines and Tasks
- Be cautious with CPU-bound code inside coroutines, as it will block the event loop.
- Avoid using blocking I/O APIs; use asyncio-compatible libraries to ensure the event loop runs smoothly 🛠️.
🔧 2.8 Accessing and Manually Managing the Event Loop
- You can access the event loop directly using
🛠️ 2.9 Using Debug Mode
- Debug mode helps in identifying long-running coroutines or tasks that block the event loop 🧐. You can enable it with:
Or by setting the
⚙️ Example of Running in Debug Mode
#PythonConcurrencyWithAsyncio
#Chapter_02
#Notes #Book
Chapter 2 delves into the foundational aspects of asyncio in Python, focusing on how it enables single-threaded concurrency using coroutines, tasks, and event loops. Here’s a breakdown:
🌀 2.1 Introducing Coroutines
- Coroutines are special Python functions that can pause and resume execution when encountering a potentially long-running task.
- When a coroutine pauses to wait for an operation, other tasks can run concurrently, providing concurrency. 💡
- `async` and `await` are the two essential keywords:
-
async defines a function as a coroutine.-
await pauses the coroutine until a result is available from an asynchronous operation.⚙️ Example of Creating a Coroutine
async def my_coroutine() -> None:
print("Hello world!")
This is similar to a normal Python function but can pause its execution.
⏳ 2.2 Introducing Long-Running Coroutines with `sleep`
- Asyncio’s
sleep function allows us to pause execution, simulating real-world, long-running operations like web requests or database queries 🌐.- When
await asyncio.sleep() is called, other tasks can be executed during the pause.⚙️ Example of Using
asyncio.sleepasync def hello_world_message() -> str:
await asyncio.sleep(1)
return "Hello World!"
This coroutine pauses for 1 second before returning "Hello World!". During that second, other coroutines can run concurrently.
🔄 2.3 Running Concurrently with Tasks
- A task is a wrapper around a coroutine that schedules it to run on the event loop 🕑.
- Tasks allow coroutines to be run concurrently, as they don’t block the event loop, unlike
await, which pauses until a result is returned.⚙️ Example of Creating a Task
import asyncio
from util import delay
async def main():
task = asyncio.create_task(delay(3))
await task
Here, the task
delay(3) runs concurrently, while other code can execute.⛔ 2.4 Canceling Tasks and Setting Timeouts
- Tasks can be canceled using
task.cancel(), raising a CancelledError within the task. If a task is taking too long, we can also set timeouts using asyncio.wait_for 🕒.⚙️ Example of Cancelling a Task
async def cancel_task(task):
task.cancel()
try:
await task
except asyncio.CancelledError:
print("Task was cancelled")
💼 2.5 Tasks, Coroutines, Futures, and Awaitables
- Futures represent a value that will be available in the future but might not exist yet. They are used internally in asyncio and can be awaited 🎯.
- Coroutines and tasks can both be used in
await expressions.⚙️ Example of Working with Futures
from asyncio import Future
my_future = Future()
my_future.set_result(42)
print(my_future.result()) # Outputs: 42
⏱️ 2.6 Measuring Coroutine Execution Time with Decorators
- By using decorators, we can measure the execution time of coroutines for performance analysis. ⌛
⚠️ 2.7 Pitfalls of Coroutines and Tasks
- Be cautious with CPU-bound code inside coroutines, as it will block the event loop.
- Avoid using blocking I/O APIs; use asyncio-compatible libraries to ensure the event loop runs smoothly 🛠️.
🔧 2.8 Accessing and Manually Managing the Event Loop
- You can access the event loop directly using
asyncio.get_event_loop(), though asyncio.run() is recommended for running main coroutines.🛠️ 2.9 Using Debug Mode
- Debug mode helps in identifying long-running coroutines or tasks that block the event loop 🧐. You can enable it with:
python3 -X dev program.py
Or by setting the
PYTHONASYNCIODEBUG environment variable.⚙️ Example of Running in Debug Mode
asyncio.run(main(), debug=True)
#PythonConcurrencyWithAsyncio
#Chapter_02
#Notes #Book
❤3👍2
سلام خدمت دوستان
اخیرا داخل یکی از پروژه ها لازمه که با چندین پنل مرزبان ارتباط برقرار کنیم و برای همین من دنبال یک کلاینت پایتونی خوب برای ارتباط با این پنل بودم که فقط یک پروژه روی گیت هاب پیدا کردم که از نظرم interface جالبی نداشت
برای همین یه کلاینت کوچیک نوشتم واسه استفاده از API های پنل مرزبان داخل پایتون
آدرس پروژه:
https://github.com/Cmatrix1/MarzbanAPIClient/
پنل مرزبان چیه؟
مرزبان یک نرم افزار (وب اپلیکیشن) مدیریت پروکسیه که امکان مدیریت چند صد حساب پروکسی رو به شما میده. مرزبان از Xray-core قدرت گرفته و درواقع با پایتون هم توسعه داده شده
بنظرم حتما یه سری به گیت هاب مرزبان هم بزنید پروژه فوقالعاده ای هست
@Pythonic_Dev
اخیرا داخل یکی از پروژه ها لازمه که با چندین پنل مرزبان ارتباط برقرار کنیم و برای همین من دنبال یک کلاینت پایتونی خوب برای ارتباط با این پنل بودم که فقط یک پروژه روی گیت هاب پیدا کردم که از نظرم interface جالبی نداشت
برای همین یه کلاینت کوچیک نوشتم واسه استفاده از API های پنل مرزبان داخل پایتون
آدرس پروژه:
https://github.com/Cmatrix1/MarzbanAPIClient/
پنل مرزبان چیه؟
مرزبان یک نرم افزار (وب اپلیکیشن) مدیریت پروکسیه که امکان مدیریت چند صد حساب پروکسی رو به شما میده. مرزبان از Xray-core قدرت گرفته و درواقع با پایتون هم توسعه داده شده
بنظرم حتما یه سری به گیت هاب مرزبان هم بزنید پروژه فوقالعاده ای هست
@Pythonic_Dev
👍7❤1
قطعا خیلی از دوستانی که توی حوزه بک اند کار میکنند گاهی اوقات برای داشتن نمونه کار مورد چالش قرار میگیرن
یه مقاله روی ویرگول منتشر کردم که یک راه خیلی ساده و خوب برای ساخت نمونه کار حرفه ای رو توش توضیح دادم
https://vrgl.ir/tM8oi
اگر خوشتون اومد و استقبال کردید، میتونم یک ویدیو هم ضبط کنم که با همین روش، یک وبسایت خفن رو از صفر تا صد بالا بیاریم! 🚀
ممنون میشم نظرات و پیشنهاداتتون رو با من به اشتراک بذارید.
یه مقاله روی ویرگول منتشر کردم که یک راه خیلی ساده و خوب برای ساخت نمونه کار حرفه ای رو توش توضیح دادم
https://vrgl.ir/tM8oi
اگر خوشتون اومد و استقبال کردید، میتونم یک ویدیو هم ضبط کنم که با همین روش، یک وبسایت خفن رو از صفر تا صد بالا بیاریم! 🚀
ممنون میشم نظرات و پیشنهاداتتون رو با من به اشتراک بذارید.
ویرگول
راهنمای ساخت نمونه کار حرفه ای برای بک اند دولوپر ها - ویرگول
راهکاری ساده برای توسعهدهندگان بکاند: با استفاده از قالبهای HTML آماده، نمونهکارهای حرفهای بسازید و زمان خود را ذخیره کنید!
👍9
💡 کاپلینگ (Coupling) در مهندسی نرمافزار
یکی از مفاهیم مهم در طراحی نرمافزار که خیلی وقتها به چشم نمیاد ولی تأثیر عمیقی روی کیفیت، توسعهپذیری و نگهداری کد داره، کاپلینگ یا همون وابستگی بین اجزای سیستم هست.
هرچقدر این وابستگی بین بخشهای مختلف کد کمتر باشه، اون سیستم قابل اعتمادتر، تستپذیرتر و توسعهپذیرتر میشه.
> 🎯 هدف کلی اینه که تا جای ممکن، کاپلینگ رو کاهش بدیم تا اجزای سیستم بتونن جدا از هم تکامل پیدا کنن.
🔧 کاپلینگ یعنی چی؟
به زبان ساده، یعنی اینکه یک ماژول یا کلاس چقدر به بقیهی ماژولها وابستهست.
- کاپلینگ زیاد → تغییر در یک قسمت باعث خرابی قسمتهای دیگه میشه
- کاپلینگ کم→ ماژولها مستقلترن و راحتتر میشه تغییرشون داد
📚 انواع کاپلینگ با مثال:
❌ 1. Content Coupling (بدترین نوع)
وقتی یه ماژول مستقیم به جزئیات داخلی ماژول دیگه دسترسی داره:
✅ بهتر:
2. Common / Global Coupling وابستگی چند ماژول به یه متغیر global:
✅ راه بهتر: استفاده از پارامترها یا Dependency Injection
3. Control Coupling
وقتی یک تابع رفتار تابع دیگه رو با فلگ (flag) کنترل میکنه:
✅ راه بهتر:
4. Stamp Coupling
تابعی یک شیء کامل رو دریافت میکنه ولی فقط بخشی از اون رو استفاده میکنه:
✅ بهتر:
یا استفاده از Protocol / Interface
5. External Coupling
وابستگی مستقیم به فرمت داده یا API خارجی:
✅ بهتر: استفاده از abstraction یا Adapter
✅ 6. Data Coupling (بهترین نوع) ماژول فقط دادههای مورد نیاز رو میگیره:
سادگی، تستپذیری و استقلال 👌
🎯 جمعبندی نهایی
یکی از اشتباهات رایج اینه که دنبال "بهترین راه ممکن" بگردیم.
اما واقعیت اینه که:
هیچ راه مطلقی وجود نداره. هر پروژه نیازهای خودشو داره و ممکنه یه نوع کاپلینگ توی یه شرایط خاص، بهترین انتخاب باشه.
اطلاعات بیشتر:
https://www.youtube.com/watch?v=MM9VQp-k0JQ
یکی از مفاهیم مهم در طراحی نرمافزار که خیلی وقتها به چشم نمیاد ولی تأثیر عمیقی روی کیفیت، توسعهپذیری و نگهداری کد داره، کاپلینگ یا همون وابستگی بین اجزای سیستم هست.
هرچقدر این وابستگی بین بخشهای مختلف کد کمتر باشه، اون سیستم قابل اعتمادتر، تستپذیرتر و توسعهپذیرتر میشه.
> 🎯 هدف کلی اینه که تا جای ممکن، کاپلینگ رو کاهش بدیم تا اجزای سیستم بتونن جدا از هم تکامل پیدا کنن.
🔧 کاپلینگ یعنی چی؟
به زبان ساده، یعنی اینکه یک ماژول یا کلاس چقدر به بقیهی ماژولها وابستهست.
- کاپلینگ زیاد → تغییر در یک قسمت باعث خرابی قسمتهای دیگه میشه
- کاپلینگ کم→ ماژولها مستقلترن و راحتتر میشه تغییرشون داد
📚 انواع کاپلینگ با مثال:
❌ 1. Content Coupling (بدترین نوع)
وقتی یه ماژول مستقیم به جزئیات داخلی ماژول دیگه دسترسی داره:
class User:
def __init__(self):
self._password = "secret"
class AuthService:
def check_password(self, user):
return user._password == "secret" # ❌ دسترسی مستقیم
✅ بهتر:
class User:
def check_password(self, pwd):
return self._password == pwd
2. Common / Global Coupling وابستگی چند ماژول به یه متغیر global:
# settings.py
shared_config = {"theme": "dark"}
✅ راه بهتر: استفاده از پارامترها یا Dependency Injection
3. Control Coupling
وقتی یک تابع رفتار تابع دیگه رو با فلگ (flag) کنترل میکنه:
def process(user, is_admin):
if is_admin:
print("Admin user")
else:
print("Normal user")
✅ راه بهتر:
class User:
def process(self):
print("Normal user")
class AdminUser(User):
def process(self):
print("Admin user")
4. Stamp Coupling
تابعی یک شیء کامل رو دریافت میکنه ولی فقط بخشی از اون رو استفاده میکنه:
def send_email(user):
print(f"Sending email to {user.email}")
✅ بهتر:
def send_email(email):
print(f"Sending email to {email}")
یا استفاده از Protocol / Interface
5. External Coupling
وابستگی مستقیم به فرمت داده یا API خارجی:
username, age = data.split(",")✅ بهتر: استفاده از abstraction یا Adapter
✅ 6. Data Coupling (بهترین نوع) ماژول فقط دادههای مورد نیاز رو میگیره:
def calculate_discount(price, percent):
return price * (1 - percent)
سادگی، تستپذیری و استقلال 👌
🎯 جمعبندی نهایی
یکی از اشتباهات رایج اینه که دنبال "بهترین راه ممکن" بگردیم.
اما واقعیت اینه که:
هیچ راه مطلقی وجود نداره. هر پروژه نیازهای خودشو داره و ممکنه یه نوع کاپلینگ توی یه شرایط خاص، بهترین انتخاب باشه.
اطلاعات بیشتر:
https://www.youtube.com/watch?v=MM9VQp-k0JQ
👍7