در هنگام ساخت نرمافزارهای کاربردی، الگوی طراحی کاربر-محور را فراموش نکنید
قبل از آنکه به بررسی مفهوم بهینهسازی کدها و روش انجام اینکار در پایتون اشاره کنیم، لازم است کمی در مورد طراحی کاربر-محور صحبت کنیم. طراحی کاربر-محور (User-Centered Design) یکی از گرایشهای مهم توسعه نرمافزارها است که چند سالی است مورد توجه تیمهای نرمافزاری و شرکتها قرار گرفته است. مزایای بالقوه طراحی مبتنی بر این گرایش کارکرد خود در صنایع مختلف را بهخوبی نشان داده است. با توجه به اینکه، بخش عمدهای از توسعهدهندگان نرمافزار سالهای متمادی است در این حوزه به فعالیت اشتغال دارند و برخی از آنها بر مبنای سبک و سیاق طراحی قدیمی کار میکنند، ممکن است در ابتدا روی خوش به طراحی کاربر-محور نشان ندهند.
طراحی کاربر- محور به مجموعهای از فرآیندهای تکرارشونده در طراحی اشاره دارد که در هر مرحله بر نیازسنجی درخواستهای کاربر متمرکز است تا راهحلی کارآمد در اختیار کاربران قرار دهد تا بتوانند از محصول توسعهیافته به بهترین شکل استفاده کنند. در طراحی کاربر-محور، انتخابهای طراحی بهشدت تحت تاثیر انتظارات، اهداف و خواستههای کاربر است. در طراحی فوق، کاربران از ابتدا تا انتهای طراحی محصول در جریان پیشرفت کار قرار دارند. نکته مهمی که باید در این زمینه به آن دقت کنید این است که اصول طراحی کاربر-محور فراتر از یک طراحی ساده کاربری است و طراحان مجبور هستند محصولات را با هدف پاسخگویی به نیازهای طیف گستردهای از کاربران توسعه دهند. بهطور معمول، رویکرد فوق بهشکل تحقیقات کاربر، مصاحبه، تست کاربردپذیری و مجموعهای از بازخوردها انجام میشود. در بیشتر موارد، طراحی کاربر-محور مبتنی بر چهار مرحله زیر است:
- درک مفهومی که کاربر در ذهن دارد
- مشخص کردن نیازها و اعتبارسنجی آنها
- ارائه راهحلهای کارآمد طراحی
- ارزیابی و تکرار مراحل توسعه
هدف نهایی پارادایم طراحی کاربر-محور، توسعه محصولی برای کاربر و مواردی است که به آنها نیاز دارد، بهگونهای که تعامل با محصول بدون مشکل قابل انجام باشد. طراحی کاربر-محور به طراحان کمک میکند مشکلات کاربران را شناسایی کنند و به آنها اجازه میدهد از راهحلهایی در فرآیند توسعه استفاده کنند که برخواسته از نقطه نظرات کاربران است.
بهینهسازی چیست؟
اجازه دهید، کار را با تعریف بهینهسازی کدها شروع کنیم تا ایده اولیهای بهدست آوریم و متوجه شویم که چرا نیازمند بهینهسازی کدهای پایتون هستیم. گاهی اوقات نوشتن کدهایی که قرار است کار خاصی انجام دهند، کافی نیست. کدهای بزرگ و ناکارآمد میتوانند سرعت اجرای برنامهها را کند کنند، ضررهای مالی به مشتریان وارد کنند یا در آینده، زمان ارزیابی و رفع مشکلات و باگها را بیشتر کنند. بهینهسازی کدهای پایتون راهکاری است که اجازه میدهد برنامهای با خطوط کمتر و میزان مصرف حافظه کمتر بنویسید و به این صورت، برنامهای کارآمدتر و روانتر در اختیار مشتری قرار دهید که نتایج دلخواه را در کمترین زمان ممکن در اختیارش قرار دهد.
زمانی که نوبت به پردازش تعداد زیادی عملیات یا دادهها میرسد، این مسئله اهمیت زیادی پیدا میکند. بنابراین، جایگزینی و بهینهسازی برخی بلوکها و ویژگیهایی که ممکن است روند اجرای یک برنامه را با مشکل روبهرو کنند، موضوع مهمی است که نباید بهسادگی از کنار آن عبور کنید. بهطور معمول، بهینهسازی کدها به دلایل زیر انجام میشود:
- افزایش سرعت و عملکرد برنامه
- افزایش خوانایی کدها
- اشکالزدایی سادهتر خطاها
- صرفهجویی در میزان استفاده از توان پردازنده مرکزی و منابع سیستمی
6 نکته برتر در زمینه بهینهسازی کدهای پایتون
توسعهدهندگان پایتون باید بهجای کدنویسی ساده از تکنیکهای بهینهسازی کد استفاده کنند تا اطمینان حاصل کنند برنامهها بهشکل سریعتری اجرا میشوند. در ادامه با شش ترفند کاربردی در زمینه بهینهسازی کدها آشنا میشوید که کمک میکنند برنامهها بهشکل روان و سریعتری اجرا شوند.
1. از تکنیک بهینهسازی Peephole استفاده کنید
برای درک بهتر تکنیک بهینهسازی Peephole، اجازه دهید کار را با نحوه اجرای کدهای پایتون آغاز کنیم. برای این منظور، ابتدا کدها را در یک فایل استاندارد بنویسید. در ادامه، دستور زیر را اجرا کنید
python -m compileall <filename>
در دستور بالا، بهجای filename باید نام فایل خود را تعیین کنید. پس از اجرا، همان فایل را با فرمت *.pyc که بیانگر کدهای بهینه است، دریافت خواهید کرد.
Peephole یک تکنیک بهینهسازی کدها در پایتون است که زمان کامپایل را بهبود بخشیده و عملکرد کدها را بهتر میکند. با استفاده از تکنیک بهینهسازی Peephole، کدها در پشت صحنه بهینه میشوند، پیشمحاسباتی روی دستورات و عبارات ثابت یا آزمونهای عضویت (Membership) روی آنها انجام میشوند. بهطور مثال، میتوانید چیزی شبیه تعداد ثانیههای یک روز را بهصورت a = 60*60*24 بنویسید تا کدها خواناتر شوند و مفسر زبان بهسرعت محاسبهها را انجام دهد.
نتیجه تکنیک بهینهسازی Peephole در مورد مثال ثانیهها، این خواهد بود که پایتون عبارات ثابت 60*60*24 را از قبل محاسبه میکند و آنها را با 86400 جایگزین میکند. بنابراین، هنگامی که عبارتهای ریاضی فوق را مشاهده میکند، محاسبهها را بهسرعت انجام میدهد و عملکرد برنامه کاربردی کاهش پیدا نمیکند.
چرا باید از تکنیک بهینهسازی Peephole استفاده کنیم؟
با استفاده از روش مذکور، میتوانید یک بخش از برنامه یا بخشی از دستورات را بدون اعمال تغییرهای قابل توجه در خروجی جایگزین کنید. به بیان دقیقتر، با استفاده از این روش بهینهسازی قادر به انجام کارهای زیر هستید:
ساختارهای قابل تغییر را به غیرقابل تغییر تبدیل کنید. این کار را میتوان با استفاده از یکی از سه تاپل (Tuple) زیر انجام داد:
- <code__.co_varnames__>: متغیرهای محلی را با پارامترهای مشخصشده، ذخیره میکند.
- <code__.co_names__>: دادههای خام global را در خود جای میدهد.
- <code__.co_consts__>: به تمامی ثابتها ارجاع میدهد.
میتوانید، عضویت یک عنصر را با در نظر گرفتن دستورات بهعنوان یک عمل با هزینه ثابت و بدون توجه به اندازه مجموعه، تایید کنید.
مجموعه (set) و لیست (list) را به ثابتها تبدیل کنید.
نکتهای که باید به آن دقت کنید این است که فرآیند تبدیل تنها برای دادههای خام توسط پایتون قابل انجام است. از اینرو، اگر مجموعهها یا لیستهایی که استفاده میکنید فاقد دادههای خام باشند، فرآیند بهینهسازی انجام نخواهد شد. برای روشن شدن بحث، اجازه دهید چند مثال ساده را بررسی کنیم:
Def peephole_func():
A= ”Hello, world” * 5
B= [1,2] *7
C=(10,20,30) * 3
Print(a,b,c)
خروجی قطعه کد بالا در شکل ۱ نشان داده شده است.
شکل 1
عبارت ”Hello, world” * 5 یک دستور ثابت به طول کمتر از 4096 است. از اینرو، توسط کامپایلر بهصورت “Hello world” در 5 بار تکرار متوالی، استنتاج میشود.
عبارت [1,2] *7 یک لیست (شیء قابل تغییر) است، از اینرو، ارزیابی نمیشود.
عبارت (10,20,30) * 3 مجموعهای به طول 9 است که کمتر از 256 است (برای تاپلها)، از اینرو بهشکل (10, 20, 30, 10, 20, 30, 10, 20, 30) ذخیره میشود.
2. درونسازی رشتهها با هدف دستیابی به عملکرد بهتر
اشیاء رشتهای در زبانهای برنامهنویسی مثل پایتون دنبالهای از کاراکترهای یونیکد هستند؛ از اینرو، در مستندات فنی، دنبالههای متنی (text) نامیده میشوند. هنگامی که کاراکترهایی با اندازههای مختلف به رشتهای اضافه میشوند، اندازه و وزن کل آن افزایش پیدا میکند، اما این افزایش اندازه فراتر از افزوده شدن چند کاراکتر است. پایتون اطلاعات اضافی را برای ذخیره رشتهها به آنها اختصاص میدهد که باعث میشود فضای زیادی از حافظه اصلی را مصرف کنند. پایتون، بهمنظور بهبود عملکرد راهکاری بهنام string interning در اختیار توسعهدهندگان قرار میدهد. string interning به این صورت عمل میکند که رشتههای خاص را هنگام ساخت، در حافظه کش میکند. به عبارت دقیقتر، تنها یک نمونه از یک رشته خاص در هر زمان مشخص، فعال است و هیچ حافظه جدیدی برای ارجاع به آن رزرو نمیشود. String interning وجه شباهت زیادی با اشیاء مشترک (Shared Objects) دارد. هنگامی که یک رشته درونسازی (interned) میشود، بهعنوان یک شیء اشتراکی شناخته میشود، زیرا نمونهای از آن شیء رشته بهشکل سراسری توسط همه برنامههایی که در یک نشست پایتون اجرا میشوند بهاشتراک قرار میگیرند. در انشعابات پایتون مثل سایتون (CPython) هر زمان یک نشست تعاملی توسط پایتون مقداردهی اولیه میشود، اشیاء اشتراکی در حافظه بارگذاری میشوند. به همین دلیل است که string interning به پایتون اجازه میدهد بهشکل کارآمدی با رشتهها کار کند، بهطوری که زمان لازم برای پردازش کمتر شده و حافظه اصلی کمتری برای ذخیرهسازی رشتهها اشغال میشود.
رشتههای identifier
معماری پایتون به این صورت است که ترجیح میدهد تنها رشتههایی را ذخیرهسازی کند که احتمال استفاده مجدد از آنها زیاد است. به بیان دقیقتر، به رشتههای شناسه (identifier) علاقه زیادی دارد. از جمله این رشتهها به موارد زیر باید اشاره کرد:
- نام ویژگیها
- نام متغیرها
- نام آرگومانها
- نام توابع و کلاسها
- کلیدهای دیکشنری
اصولی که بر مبنای آنها یک رشته درونسازی (Intern) میشود، بهشرح زیر است:
فقط رشتهای که در زمان کامپایل بهعنوان یک رشته ثابت بارگذاری میشود، درونسازی میشود و برعکس، رشتهای که در زمان اجرا ساخته شده، درونسازی نخواهد شد. یک رشته اگر حاصل یک محاسبه constant folding باشد، بیانگر این موضوع است که عبارتهای ثابت در زمان کامپایل بهجای زمان اجرا محاسبه شوند، اما اگر طولی بیشتر از 20 کاراکتر داشته باشند، درونسازی روی آنها انجام نمیشود، زیرا تشخیص این مسئله که identifier هستند یا خیر، بهسختی امکانپذیر است. پایتون فقط در صورتی یک رشته را درونسازی و یک هش برای آن ایجاد میکند که رشته با نامی که ترکیبی از حروف، اعداد و یک حرف یا یک کاراکتر زیرخطدار است، تعریف شده باشد. از اینرو، تمام رشتههایی که از یک فایل خوانده میشوند یا از طریق شبکه دریافت میشوند، قابلیت درونسازی ندارند. البته، راهکاری برای حل این مشکل وجود دارد؛ کافی است چنین رشتههایی را با تابع ()intern بارگذاری کنید.
3. نمایهسازی (Profiling) کدها
نمایهسازی کدها راهکار دیگری برای بهینهسازی کدها است. برای این منظور دو گزینه در دسترس توسعهدهندگان قرار دارد.
استفاده از <timeit>
این ماژول مدت زمان مورد نیاز برای اجرای یک وظیفه توسط یک بلوک خاص از کدها را بر حسب میلیثانیه محاسبه میکند. نحوه فراخوانی و اجرای ماژول فوق در شکل ۲ نشان داده شده است. خروجی ماوژول فوق نیز در شکل ۳ نشان داده شده است.
شکل 2
شکل 3
استفاده از <cProfile>
cProfile یک ماژول پیشرفته و بخشی از بسته نرمافزاری است که اولین بار همراه با پایتون 2.5 در دسترس توسعهدهندگان قرار گرفت. توسعهدهندگان میتوانند به روشهای زیر این ماژول را به کدهای پایتون اضافه کنند:
- اضافه کردن تابعی به متد run و در ادامه محاسبه عملکرد
- کل اسکریپت را از خط فرمان در حالی که cProfile را بهعنوان آرگومان فعال میکنید با استفاده از گزینه m- پایتون اجرا کنید.
بهطور مثال، میتوانید از ترکیب نحوی زیر استفاده کنید:
python -m cProfile code.py arg1 arg2 arg3
با دانستن عناصر کلیدی گزارش cProfile، میتوانید گلوگاههای موجود در کدهای خود را پیدا کنید. نکته مهمی که باید به آن دقت کنید این است که تکنیک فوق تنها با فایلهای پایتون کار میکند، از اینرو، نمیتوانید یک CLI پایتون را با فراخوانی مستقیم آن بهشکل زیر نمایه کنید:
python -m cProfile my_cli
اگر در نظر دارید یک CLI را پروفایل کنید، باید مسیر ورودی را در اختیار cProfile قرار دهید. ترکیب نحوی، چیزی شبیه به حالت زیر خواهد بود:
python -m cProfile venv/bin/my_cli
با اجرای دستور بالا، پس از اتمام برنامه، یک جدول خروجی خواهید داشت (شکل 4).
شکل 4
عناصر موجود در شکل ۴ به شرح زیر هستند:
- <ncalls> تعداد فراخوانیهای ایجادشده را نشان میدهد.
- <tottime> زمان کل صرفشده در تابع را نشان میدهد.
- <percall> ضریب <tottime> تقسیم بر <ncalls> را نشان میدهد.
- <cumtime> یکی دیگر از پارامترهای مهم است که زمان تجمیعی اجرای توابع اصلی و فرعی را نشان میدهد.
- <percall> ضریب <cumtime> تقسیم بر فراخوانیهای اولیه را نشان میدهد.
- <filename_lineno(function)> نقطه اجرای یک برنامه را نشان میدهد.
4. استفاده از ژنراتورها و کلیدها برای مرتبسازی
از راهکاریهای قدرتمند دیگری که برای بهینهسازی حافظه در اختیار توسعهدهندگان قرار دارد، ژنراتورها و کلیدها هستند. نکتهای که باید در مورد ژنراتورها به آن دقت کنید این است که همه آیتمها (تکرارگرها) را به یکباره برنمیگردانند، بلکه میتوانند هر بار فقط یک مورد را برگردانند. هنگام مرتب کردن عناصر در یک لیست، بهتر است از کلیدها و روش پیشفرض <sort()> استفاده کنید. بهطور مثال، میتوانید فهرستها و رشتهها را بر اساس شاخص انتخابشده بهعنوان بخشی از آرگومان کلید مرتب کنید. شکل ۵ این موضوع را نشان میدهد.
شکل 5
5. از عملگرهای داخلی و کتابخانههای خارجی غافل نشوید
هزاران عملگر و کتابخانه داخلی در پایتون موجود است. بهتر است تا جایی که ممکن است از ویژگیهای داخلی و ازپیشتعریفشده پایتون استفاده کنید تا عملکرد کدها افزایش پیدا کند. عملگرها و ماژولهایی که از پیش ساخته شدهاند از قبل کامپایل شدهاند و همین مسئله سرعت اجرای برنامههای کاربردی را بیشتر میکند.
برخی از کتابخانههای پایتون، ویژگیها و قابلیتهای ارزشمندی ارائه میکنند که سرعت و عملکرد برنامههای کاربردی را به میزان قابل توجهی افزایش میدهند. بهطور مثال، کافی است بهجای Pickle از cPickle استفاده کنید تا تفاوتها را مشاهده کنید. بستههای PyPy و <Cython> راهی برای بهینهسازی یک کامپایلر ایستا برای سریعتر کردن فرآیند پردازشها ارائه میکنند.
6. از Globalها استفاده نکنید
Globalها میتوانند عوارض جانبی آشکار و پنهان زیادی داشته باشند که در نهایت کدنویسی شما را به سبکی که «کدهای اسپاگتی» نام دارند، سوق میدهند. همچنین، پایتون در دسترسی به متغیرهای خارجی کند است. بنابراین، بهتر است از آنها استفاده نکنید یا دستکم استفاده از آنها را محدود کنید. اگر استفاده از Global اجتنابناپذیر است و مجبور هستید از آنها استفاده کنید به دو مورد زیر دقت کنید:
- از کلمه کلیدی global برای تعریف یک متغیر خارجی استفاده کنید.
- قبل از استفاده از آنها داخل حلقهها، یک کپی محلی آماده کنید.
کلام آخر
ساخت یک برنامه قدرتمند و مقیاسپذیر که بتواند وظایف محوله را بهسرعت انجام دهد و در عین حال از حافظه اصلی بهشکل بهینهای استفاده کند، مهم است. با این حال، ساخت چنین برنامهای تنها بر پایه کدنویسیهای پایه غیرممکن است. به همین دلیل است که باید کدهای پایتون را بهینهسازی کنید. اگر به روشهای بهینهسازی که در این مقاله شرح داده شد دقت کنید، نهتنها کدنویسی تمیزی انجام خواهید داد، بلکه عملکرد برنامههای کاربردیتان بهبود پیدا خواهد کرد و روند بازبینی کدها در آینده کوتاهتر خواهد شد.
ماهنامه شبکه را از کجا تهیه کنیم؟
ماهنامه شبکه را میتوانید از کتابخانههای عمومی سراسر کشور و نیز از دکههای روزنامهفروشی تهیه نمائید.
ثبت اشتراک نسخه کاغذی ماهنامه شبکه
ثبت اشتراک نسخه آنلاین
کتاب الکترونیک +Network راهنمای شبکهها
- برای دانلود تنها کتاب کامل ترجمه فارسی +Network اینجا کلیک کنید.
کتاب الکترونیک دوره مقدماتی آموزش پایتون
- اگر قصد یادگیری برنامهنویسی را دارید ولی هیچ پیشزمینهای ندارید اینجا کلیک کنید.
نظر شما چیست؟