Що таке програмування: доступне пояснення для абсолютних новачків [*]


Ця стаття не є повноцінним керівництвом по програмуванню на одній з відомих мов. Цей переклад служить в якості введення у базові концепції програмування. Для кого написана стаття:

  1. Для тих, хто зацікавлений в програмуванні, але не знає, як почати і чи слід продовжувати.
  2. Для тих, хто працює безпосередньо з програмістами і бажає зрозуміти основи того, що вони роблять.
  3. Для тих, хто тільки почав свій шлях в програмуванні і хоче познайомитися з базовими поняттями.
  4. Для тих, хто бачив програмістів тільки у фільмах і не уявляє, що вони роблять насправді.

Комп’ютерна програма

Комп’ютерна програма (вона ж додаток) – зв’язка численних рядків спеціального тексту. Він є спеціальним, тому що створений так, щоб машині було зрозуміло, які дії мають бути виконані. Найпростіші застосування містять близько ста рядків коду, а в складних і масштабних застосуваннях кількість рядків коду доходить до мільярда.

Комп’ютерний код – це спеціальний текст, що складається з набору покрокових інструкцій. Він не завжди містить в собі нулі і одиниці, також в нім є певні слова і додаткові символи. Комп’ютер прочитує код, який повідомляє його, які операції слід виконати з даними. Ви знайомі з Twitter? Уявіть, що Twitter – одна велика квартира, в якій розташовані мільйони комп’ютерів, що зберігають ваші твіти і вашу дату народження (день народження), як і твіти, і дати народження мільйонів інших користувачів.

Все ці твіти і дати – дані. Проте, комп’ютери не обробляють і не перечитують ваші твіти увесь час. Навіть якщо б вони перечитували ваші твіти, повірте, їм було б боляче. Комп’ютер починає обробляти і витягати код, коли ви входите в Twitter. У цей момент він завантажує з серверів ті дані, які користувачі внесли на сайт: твіти, дати народження. Ці дії виконуються в тому порядку, який прописаний в коді, комп’ютер слідує прописаним інструкціям подібно до того, як кухар слідує рецепту.

Якщо інструкції добре продумані, то все відносно добре працюватиме. Чому відносно? Розробникам часто доводиться шукати і виправляти баги (помилки) в проектах, навіть попри те, що вони робочі. Адже баг може перетворитися на велику уразливість.

Якщо в інструкціях буде який-небудь недолік, наприклад, друкарська помилка або неправильне тлумачення даних, то додаток працюватиме нестабільно або не запускатиметься взагалі, показуючи повідомлення про помилку.
Пам’ятайте, не так складно писати код, як уміти терпіти і приймати усі невдачі й провали, з якими вам, поза сумнівом, доведеться зіткнутися. Можете узяти приклад в плані терпіння з програмістів з Індії: їх код не завжди хороший, але їх оптимізму можуть позаздрити багато новачків, які розчарувалися в собі.

Одна з найцікавіших і захоплюючих частин програмування – рішення різних завдань і проблем, які є щось подібне до пазлу або головоломки. Але це здасться цікавим тільки тоді, коли ви розберетеся в коді і почнете розуміти його.

Набір інструментів для роботи

Інструментарій типового програміста найчастіше складається з наступних речей:

  • комп’ютер;
  • інтернет (передусім він потрібний для пошуку усього невивченого і невідомого у будь-якому з відомих пошукових сервісів);
  • редактор коду (чи IDE – комплекс програмних засобів, використовуваний програмістами для розробки програмного забезпечення), який допоможе упорядкувати все, що ви створюєте;
  • компілятор або інтерпретатор. Це програма, яка читає ваш код і намагається знайти в ньому помилки. Потім він збирає ваш код в єдиний пакет і передає комп’ютеру для виконання;
  • навушники. Можливо, вас відволікатимуть зовнішні шуми, а навушники – один з простих способів захистити себе від шумів.

Ви можете використати вільне програмне забезпечення для початку роботи з кодом. Таким є Atom і Notepad++. Ви також можете спробувати SublimeText, проте цей редактор є платним програмним забезпеченням.

Мови програмування

