Найти Π² Π”Π·Π΅Π½Π΅
Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста

πŸͺΆ Как ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡƒ DRY ΠΏΡ€ΠΈ настройкС Apache APISIX

ОглавлСниС

ОбъясняСм, ΠΊΠ°ΠΊ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ DRY (Don't Repeat Yourself) ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ дублирования ΠΈ ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ настройку Apache APISIX, дСлая ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ Π±ΠΎΠ»Π΅Π΅ ΠΊΠΎΠΌΠΏΠ°ΠΊΡ‚Π½ΠΎΠΉ ΠΈ управляСмой.

Π­Ρ‚ΠΎΡ‚ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» взят ΠΈΠ· нашСй СТСнСдСльной email-рассылки, посвящСнной бэкСнду. ΠŸΠΎΠ΄ΠΏΠΈΡˆΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π² числС ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, ΠΊΡ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ дайдТСст.

πŸ“§ ΠŸΠΎΠ΄ΠΏΠΈΡΠ°Ρ‚ΡŒΡΡ

(function () { let link = document .getElementById ("82223eb3-b78d-464d-8178-77f902fb842f-https://proglib.io/w/cf351d3d-2"); if (! link) return; let href = link .getAttribute ("href"); if (! href) return; let prefix = link .dataset .prefix; let action = link .dataset .action; link .addEventListener ("click", function (e) { let data = new FormData (); data .append ("url", href); apiFetch (action, { method: "POST", body: data }) .then (function (res) {}) .catch (function (err) { console .error (err); }); }) })();

DRY – ΠΎΠ΄ΠΈΠ½ ΠΈΠ· самых извСстных ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΎΠ² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ПО: ΠΎΠ½ ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π½Π΅Π½ΡƒΠΆΠ½ΠΎΠ³ΠΎ повторСния Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ΠΎΠ² ΠΊΠΎΠ΄Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ ΠΎΠ΄Π½ΠΈ ΠΈ Ρ‚Π΅ ΠΆΠ΅ дСйствия. DRY Ρ‚Π°ΠΊΠΆΠ΅ стоит ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΏΡ€ΠΈ настройкС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ слоТных систСм, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ этот ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ:

  • Π”Π΅Π»Π°Π΅Ρ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ Π±ΠΎΠ»Π΅Π΅ ΠΊΠΎΠΌΠΏΠ°ΠΊΡ‚Π½ΠΎΠΉ ΠΈ Π»Π΅Π³ΠΊΠΎΠΉ для понимания.
  • Π£ΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ – ΠΊΠΎΠ³Π΄Π° Π½ΡƒΠΆΠ½ΠΎ внСсти измСнСния, Π²Ρ‹ Π΄Π΅Π»Π°Π΅Ρ‚Π΅ это Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² ΠΎΠ΄Π½ΠΎΠΌ мСстС.
  • ΠŸΠΎΠ²Ρ‹ΡˆΠ°Π΅Ρ‚ Ρ‡ΠΈΡ‚Π°Π΅ΠΌΠΎΡΡ‚ΡŒ – конфигурация становится Π±ΠΎΠ»Π΅Π΅ структурированной ΠΈ Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎΠΉ, Ρ‡Ρ‚ΠΎ ΠΎΠ±Π»Π΅Π³Ρ‡Π°Π΅Ρ‚ Π΅Π΅ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌΠΈ ΠΈΠ»ΠΈ администраторами.
  • Π£Π»ΡƒΡ‡ΡˆΠ°Π΅Ρ‚ ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΡƒΠ΅ΠΌΠΎΡΡ‚ΡŒ – ΠΏΡ€ΠΈ услоТнСнии ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ DRY ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‚ ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ Π΅Π΅ управляСмой ΠΈ Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅ΠΌΠΎΠΉ.
  • Π‘ΠΎΠΊΡ€Π°Ρ‰Π°Π΅Ρ‚ врСмя Π½Π° настройку – ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, ΠΌΠΎΠΆΠ½ΠΎ быстрСС ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅.

Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° рассмотрим, ΠΊΠ°ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ DRY ΠΏΡ€ΠΈ настройкС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ API-шлюза Apache APISIX.

DRY-настройка Upstream

Upstream Π² Apache APISIX выполняСт балансировку Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ Π½Π° Π·Π°Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π°Π±ΠΎΡ€ сСрвисных ΡƒΠ·Π»ΠΎΠ² согласно ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ: ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΡŽ клиСнтских запросов ΠΈ ΠΈΡ… Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ сСрвисам. ΠŸΡ€ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΎΠ½Π»Π°ΠΉΠ½-ΠΌΠ°Π³Π°Π·ΠΈΠ½Π°, Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‰ΠΈΠΉ бэкСндСр, скорСС всСго, Π½Π°Ρ‡Π½Π΅Ρ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

Π”ΠΎΠ²ΠΎΠ»ΡŒΠ½ΠΎ быстро Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сообразит, Ρ‡Ρ‚ΠΎ этот ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎ ΠΎΡˆΠΈΠ±ΠΎΡ‡Π΅Π½ – ΠΎΠ½ допускаСт Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ всСх HTTP-ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² Π² ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π΅ Ρ‚ΠΎΠ²Π°Ρ€ΠΎΠ², Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅, ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ записСй Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ доступны Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌ. Для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ бэкСндСр Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ Π½Π° Π΄Π²Π΅ части:

-2

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π²Ρ€ΠΎΠ΄Π΅ Π±Ρ‹ Ρ€Π΅ΡˆΠ΅Π½Π°, Π½ΠΎ настройки Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π΄ΡƒΠ±Π»ΠΈΡ€ΡƒΡŽΡ‚ΡΡ – Ссли Π±ΡƒΠ΄Π΅Ρ‚ Π½ΡƒΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΈΠ»ΠΈ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ ΡƒΠ·Π»Ρ‹, это придСтся ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π² Π΄Π²ΡƒΡ… мСстах. И хотя Π² Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ… Π½ΠΎΠ΄Ρ‹ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π½Π΅ ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡΠ»ΡΡŽΡ‚ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ, Π° ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ динамичСски с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ обнаруТСния сСрвисов, смысл ошибки ΠΎΡ‚ этого Π½Π΅ мСняСтся – Π΄ΡƒΠ±Π»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π°/настроСк Π²Π»Π΅Ρ‡Π΅Ρ‚ Π·Π° собой ΡƒΡ‚ΠΎΠΌΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ внСсСния ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π²ΠΎ всС ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΡΡŽΡ‰ΠΈΠ΅ΡΡ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Ρ‹. Π’ случаС с ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΌ Π²Ρ‹ΡˆΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠΌ Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Ρ‚Π°ΠΊ:

-3

НуТно ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π² Apache APISIX Π΅ΡΡ‚ΡŒ Π΄Π²Π° способа Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ upstream:

  • ВстроСнный – конфигурация указываСтся нСпосрСдствСнно Π² ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π΅.
  • Бсылка ΠΏΠΎ ID – ΠΊΠΎΠ³Π΄Π° создаСтся ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ upstream, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡΡΡ‹Π»Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· upstream_id.

Π­Ρ‚ΠΈ Π΄Π²Π° ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π²Π·Π°ΠΈΠΌΠΎΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΌΠΈ – нСльзя ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π΅.

Π‘Ρ‚Π°Ρ‚ΡŒΡ ΠΏΠΎ Ρ‚Π΅ΠΌΠ΅

10 Π·Π°ΠΏΠΎΠ²Π΅Π΄Π΅ΠΉ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈ тСстирования

ΠŸΡ€ΠΈΠ½Ρ†ΠΈΠΏ DRY Π² ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠ²

Π‘ΠΎΠ»ΡŒΡˆΠ°Ρ Ρ‡Π°ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ APISIX рСализуСтся Ρ‡Π΅Ρ€Π΅Π· ΠΏΠ»Π°Π³ΠΈΠ½Ρ‹, ΠΈ ΠΏΡ€ΠΈ ΠΈΡ… настройкС Ρ‚ΠΎΠΆΠ΅ Π²Π°ΠΆΠ½ΠΎ ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡƒ DRY. ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Π½ΡƒΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ вСрсионированиС API Π½Π° основС ΠΏΡƒΡ‚ΠΈ. Для этого Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ URI ΠΏΠ΅Ρ€Π΅Π΄ Π΅Π³ΠΎ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΎΠΉ:

-4

Π—Π΄Π΅ΡΡŒ Π΅ΡΡ‚ΡŒ Ρ‡Ρ‚ΠΎ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ – опСрация ΠΏΠΎ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΡŽ прСфикса дублируСтся. Π”ΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ, Ссли вынСсти ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ URI Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ plugin_configs:

-5

Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ upstream ΠΈ upstream_id, настройки plugins ΠΈ plugin_config_id Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π²Π·Π°ΠΈΠΌΠΎΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΌΠΈ – Π½Π°ΠΏΡ€ΠΎΡ‚ΠΈΠ², APISIX прСдусматриваСт ΠΈΡ… ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ΅ использованиС для раздСлСния ΠΎΠ±Ρ‰ΠΈΡ… настроСк ΠΈ спСцифичСских для ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°. ΠŸΡ€ΠΈ этом конфигурация ΠΏΠ»Π°Π³ΠΈΠ½Π° Π² ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ Π½Π°Π΄ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠ΅ΠΉ Π² plugin_config_id. НапримСр, ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠΌ key-auth ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ apikey Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ потрСбитСля, Π½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ для ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°.

πŸ’» Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста

Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста»