تجزیه و تحلیل استاتیک در مقیاس: یک داستان اینستاگرام
سرور اینستاگرام کاملاً با پایتون کار می کند.
خب ، بیشتر اوقات. برخی از Cython نیز وجود دارد و وابستگی های ما شامل مقدار کافی کد C ++ در معرض Python به عنوان پسوند C است.
برنامه سرور ما یکپارچه است ، یک پایگاه کد بزرگ با چندین میلیون خط و چند هزار نقطه پایانی Django [ 1] ، همه بارگیری شده و با هم خدمت می کنند. چند سرویس از یکپارچه جدا شده است ، اما ما برنامه ای برای از بین بردن تهاجمی آن نداریم.
و این یک یکپارچه سریع است. ما صدها مهندس داریم که روزانه صدها متعهد را حمل می کنند. ما این تعهدات را به طور مداوم و هر هفت دقیقه مستقر می کنیم و معمولاً صد بار در روز تولید می کنیم. هدف ما این است که کمتر از یک ساعت تأخیر بین فرود آمدن در کارشناسی ارشد و تولید مستقیم زندگی کنیم. [2]
واقعاً دشوار است که این پایگاه کد گسترده یکپارچه ، صدها تعهد در روز ، از تبدیل شدن به یک هرج و مرج کامل ، آسیب دید. ما می خواهیم اینستاگرام را به مکانی تبدیل کنیم که تمام مهندسان ما بتوانند تولیدکننده باشند و ویژگی های مفید را به سرعت ارسال کنند!
این پست در مورد چگونگی استفاده از آستر کاری و بازسازی مجدد خودکار برای کمک به مدیریت مقیاس پایگاه کد پایتون است. در چند هفته آینده ، ما جزئیات بیشتری از سایر ابزارها و تکنیک هایی را که برای مدیریت جنبه های دیگر کیفیت پایگاه کد خود توسعه داده ایم ، به اشتراک خواهیم گذاشت.
اگر می خواهید برخی از ایده های ذکر شده را امتحان کنید در این پست ، ما اخیراً LibCST را به صورت منبع آزاد در اختیار شما قرار می دهیم که به عنوان قلب بسیاری از ابزارهای داخلی پرز و بازسازی خودکار ما عمل می کند.
[1] برای اطلاعات بیشتر در مورد نحوه استفاده از جنگو ، بحث "Django در اینستاگرام ”در کنفرانس Django Under the Hood در سال 2016 ارائه دادیم.
[2] برای اطلاعات بیشتر در مورد استقرار مداوم ، بحث "آزاد کردن بزرگترین سایت پایتون جهان در هر هفت دقیقه" را که در PyCon 2019 ارائه دادیم مشاهده کنید.
لنت: مستندات درخواستی
پر کردن به توسعه دهندگان کمک می کند تا موارد یا الگوهای ضد الگویی را که ممکن است هنگام مواجهه با آنها اطلاع نداشته باشند ، پیدا و تشخیص دهند. این برای ما مهم است ، زیرا با وجود صدها مهندس انتشار این ایده ها به طور فزاینده ای دشوار می شود.
پر کردن فقط یکی از انواع تجزیه و تحلیل استاتیک است که ما در Instagram استفاده می کنیم. روش ساده لوحانه اجرای قانون پرز با بیان منظم است. عبارات منظم به راحتی قابل نوشتن هستند ، اما پایتون یک زبان منظم نیست ، بنابراین مطابقت قوی الگویی در کد با یک عبارت منظم دشوار است (یا گاهی اوقات غیرممکن است).
در انتهای دیگر طیف ، ما ابزارهایی مانند mypy و Pyre ، دو جستجوگر نوع استاتیک پایتون داریم که می توانند تجزیه و تحلیل کل برنامه را انجام دهند. اینستاگرام از Pyre استفاده می کند. این ابزارها قدرتمند هستند ، اما گسترش و سفارشی سازی آنها دشوار است.
وقتی در Instagram از پرزها صحبت می کنیم ، معمولاً به قوانین ساده پرینت درخت نحوی انتزاعی اشاره می کنیم. اینگونه است که ما معمولاً قوانین سفارشی lint را برای پایگاه کد سرور اینستاگرام می نویسیم.
وقتی Python ماژولی را اجرا می کند ، با اجرای تجزیه کننده روی کد منبع شروع می شود. این به طور ضمنی یک درخت تجزیه ، نوعی درخت نحو بتونی (CST) ایجاد می کند. این درخت تجزیه نمایشی بدون ضرر از کد منبع ورودی است.همه جزئیات مانند نظرات ، پرانتزها و ویرگولها در این درخت حفظ می شوند. ما می توانیم کد منبع اصلی را با استفاده از این درخت بازسازی کنیم.
درخت تجزیه پایتون (a متأسفانه ، این یک درخت پیچیده ایجاد می کند ، استخراج معناشناسی مورد علاقه ما را دشوار می کند.
Python درخت تجزیه را جمع می کند را به یک درخت نحوی انتزاعی یا AST تبدیل کنید. این یک تبدیل با ضرر است و جزئیات مربوط به "چیزهای بی اهمیت نحوی" مانند نظرات ، پرانتزها و ویرگول ها دور ریخته می شوند. با این حال ، معانی معنایی کد حفظ می شود. توسط ماژول ast.
در اینستاگرام ، ما LibCST را توسعه داده ایم که بهترین های هر دو جهان را ارائه می دهد. این یک نمایش بدون ضرر مانند یک درخت نحوی بتونی (CST) را ارائه می دهد ، اما با این وجود استخراج معناشناسی مانند یک درخت نحوی انتزاعی (AST) را آسان می کند.
نمایندگی درخت نحوی بتونی LibCST.
قوانین پرز ما از درخت نحوی LibCST برای مطابقت با الگوهای کد استفاده می کند. به عنوان یک نمایش سطح بالا ، درخت نحو به راحتی قابل بررسی است و مشکل برخورد با یک زبان غیر منظم را برطرف می کند.
بگذارید بگوییم به دلیل نوع آن وابستگی دایره ای در ماژول خود دارید. فقط واردات پایتون به شما امکان می دهد با قرار دادن واردات فقط نوع در پشت TYPE_CHECKING ، این مشکل را حل کنید: برای جلوگیری از وارد کردن چیزی در زمان اجرا ، از محافظت جلوگیری کنید.
# value imports
از تایپ کردن وارد کردن TYPE_CHECKING
از help help_fn وارد کنید
# واردات فقط نوع
اگر TYPE_CHECKING:
بعداً ، شخصی وابستگی نوع دیگر دیگری را به کد اضافه می کند و از آن محافظت می کند. با این حال ، ممکن است آنها متوجه نشوند که از قبل یک محافظ نوع در ماژول وجود داشته است. # مقدار واردات
از تایپ کردن وارد کردن TYPE_CHECKING
از help help_fn وارد کنید
# واردات فقط نوع
اگر TYPE_CHECKING:
از Circular_dependency وارد کردن CircularType
اگر TYPE_CHECING: # اوه! محافظ نوع تکراری!
از other_package import OtherType
ما می توانیم با یک قانون پرز از این افزونگی جلوگیری کنیم!
ما با شروع مقدمه ای از بلوک های بررسی نوع که با آن روبرو شده ایم ، شروع خواهیم کرد.
< pre> class OnlyOneTypeCheckingIfBlockLintRule (CstLintRule):
def __init __ (خود ، زمینه: زمینه) -> هیچکدام
super () .__ init __ (زمینه)
self .__ type_checking_blocks = 0
سپس ، وقتی با یک شرط بررسی نوع مواجه شدیم ، شمارنده را افزایش می دهیم و بررسی می کنیم که بیش از یک نوع بلوک بررسی وجود ندارد. اگر این اتفاق بیفتد ، با تماس با راهنمای گزارش خود هشدار در آن مکان ایجاد خواهیم کرد.
def visit_If (self، node: cst.If) -> هیچکدام:
اگر node.test.value == "TYPE_CHECKING":
خود .__ نوع_بستن_بلاکها + = 1
if self .__ type_checking_blocks> 1:
self.context.report (
گره ،
"بیش از یک" اگر TYPE_CHECKING "بخش!"
)
این قوانین پرز با عبور از درخت LibCST و جمع آوری اطلاعات کار می کنند. در خط داخلی ما ، این کار با استفاده از الگوی بازدید کننده انجام می شود. همانطور که ممکن است متوجه شده باشید ، قوانین روشهای بازدید را رد می کنند و روشهای مرتبط با انواع گره را رها می کنند. آن بازدید کنندگانبه ترتیب خاصی فراخوانی شوید.
کلاس MyNewLintRule (CstLintRule):
def visit_Assign (خود ، گره):
... # ابتدا تماس گرفت
def visit_Name (خود ، گره):
... # برای هر کودک تماس گرفت
def ترک_تخصیص (خود ، نام):
... # بعد از همه بچه ها
فراخوانی می شود روش های بازدید قبل از هر یک از از فرزندان گره بازدید می شود. روشهای ترک پس از بازدید از همه کودکان گره فراخوانی می شوند.
فلسفه ما در اینستاگرام این است که "ابتدا کار ساده را انجام دهیم". اولین قوانین پرینت سفارشی ما با استفاده از حالت اشتراکی در یک پرونده و با یک بازدید کننده واحد اجرا شد.
یک فایل منفرد ، با یک بازدید کننده ، با استفاده از حالت مشترک.
کلاس بازدید کننده منفرد باید از وضعیت و منطق همه قوانین مربوط به پرزهای ما آگاه باشد ، و همیشه مشخص نبود که کدام ایالت با چه قاعده ای مطابقت دارد. وقتی چند قانون پرز سفارشی داشته باشید ، این درست است ، اما ما تقریباً یک صد قانون پرینت سفارشی داریم که باعث می شود الگوی یک بازدید کننده غیرقابل حفظ شود.
فهمیدن اینکه چه وضعیت و منطقی با هر بررسی انجام می شود دشوار است.
البته ، یک راه حل ممکن برای این مشکل تعریف چندین بازدید کننده است و این که هر بازدید کننده هربار کل درخت را معکوس کند. با این حال ، این مجازات عملکرد بزرگی را متحمل می شود ، و ملافه باید سریع باقی بماند.
هر قانون پرز می تواند درخت را دوباره مرور کند ، و به ترتیب بر روی پرونده اجرا می کند. با این حال ، این مرور مجدد مکرر مجازات عملکرد بزرگی را متحمل خواهد شد.
در عوض ، ما از پرزهای موجود در اکوسیستم های زبان دیگر مانند ESLint جاوا اسکریپت الهام گرفتیم و یک رجیستری متمرکز بازدید کننده ایجاد کردیم.
یک رجیستری بازدید کننده متمرکز. ما می توانیم به طور کارآمد مشخص کنیم که کدام قانون پرزها به کدام گره ها اهمیت می دهد ، در وقت گره هایی که برای آنها مهم نیست صرفه جویی کنید. وقتی درخت را رد می کنیم ، تمام بازدیدکنندگان ثبت شده را جستجو می کنیم و آنها را صدا می کنیم. اگر روشی اجرا نشده باشد ، نیازی به فراخوانی آن نداریم.
این باعث کاهش هزینه محاسبه هر قانون جدید پرز می شود. اگرچه ما معمولاً linter را روی تعداد کمی از پرونده هایی که اخیراً تغییر کرده اند اجرا می کنیم ، اما می توانیم تمام قوانین جدید پرینت خود را به صورت موازی بر روی کل کد سرور اینستاگرام فقط در 26 ثانیه اجرا کنیم. در اینجا ، ما یک چارچوب آزمایشی ایجاد کرده ایم که برای اجرای بهترین روش ها نیاز به آزمایش هم برای مثبت و هم برای منفی کاذب دارد.
کلاس MyCustomLintRuleTest (CstLintRuleTest):
RULE = MyCustomLintRule
معتبر = [
معتبر ("عملکرد خوب_ (این نباید گزارش ایجاد کند")) ،
معتبر ("foo.bad_function (" و نه باید این باشد "))) ،
]
نامعتبر = [
نامعتبر است ("عملکرد بد_ (" اما این باید ") ،" IG00 ") ،
]
خستگی پرزها
با نزدیک به صد قاعده سفارشی ، پرزهای پدیتیکی می توانند به سرعت تبدیل به اتلاف وقت برایتوسعه دهندگان صرف وقت برای اصلاح سبک های سبک و کدگذاری های منسوخ ، مانع پیشرفت مهمتر می شود.
ما دریافته ایم که با تعداد زیادی نق ، مهندسان شروع به نادیده گرفتن همه پرزها ، حتی موارد مهم می کنند. در یک زمان خاص ، مهم نیست که چه توصیه خوبی ارائه می دهیم ، فقط نادیده گرفته می شود.
بیایید بگوییم که ما برای یک تابع با نام بهتر به نام "افزودن" لازم بود که یک تابع به نام "fn" را استهلاک کنیم . تا زمانی که توسعه دهندگان از این واقعیت که "fn" منسوخ شده است آگاه نشوند ، آنها نمی دانند که از آن استفاده نمی کنند. حتی بدتر ، آنها نمی دانند که چه چیزی را در عوض استفاده کنند. بنابراین ، می توانیم یک پرز ایجاد کنیم. اما هر پایگاه کد کافی کافی احتمالاً تعداد زیادی لامپ دیگر از قبل دارد. احتمال این است که این پرزهای مهم در سر و صدا از بین بروند.
باهم بسیاری از nitpicks ، سیگنال ممکن است در نویز از بین برود.
بنابراین ، چه کاری می توانیم در مورد آن انجام دهیم؟
ما می توانیم به طور خودکار بسیاری از مشکلات پیدا شده توسط پرز را برطرف کنیم. دقیقاً مانند اینکه پرزها مستندات مربوط به تقاضا هستند ، اصلاح کنندگان خودکار می توانند بر اساس تقاضا رفع اشکال کنند. با توجه به تعداد گسترده برنامه نویسان در اینستاگرام ، امکان آموزش همه بهترین اقدامات برای هر توسعه دهنده وجود ندارد. افزودن اصلاح کننده های خودکار به ما امکان می دهد تا توسعه دهندگان را در مورد بهترین روشهای جدید در صورت تقاضا آموزش دهیم. رفع کننده های خودکار همچنین به ما امکان می دهند تا با حذف تغییرات یکنواخت ، تمرکز توسعه دهنده را حفظ کنیم. اساساً ، رفع کننده های اتوماتیک از هشدارهای ساده پرز بسیار عملیاتی و آموزشی هستند.
بنابراین ، چگونه می توان یک رفع کننده خودکار ساخت؟ پرزهای مبتنی بر درخت نحو گره آزار دهنده را به ما می دهند. دیگر نیازی به تکرار منطق کشف نیست زیرا قانون lint از قبل وجود دارد! از آنجا که گره ای را که می خواهیم جایگزین کنیم ، می دانیم و محل آن را از منبع می دانیم ، می توانیم آن را با نام عملکرد به روز شده با خیال راحت جایگزین کنیم! این برای رفع نقض پرزهای منفرد در هنگام معرفی بسیار مفید است ، اما وقتی قانون جدید پرزها را معرفی می کنیم صدها مورد نقض موجود در آن وجود دارد. آیا می توانیم همه پرونده های موجود را به یک باره فعالانه به یک باره حل کنیم؟
رمزگذارها
کد رمز فقط یک روش قابل نوشتن برای یافتن مشکلات و ایجاد تغییر در کد منبع است. رمزگذار را به عنوان یک عامل بازدارنده بر روی استروئیدها در نظر بگیرید: این می تواند به سادگی تغییر نام یک متغیر در یک تابع یا به همان اندازه پیچیده باشد که بازنویسی یک تابع برای یک استدلال جدید پیچیده است. دقیقاً از همان مفهوم پرز استفاده می کند ، اما به جای هشدار به برنامه نویس ، می تواند به طور خودکار اقدام کند.
بنابراین ، چرا شما به جای پرز کد کد می نویسید؟ در این مثال ، ما می خواهیم استفاده از get_global را منسوخ کنیم. ما می توانیم از پرز استفاده کنیم ، اما زمان تعمیر محدود نیست و در چندین توسعه دهنده پخش می شود. حتی با نصب خودکار در محل ، ممکن است مدتی طول بکشد تا همه کد به روز شود.
ما می خواهیم استفاده از get_global را با استفاده از متغیرهای نمونه جایگزین نکنیم.
برای رفع این مشکل ، علاوه بر اینکه در برابر get_global قرار می گیریم ، می توانیم یک کد رمز نیز بنویسیم! در اینستاگرام ، ما معتقدیم که الگوهای منسوخ شده و API ها که به آرامی پژمرده می شوند ، تمرکز را از توسعه دهندگان می گیرند و خوانایی کد را کاهش می دهند. ما ترجیح می دهیم پیش فعالانه کد منسوخ شده را حذف کنیم تا اینکه اجازه دهیم آن از بین برودزمان. با توجه به حجم زیاد کد و تعداد توسعه دهندگان فعال ، این اغلب به معنای خودکار کردن استهلاک ها است. اگر بتوانیم به سرعت الگوهای منسوخ شده را از کد خود حذف کنیم ، همه اینستاگرام را مثمر ثمر نگه می داریم.
بسیار خوب ، بنابراین چگونه واقعاً کد نویسی می کنید؟ چگونه با حفظ نظرات ، فاصله و سایر موارد ، فقط متن مورد علاقه خود را جایگزین می کنید؟ شما می توانید از یک درخت نحوی بتونی مانند LibCST برای تغییر کد جراحی با حفظ نظرات و فاصله استفاده کنید. بنابراین ، اگر می خواستم نام "fn" را به "add" در درخت زیر تغییر دهم ، من گره Name را به روز می کنم تا به جای "fn" مقدار "add" داشته باشد و سپس درخت را به دیسک بنویسم!
ما می توانیم با به روزرسانی گره Name از "fn" به "add" قبل از نوشتن ، کد رمز را انجام دهیم درخت به دیسک برگردد. برای مثال دقیق تر ، اسناد LibCST را بررسی کنید.
اکنون که اطلاعاتی در مورد رمزگذارها کسب کردیم ، به یک مثال عملی نگاه می کنیم. اینستاگرام برای رسیدن به یک کد کد کاملاً تایپ شده سخت کار کرده است و ما با استفاده از کد رمزها پیشرفت زیادی کرده ایم.
با توجه به مجموعه ای از توابع تایپ نشده ، می توانیم با استنباط ساده انواع بازگشتی تولید کنیم! به عنوان مثال ، اگر یک تابع فقط یک نوع ابتدایی را بازگرداند ، آن را از نوع بازگشتی اختصاص می دهیم. اگر یک تابع نتیجه یک عمل بولی مانند مقایسه یا "isinstance" را برمی گرداند ، ما به آن یک نوع برگشت بول اختصاص می دهیم. ما دریافتیم که در عمل این یک عمل کاملاً ایمن است که می توان آن را در کل کد اینستاگرام انجام داد.
خوب ، اگر تابعی صریحاً برنگردد یا به طور ضمنی None را بازگرداند ، چه می کنید؟ اگر تابعی صریحاً یک نوع را برنمی گرداند ، به آن نوع None اختصاص دهید. برخلاف مثال آخر ، این امر به دلیل الگوهای رایج توسعه دهنده می تواند خطرناک تر باشد. به عنوان مثال ، ممکن است یک استثنای NotImplemented را در یک روش کلاس پایه بیاندازم و یک رشته را در همه جایگزین های زیر کلاس برگردانم. ذکر این نکته مهم است که همه این تکنیک ها ابتکاری هستند ، اما به نظر می رسد که آنها اغلب به درستی درست هستند که مفید هستند!
تقویت کد رمزها با استفاده از Pyre
بگذارید یک قدم جلوتر برویم. اینستاگرام برای تأیید انواع موجود در پایگاه کد ما ، از Pyre ، یک جستجوگر نوع استاتیک کامل برنامه مشابه mypy ، استفاده می کند. اگر از خروجی Pyre برای قدرتمندتر کردن این رمزگذار استفاده کنیم چه می کنیم؟ همانطور که در قطعه خروجی زیر Pyre مشاهده می کنید ، Pyre اساساً هر آنچه را که برای اصلاح خودکار حاشیه نویسی نیاز داریم به ما می دهد!
$ pyre
2 2 نوع خطا پیدا شد!
test /utils.py: 7: 0 حاشیه نویسی برگشتی [3]: بازگشت "SomeClass" اما هیچ نوع بازگشتی مشخص نشده است.
test /utils.py: 10: 0 حاشیه نویسی برگشتی [3]: برگرداندن `test.other.SomeOtherClass` اما هیچ نوع بازگشتی مشخص نشده است.
هنگام اجرای pyre ، آنالیز دقیقی از جریان کنترل در هر تابع بنابراین ، گاهی اوقات می تواند حدس خوبی در مورد بازگشت عملکرد غیرمعمول داشته باشد. این بدان معنی است که اگر pyre فکر می کند که تابعی یک نوع ساده را برمی گرداند ، پس آن را از نوع بازگشتی اختصاص می دهیم. با این حال ، اکنون به طور بالقوه باید واردات را کنترل کنیم. این بدان معناست که باید بدانیم آیا چیزی از قبل وارد شده است یا به صورت محلی تعریف شده است. کمی لمس می کنمکمی در مورد چگونگی کشف بعداً آن
از افزودن خودکار انواع آسان برای استنباط چه فایده ای داریم؟ خوب ، انواع مستندات هستند! اگر یک عملکرد کاملاً تایپ شود ، توسعه دهندگان برای درک شرایط قبل و بعد از آن مجبور نیستند کد را بخوانند.
def get_description (صفحه: WikiPage) -> اختیاری [str]:
اگر page.draft:
بازگشت هیچ
Return page.metadata ["توضیحات"] # <- این نوع چیست؟
بسیاری از ما با کد پایتون مانند این روبرو شده ایم و کد اینستاگرام نیز از این قاعده مستثنی نیست. اگر get_description تایپ نشده باشد ، ممکن است مجبور باشم چندین ماژول منبع را جستجو کنم تا بفهمم این عملکرد دقیقاً چه چیزی را برمی گرداند. حتی برای توابع ساده تر که استنباط آنها آسان است ، خواندن تعاریف عملکرد با انواع آن برای انسان بسیار آسان تر است.
همچنین ، Pyre صحت درون بدنه عملکرد را ارزیابی نمی کند مگر اینکه خود عملکرد کاملاً حاشیه نویسی شود. در مثال زیر ، خوب است بدانید که تماس ما با برخی از عملکردها قبل از شروع تولید خراب می شود.
def some_function (in: int) -> bool:
بازگشت به> 0
def some_other_function ():
if some_function ("bla"): # <- باید نوع نقض داشته باشد
print ("بله!")
در این صورت ما راه سختی را یاد می گیریم زیرا برخی از عملکردهای دیگر حاشیه نویسی برگشتی ندارند! اگر با استفاده از روش ابتکاری خود نوع بازگشت "هیچ" را به طور خودکار استنباط کرده بودیم ، قبل از اینکه مشکلی ایجاد شود ، در مورد این موضوع اطلاعاتی کسب می کردیم. این مثال به وضوح ساخته شده است ، اما این مسئله همچنان برای Instagram مهم است. اگر میلیون ها خط کد داشته باشید ، در نهایت مشکلات ظاهراً واضحی از این دست را در حین مرور از دست خواهید داد.
در اینستاگرام ، این استنتاج های ساده باعث افزایش تقریباً 10 درصدی عملکردهای تایپ شده می شوند. این باعث می شود هزاران هزار عملکرد که انسان دیگر مجبور به رفع آنها نیست. مزایای کد تایپ بهتر آشکار است ، اما به مزیت دیگری نیز منجر می شود: داشتن یک کد کد کاملاً تایپ شده ، کد رمزهای پیشرفته تری را باز می کند.
اگر به حاشیه نویسی نوع خود اعتماد کنیم ، می توانیم از Pyre برای باز کردن امکانات اضافی استفاده کنیم. . بیایید به عنوان تغییر نام عملکرد خود نگاه کنیم. اگر تابعی که ما به آن تغییر نام می دهیم یک روش کلاس است نه یک تابع جهانی؟
اگر اطلاعاتی را که از pyre دریافت می کنیم با codemod تغییر نام دهیم ، می توانیم سایت های تماس و همچنین تعریف را به طور ناگهانی درست کنیم! در این مثال ، از آنجا که سمت چپ a.fn را می شناسیم ، می دانیم که تغییر نام به a.add ایمن است.
تجزیه و تحلیل استاتیک پیشرفته تر
پایتون دارای چهار نوع دامنه است: جهانی ، کلاس ، عملکرد و درک.
ما می توانیم قفل بیشتر را باز کنیم رمزگذارهای قدرتمند با تجزیه و تحلیل دامنه. این مشکل را از اوایل به خاطر می آورید ، جایی که افزودن نکات نوع به این معنی است که ما باید بالقوه واردات را اضافه کنیم؟ اگر تجزیه و تحلیل دامنه داشته باشید ، می دانید که انواع وارد شده در پرونده از طریق واردات وارد می شوند ، کدام یک به صورت محلی تعریف می شوند و کدام یک از آنها وجود ندارد. به همین ترتیب ، اگر می دانید که یک متغیر جهانی تحت سایه یک آرگومان تابع است ، می توانید از تغییر تصادفی آن جلوگیری کنیداگر به آن متغیر جهانی تغییر نام می دهید.
در تلاش برای رفع همه مشکلات در اینستاگرام یک چیز روشن شده است: یافتن کدی که می خواهیم اصلاح کنیم اغلب مهمتر از خود اصلاح است. غالباً ، افراد می خواهند کارهای ساده ای مانند تغییر نام تابع ، افزودن آرگومان به روشی یا تقسیم ماژول را انجام دهند. انجام هیچ یک از این کارها دشوار نیست ، اما با توجه به اندازه پایگاه کد ما ، یافتن هر خطی که نیاز به اصلاح دارد برای انسان غیرممکن است. به همین دلیل جفت شدن قابلیت کدگذاری با آنالیز استاتیک قوی بسیار مهم است. این به ما امکان می دهد که کدهایی را که باید در نظر بگیریم تا کد رمزها را ایمن تر و قدرتمندتر کنیم ، محدود کنیم.
با تشکر فراوان از اعضای تیم من: جنیفر تیلور (که به طور مشترک این مقاله را نوشت) ، مارک ویسمونته ، جیمی لای ، ری زنگ ، کارل مایر ، آنیرود پادمارائو ، کیت بلاها و لی بیرمن.
اگر می خواهید در مورد این کار اطلاعات بیشتری کسب کنید یا می خواهید به یکی از تیم های مهندسی ما بپیوندید ، لطفاً به ما مراجعه کنید صفحه مشاغل ، ما را در فیس بوک یا توییتر دنبال کنید.
دولت با اینستاگرام مشکل دارد
[ بازدید : 21 ] [ امتیاز : 3 ] [ نظر شما :
]