У світі існує більше тисячі різних мов програмування. Багато з них трохи менше, ніж повністю даремні. У вас може бути чудова кар’єра, якщо ви володієте 3-4 мовами програмування. Але не лякайтеся, вони не такі складні, як людські мови.
Мови програмування частенько описуються своєю парадигмою, яка є способом категоризації видів функцій. Наприклад, JavaScript – мова, яка може бути запущена у будь-якому веб-браузері, також вона заслужено займає лідируючі позиції в рейтингу популярності. Вона має різноманітний набір функцій: підтримує імперативні парадигми, що структуруються, об’єктно-орієнтовані і керовані подіями. Поки що це може звучати дивно для вас, але якщо ви заглибитеся в мови програмування, то зрозумієте, що означають усі ці поняття.

У мов програмування є одна особливість – якщо дві мови мають схожість в парадигмах, то, як правило, вони схожі і в синтаксисі. Після вивчення JavaScript ви зможете зрозуміти до 75 % коду на Python або Ruby, оскільки вони схожі.

Введення в програмування на основі JavaScript

З цієї миті використовуватиметься мова програмування JavaScript для наведення конкретних прикладів.

Зразки коду будуть надруковані спеціальним непропорційним шрифтом і виділені в рамки. Непропорційний шрифт зрівнює кеглеві майданчики для кожної букви. Так задумано, щоб полегшити розробникам пошук помилок в командах. Як приклад давайте розглянемо наступні зображення:

Пропорційний текст

Непропорційний текст

У пропозиціях є присутніми наступні помилки: зайвий пропуск після слова for, зайвий апостроф після слова Alice, а також пропущена буква в слові without. Можливо, ви усі помилки помітили відразу, але звернете увагу, що їх простіше помітити на другій картинці, де розташований непропорційний текст.

Робота з даними в коді

Давайте перейдемо до практичної частини і спробуємо написати який-небудь код. Основним елементом в комп’ютерній програмі є змінна, яка у свою чергу визначає ім’я для якої-небудь інформації, будь то число або текст. Завжди треба давати назви даним.
Існує дві головні причини, по яких слід іменувати дані:

  1. Вам частенько не відомо, що ховатиметься під змінною. Наприклад, Facebook не знає, коли у вас день народження, тому він використовує змінну із загальною назвою donalds_birthday для позначення дати або позначення її відсутності. (Змінні не можуть містити пропуски, тому слід розмежовувати слова іншими символами.) Змінна привласнюється будь-якій даті, яку ви введете, і далі програма продовжує використати ваші дані, приховуючи їх за змінною.
  2. Вам може бути складно згадати, що означає та або інша змінна. Наприклад, треба вказати комп’ютеру, що 86-е грудня не є реальною датою. Отже, ми де-небудь повинні вказати, що в грудні 31 день. Але 31 – це число (дані), тому якщо ви використовуватимете 31 в усьому своєму коді, щоб таким чином позначити кількість днів цього місяця, то одного разу заплутаєтеся. Адже у нас існують інші місяці. Таким чином, можна присвоїти числу 31 ім’я the_number_of_days_in_december. Тепер ви точно не заплутаєтеся. Відмінно, йдемо далі!

Примітка у назвах змінних не можна використати апострофи.

Щоб змінна існувала, її треба оголосити. Оголошення змінних служить в ролі свідоцтва про “народження” для даних. Давайте подивимося на приклад:

var the_number_of_days_in_december

Ключове слово var означає змінну (скорочення від variable). Використання скорочень прискорює роботу з кодом.

Також змінної треба присвоїти значення:

var the_number_of_days_in_december = 31

Все дуже просто. Оголошуєте змінну, привласнюєте їй значення і використовуєте скрізь в коді, наприклад, the_number_of_days_in_december замість числа 31.

Слід пам’ятати, що ви також можете оголошувати змінні для даних, які ще не існують. Давайте повернемося до прикладів. Ви можете оголосити var donalds_birthday і повідомити додаток, щоб він чекав введення значення. Все, що буде введено користувачем для цієї змінної, використовуватиметься в тексті під ім’ям donalds_birthday.

Змінні можуть містити не лише дати і числа. Наприклад, ви можете оголосити цілий рядок або фрагмент тексту :

var great_song_lyrics = 'pasito a pasito, suave suavecito'

Тепер можна де завгодно в коді написати great_song_lyrics і комп’ютер зрозуміє, що йдеться о 'pasito a pasito, suave suavecito'.

Як щодо перевірки цих тверджень? Давайте протестуємо все, що було сказано вище. Відкрийте консоль в Google Chrome натисненням клавіші F12 (для власників Mac рекомендується ознайомитися з цією статтею). Перед вами з’явиться наступне вікно:

Переконайтеся, що вибрана вкладка ” Console”, кликніть на порожньому полі поряд зі знаком “більше” (>), оголосіть змінну і присвойте їй значення, а потім натисніть клавішу введення.

У консолі відображається повідомлення undefined через те, що рядок коду не вивів які-небудь дані, чого, власне, робити і не повинен. Тепер введіть назву своєю змінної в рядок і натисніть кнопку введення.

Прийміть поздоровлення! Консоль (яка також служить в ролі інтерпретатора) розуміє вашу змінну. Її значення було виведене у вигляді тексту, який ви їй присвоїли. До речі, ви могли помітити, що були використані одинарні лапки, але ви також можете використати подвійні. Тільки не змішуйте їх (т. е. не слід робити “так”).

Багато мов програмування вимогливі до конкретної інформації про те, яку саме змінну ви оголошуєте. Наприклад, в C++ ключове слово var відсутнє. У C++ слово int використовується для оголошення невеликих цілих чисел; long використовується для оголошення великих цілих чисел; float і double використовуються для оголошення десяткових чисел, а string використовується для оголошення тексту. Але поки що вам не варто в це вникати, ви зможете детальніше ознайомитися з C++ пізніше.

Комплексні типи даних

Об’єкти

Важливою частиною розробки коду є вивчення організації даних. Візьмемо, наприклад, Facebook. Соціальна мережа зберігає сотні мільйонів записів про дні народження (і інших датах), які зберігаються на серверах. Але як алгоритм розуміє, до чого та або інша дата відноситься, і для чого вона взагалі вказана? Давайте розберемося в цьому.

Facebook не просто зберігає мільйони довільних дат, він зв’язує усі ваші дані з унікальним ідентифікатором (id). Можете провести аналогію з паспортом. Усі дані про прописку, вік, ім’я і статеву приналежність прив’язуються до номера паспорта, по якому вас можуть ідентифікувати. Те ж саме відбувається при створенні облікового запису в Facebook. Для соціальної мережі ви є користувачем під яким-небудь випадковим (чи не дуже) номером.

У Javascript об’єкти оголошуються майже так само, як і змінні:

var human ={ id: 12884002, age: 28, name: 'Bob', favorite _song: 'Photograph, by Nickelback'}

Насправді, все, що ми зробили – це оголосили чотири змінні: два числа і два рядки. Але усі вони організовані разом, тому ми зможемо знайти їх, коли захочемо упізнати що-небудь о human. Все, що ви бачите у фігурних дужках, розмежовується на дві частини: ліворуч прописуються поля, а справа вказуються властивості для них. Об’єкт може мати будь-які властивості до тих пір, поки вони знаходяться усередині {фігурних дужок}.

Ми можемо використати об’єкт human і посилатися на нього точно так, як і на будь-яку іншу змінну. Комп’ютер зрозуміє, що треба послатися на яку-небудь певну властивість, якщо ми його напишемо через точку:

human.idhuman.namehuman.agehuman.favorite_song

Кожен з елементів згори може бути змінений і посилатися на іншу властивість. Наприклад, давайте змінимо ім’я (name) :

human.name = 'Alice'

Масиви

Іноді у вас може не бути бажання придумувати унікальне ім’я для кожної властивості об’єкту, особливо, якщо вони усі дуже схожі або ви не знаєте скільки об’єктів буде. Ось тоді і приходить час для використання масивів, які є списком схожих фрагментів даних. Масиви можуть збільшуватися або зменшуватися, залежно від необхідності.

Хорошим прикладом є Twitter. Йому не відомо, скільки твітів ви збираєтеся написати. Ви розпочинаєте з нуля і продовжуєте їх писати більше і більше. Twitter використовує масиви для зберігання записів. У JavaScript масиви виглядають таким чином:

var tweets =['Hello, Twitter!', 'My friends are so cool', 'Does anyone want a LaCroix?']

Пам’ятайте, як використовуються об’єкти в {фігурних дужках}. Зараз ми працюємо з масивами, і для них прийнято використовувати [квадратні дужки]. Даний масив має три рядки, розділені комами. І так, це також можна вважати чимось на зразок змінної. Ви можете використати tweets у будь-якому місці вашого коду, посилаючись на масив, який тільки що був визначений.

Примітка Рахунок масивів розпочинається з нуля, але не з одиниці.

Якщо ви хочете звернутися до якогось окремому твіту, то можна зробити наступне:

tweets[0]tweets[1]tweets[2]

У прикладі вище використовується ім’я масиву tweets, а потім усередині квадратних дужок ми пишемо номер (індекс) твіту (елементу), до якого бажаємо звернутися.

Кожен з приведених вище виразів – змінна. Ви можете присвоїти їм яке-небудь нове значення, щоб поекспериментувати:

tweets[2] = 'I regret literally everything I have ever said'

Що сталося з попереднім значенням? Правильно! Воно було замінене на нове, тепер tweets[2] посилатиметься на нове значення.

Масиви можуть містити текст, числа, дати, об’єкти і навіть інші масиви. Ви можете помістити масиви усередині масивів, які, у свою чергу, містять масиви.

Масиви також можуть бути властивостями об’єктів. Об’єкт може мати властивість, яка є масивом об’єктів. Звучить, немов опис матрьошки, але саме так і структуруються дані.

var nested_object ={ an _array: [ { another _array: [ { yet _another: [ { message: 'Blink twice if you need help'} ] } ] } ]}

Щоб звернутися до message, ви можете написати наступне:

nested_object.an_array[0].another_array[0].yet_another[0].message

І комп’ютер зрозуміє, що ви маєте на увазі 'Blink twice if you need help'

Об’єкти (продовження)

У JavaScript все трішки є об’єктами. Наприклад, наші твіти tweets мають властивість, яку ми ніколи не оголошували :

tweets.length

Що таке length? Це довжина нашого масиву. У ньому міститься три елементи. Ця властивість оновлюється автоматично.

API

API – набір властивостей і методів (цільових фрагментів коду), які мають свої імена, як змінні. Ви можете посилатися на них по імені і дозволяти їм працювати.

Масиви JavaScript також мають свій власний API. Властивість length є частиною цього API. Інша його частина – метод push, який додає елементи в кінець масиву :

tweets.push ('Man I hate good attitudes')

Метод схожий на властивість, тому що до нього можна отримати доступ через точку. Він відрізняється від властивості тим, що після нього треба поставити (круглі дужки). У цих круглих дужках зберігаються дані, які ми хочемо додати в наш масив. Тепер в tweets чотири елементи. Це виглядає ось так:

['Hello, Twitter!', 'My friends are so cool', 'I regret literally everything I have ever said', 'Man I hate good attitudes']

Проте пам’ятайте, що вам слід починати рахувати елементи з нуля. Тому індексом останнього елементу буде 3 – tweets[3].

У API JavaScript існує безліч різних методів, але до них ви вже дійдете самі, коли прийде час. Але на дозвіллі можете ознайомитися з ними по посиланню.

У сучасних браузерів є величезний API, який розробники JavaScript використовують майже щодня. У цього API є методи для різних завдань: для веб-анімації, для призначеного для користувача введення, для з’єднання комп’ютера з іншими пристроями в Мережі, а також для інших завдань. Створення власної шпаргалки для конкретного API – невід’ємна частина становлення веб-розробника.

Функції

Функція – ще одно назва методу. Це усього лише фрагмент коду, який щось виконує і має ім’я. Функції можна легко оголошувати:

function giveMeOne (){ return 1}

Оголошення функції розпочинається з ключового слова, потім їй дається ім’я. Схоже на змінну, чи не так? У прикладі вище використовуються заголовні букви для розмежування слів. Потім фігурні дужки, усередині яких записаний код, який треба буде витягнути при виклику функції.

Слово return – ще одно ключове слово. Воно примушує значення ” вистрибувати” з функції. Потім функція завершується (якщо ви напишете код після return, те він не буде виконаний). Таким чином, ви можете зробити наступне:

var the_loneliest_number = giveMeOne ()

Не занадто складно, чи не так? Ми оголошуємо змінну з ім’ям the_loneliest_number. Частина нашої команди викликає функцію giveMeOne () і оскільки функція говорить return 1, виводиться одиниця. Наша змінна міститиме цифру 1. Тепер спробуйте ввести у браузері перший блок з функцією, потім блок зі змінною, а потім ввести the_loneliest_number і натиснути кнопку введення. Ви побачите одиницю.

Функція може бути властивістю об’єкту. Вона може бути елементом масиву. Вона може повертати число, дату, рядок, об’єкт, масив, іншу функцію, масив функцій і т. д. Це схоже на лего: помістите що завгодно у будь-якому місці, і воно підійде. Криво, але підійде.

Функція giveMeOne () схожа на tweets.push (). Основні відмінності:

  • giveMeOne () – функція, яка була створена нами, а push () – це функція, яку написав хтось, а не ми;
  • push () – метод масиву tweets (а так само будь-якого іншого масиву). giveMeOne () є глобальною, тому нам не треба посилатися на інші об’єкти, щоб використати її.

Як ви могли помітити, є ще одно невелика відмінність: giveMeOne () використовує порожні круглі дужки, а push () чекає, що ми введемо що-небудь усередині круглих дужок. Фактично, push () буде даремний, якщо ми нічого не додамо в наш масив. Частина даних, яку ми додаємо у функції, називається аргументом. Оголошення функції, яка може чекати аргументи, виглядає так:

function addTheseNumbersTogetherPlz (number1, number2) { return number1 + number2}

Ця функція не сильно відрізняється від giveMeOne (). У ній замість порожнечі в дужках записані імена змінних, розділені комою. Це наші аргументи. Оператор return складає number1 і number2, а потім видає результат. Можна було б жартома назвати це таким чином: addTheseNumbersTogetherPlz (3, 4) і було б виведено число 7.

Вам же подобається математика, чи не так? Майже в усіх мовах програмування ви можете писати математичні вирази так само, як і на калькуляторах.

Давайте подивимося, що можна зробити з “калькулятором” JavaScript:

+ використовується для складання;
- використовується для віднімання;
* використовується для множення;
(круглі дужки) служать для примусового виконання порядку операцій;
% використовується для отримання залишку ділення.

Ви могли б записати попередню функцію таким чином:

function addTheseNumbersTogetherPlz (number1, number2) { var sum = number1 + number2 return sum}

Ця функція робить все те ж, що і попередня, тільки в неї введена змінна в якості посередника.

Логічні гілки і порівняння

Комп’ютерні програми не виконують одну й ту ж дію при кожному запуску. Уявить, якби це було так, то ігри самі в себе грали б. Нудно, чи не так? Програми повинні реагувати на різні ситуації. Вони повинні приймати рішення.

Припустимо, ми пишемо додаток, який визначає, чи дозволено конкретній людині увійти до нічного клубу. Уявимо, що в JavaScript API є метод, який отримує вік користувача. Ми назвемо його getUserAge (). Також припустимо, що існують два інші методи: allowThemInTheNightClub () і throwThemOutOnTheirButt (). Як ми можемо допомогти нашій програмі вирішити, який з цих двох методів треба викликати, виходячи зі значення першого методу, що повертається?

var age = getUserAge () if (age >= 21) { allowThemInTheNightclub ()} else { throwThemOutOnTheirButt ()}

Ви вже знаєте, що робить перший рядок. age (вік) може варіюватися від 7 до 101. Тепер нам треба визначити більше значення age, чим 21 або ні. Якщо більше, то відвідувачі можуть розважатися, якщо ні, то повинні будуть покинути клуб.

Ми робимо це за допомогою оператора if(якщо) – ключового слова, схожого на метод. Аргумент, який він чекає, є якимсь вираженням (звичайне порівняння). Порівняння набувають два значення і порівнюють їх один з одним. Внаслідок чого вибирається одно з наступних ключових слів: true – у разі відповідності правилу і false – у разі невідповідності. Це називається логічним виразом.

У JavaScript є можливість 6 видів порівняння :
=== порівнює значення. Якщо вони однакові, то ви побачите true. Наприклад, 6 === 6 було б true;
!== порівнює значення на нерівність. Якщо вони не рівні, то ви побачите true. Наприклад, 6 !== 3 було б true;
> перевіряє, чи більше значення ліворуч. Якщо більше, то ви побачите true. Наприклад, 6 > 3 було б true;
< перевіряє, чи більше значення справа. Якщо більше, то ви побачите true. Наприклад, 3 < 6 було б true;
- >= перевіряє, більше або рівна права частина лівою. Якщо більше або рівна, то ви побачите true. Наприклад, вирази 6 >= 6 і 6 >= 5 були б true;
- <= перевіряє, менше або рівна права частина лівою. Якщо більше або рівна, то ви побачите true. Наприклад, вирази 6 <= 6 і 6 <= 7 були б true.

Оператор if оцінює порівняння. Якщо виводиться true, те код виконується усередині блоку порівняння. Якщо виводиться false, код не виконується і ігнорується.

Оператор if також може працювати з оператором else(те). Він містить в собі блок коду, який буде виконаний, якщо порівняння поверне false. Тепер погляньте знову на код, що відноситься до нічного клубу, і ви зрозумієте, як він працює (якщо ні, перечитайте цей фрагмент ще раз)

Цикли

Іноді, коли ви працюєте з масивом, вам може знадобитися виконати якийсь блок коду кілька разів підряд. У таких випадках слід використати цикли. Простим видом циклу JavaScript є while(поки):

var the_real_slim_shady =['My name is', 'My name is', 'My name is', 'Waka waka Slim Shadyyy']var index = 0while (index < the_real_slim_shady.length) { rap (the_real_slim_shady[index]) index = index + 1}

Цикл while використовує той же синтаксис, що і оператор if: йому використовуються круглі дужки, ви проходите через порівняння і т. д. Але блок if виконує код усередині тільки один раз, а блок while повторюється раз по раз. Він виконує умову до тих пір, поки воно не стане false . Якщо воно відповідає true, блок запускається знову і знову. Давайте ознайомимося з прикладом вище. Був використаний вигаданий API з методом rap (), але усе інше - справжній JavaScript.

Скільки разів виконуватиметься цикл? Що ж, вперше він оцінить порівняння і перевірить чи менше index (який дорівнює 0)чим the_real_slim_shady[0]. Якщо порівняння виведе true, те буде запущене цикл, оскільки index дорівнює нулю. З цієї миті цикл виконуватиметься до тих пір, поки блок index не дорівнюватиме 4, оскільки the_real_slim_shady[4] не існує, ви ж пам'ятаєте, що масиви розпочинаються з нуля, а не одиниці?

Null і Undefined

Якщо ви оголосите змінну і не присвоїте їй значення, то вона міститиме спеціальне значення undefined. Null значить, грубо кажучи, те ж саме. Мало хто знає, в чому різниця.

Сфери застосування

Функції дуже егоїстичні. Якщо ви оголосите змінну усередині функції, то ви не зможете нею скористатися де-небудь за межами функції. Приклад:

function whatHappensInVegas (){ var wildIndiscretions =['partied', 'danced'] return 'I admit nothing'}whatHappensInVegas () whatHappensInVegas () whatHappensInVegas () if (wildIndiscretions.length > 0) { getADivorce ()}

У нас дуже проста функція. У ній оголошена змінна wildIndiscretions. Світ за межами функції не знає про існування змінної. Навіть оператор if не може нічого зробити в цьому випадку. Оператор if спрацює тільки усередині функції, якщо помістити його перед return.

Коментування коду

Не завжди буває зрозуміло, що виконує той або інший код. Тому завжди слід коментувати свій код. Оскільки, можливо, вам доведеться працювати з ним знову, і ви не зможете щось згадати або ж іншим людям треба буде заглянути у ваш код. У JavaScript коментарі розпочинаються з двох слешів - //:

var age = 21{// змінна дорівнює 21.// Якщо вона не дорівнює 21, будь ласка, зміните на 21.// Що зробити: додати більше за змінних.}

Пропонуємо вам познайомитися з прикладами коментування коду в нашій спеціальній статті.

Висновок

Ви виконали хорошу роботу, якщо дійшли до кінця статті, з чим вас варто привітати. Тепер ви розумієте, що таке програмування на базовому рівні. Бажаємо вам успіхів на шляху до освоєння майстерності програмування.

Якщо ви розумієте, що JavaScript вам не підходить, або хочете вивчити іншу мову, але не можете зрозуміти, з чого варто починати новачкові, то пропонуємо вам ознайомитися з відповідями експертів з приводу вибору мови програмування.

Переклад статті "When you finish reading this, you'll know how to code"

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *