Перейти до основного вмісту

Публікації

Термінал на Android

Часто є необхідність користуватися теміналом на ОС Android. Наприклад, для підключення по SSH до сервера. Для цього є кілька можливостей. Розглянемо досить популярну із них - Termux Для початку потрібно встановити F-Droid: зайти на сайт f-droid.org/ , завантажити apk-файл та встановити його на свій смартфон. Власне після цього можна встановити Termux , скориставшись пошуком у F-Droid (F-Droid - це альтернатива Google Play Market). Після цього можна запускати програму і користуватися терміналом. Важливо розуміти, що у Termux не можна напряму використовувати apt-репозиторії Debian/Ubuntu. Але є власний репозиторій пакетів, адаптований під Android (ARM, sandbox, відсутність root тощо). Наприклад, оновлення пакетів: pkg upgrade Встановити git pkg install git Встановити JDK25 pkg install openjdk-25 У репозиторії Termux є кілька тисяч пакетів, зокрема: gcc / clang python nodejs rust go php nginx redis postgres openssh neovim tmux Налаштування, як сервера З допом...

Запуск Java-проєкту з вказаною JDK через maven

Інколи виникає потреба запустити java-проєкт з використанням іншої JDK/JRE, ніж встановлена по замовчуванню і налаштована в Maven. Якщо це разовий запуск (або інша дія), то змінювати налаштування може зайняти більше часу, ніж хотілося б. В такому випадку можна використати, наприклад, наступні команди (для JDK 17). Всі приклади - для операційної системи Ubuntu. Замість mvn clean install JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin:$PATH mvn clean install Запуск Spring Boot-проєкту: JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin:$PATH mvn spring-boot:run -Dspring-boot.run.profiles=local Як подивитися, які версії JDK встановлені, описано тут . Варто зауважити, що важливою є не лише дефолтна версія JDK, а й налаштування Maven. Подивитися поточне значення JAVA_HOME можна командою: echo $JAVA_HOME Змінити налаштування: nano ~/.bashrc Потрібно додати/змінити рядки на зразок: M2_HOME="/...

Робота з кількома аккаунтами GitHub

Інколи потрібно з однієї машини працювати з різними GitHub-аккаунтами, використовуючи різні облікові дані та ключі. Можна використати локальну конфігурацію на рівні репозиторію. Заходимо в репозиторій і вводимо: git config user.name "Company Dev" git config user.email "your.corp.email@company.com" або відповідно git config user.name "Your Name" git config user.email "your.personal.email@gmail.com" Перевірити налаштування: git config --show-origin user.name git config --show-origin user.email Використання двох SSH-ключів (для GitHub/GitLab/Bitbucket). Всі наступні команди для Linux (Ubuntu). ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_personal ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_corporate Отримати публічний ключ: cat ~/.ssh/id_ed25519_personal.pub Цей код потрібно додати у відповідний аккаунт у GitHub (GitLab/Bitbucket). Для цього перейти в https://github.com/settings/keys Налаштовуємо конфігурацію: nano ~/.ssh/config І д...

Error Handling в Node.js

Error Handling у Node.js vs Java У Java ми звикли до checked та unchecked exceptions, блоків try-catch-finally, та Spring'івських @ExceptionHandler. JavaScript має інший підхід до обробки помилок, особливо в асинхронному коді. // Java - знайомий підхід try { User user = userService.getUser(id); processUser(user); } catch (UserNotFoundException e) { logger.error("User not found", e); } catch (Exception e) { logger.error("Unexpected error", e); } finally { cleanup(); } // JavaScript/TypeScript - схожий синтаксис, різна семантика try { const user = await userService.getUser(id); await processUser(user); } catch (err) { if (err instanceof UserNotFoundError) { logger.error('User not found', err); } else { logger.error('Unexpected error', err); } } finally { cleanup(); } Ключова відмінність: У JavaScript немає checked exceptions. Всі помилки unchecked, компіл...

Callbacks, Promises, async/await в Node.js

Node.js однопотоковий і використовує неблокуючий I/O. Замість створення нових потоків, Node.js реєструє callback-функції, які викликаються, коли операція завершується. Це схоже на CompletableFuture у Java, але є основним способом роботи. 1. Callbacks: Перший підхід до асинхронності Callback — це функція, яку ви передаєте як аргумент і яка викликається після завершення операції. У Java це можна порівняти з передачею Consumer або Function як параметра. // Node.js - callback pattern import fs from 'fs'; // Error-first callback convention fs.readFile('user.json', 'utf8', (err, data) => { if (err) { console.error('Помилка читання файлу:', err); return; } console.log('Дані:', data); }); console.log('Цей рядок виведеться ПЕРШИМ!'); Конвенція Error-First Callback: Перший параметр завжди помилка (або null), другий — результат. Це стандарт у Node.js. Приклад: HTTP-запит з call...

Event Loop в Node.js

Event Loop в Node.js: архітектура, фази, черги Event Loop — це серце асинхронності в Node.js. Якщо ви знайомі з Java, то знаєте про багатопотоковість та Thread Pool. Node.js працює інакше: замість створення окремих потоків для кожного запиту, він використовує єдиний потік і Event Loop для обробки всіх операцій. Порівняння з Java/Spring Boot Java/Spring Boot (традиційна модель): Кожен HTTP-запит обробляється окремим потоком з Thread Pool Якщо потік блокується на I/O операції (база даних, файл), він чекає Обмежена кількість потоків (наприклад, 200) = максимум 200 одночасних запитів Node.js (асинхронна модель): Один основний потік (Event Loop) I/O операції делегуються системі (libuv), потік не блокується Може обробляти тисячі одночасних підключень на одному потоці // Java - блокуючий виклик String data = readFile("file.txt"); // потік чекає System.out.println(data); /...

Рекурсія в Elixir

Рекурсія — це коли функція викликає саму себе. В Elixir, де немає циклів, рекурсія є основним способом обробки колекцій та повторюваних операцій. Проста рекурсія Базова рекурсивна функція складається з двох частин: базового випадку та рекурсивного виклику: # Факторіал defmodule Math do def factorial(0), do: 1 def factorial(n) when n > 0 do n * factorial(n - 1) end end Math.factorial(5) # 120 (5 * 4 * 3 * 2 * 1) # Сума списку defmodule ListHelper do def sum([]), do: 0 def sum([head | tail]) do head + sum(tail) end end ListHelper.sum([1, 2, 3, 4, 5]) # 15 Примітка: Базовий випадок (наприклад, порожній список або 0) запобігає нескінченній рекурсії. Проблема простої рекурсії Проста рекурсія створює стек викликів, що може призвести до переповнення пам'яті: # Неефективна рекурсія def factorial(5) 5 * factorial(4) 4 * factorial(3) 3 * factorial(2) 2 * facto...

Модулі в Elixir

Модулі — це основний спосіб організації коду в Elixir. Вони групують пов'язані функції разом і створюють простори імен, що дозволяє уникнути конфліктів імен та структурувати програму. Базове визначення модуля Модулі визначаються за допомогою ключового слова defmodule : # Простий модуль defmodule Greeting do def hello do "Привіт, світ!" end def hello(name) do "Привіт, #{name}!" end end # Виклик функцій модуля Greeting.hello() # "Привіт, світ!" Greeting.hello("Олексій") # "Привіт, Олексій!" Публічні та приватні функції Функції можуть бути публічними ( def ) або приватними ( defp ): defmodule Calculator do # Публічна функція - доступна ззовні def calculate(a, b, operation) do case operation do :add -> add(a, b) :subtract -> subtract(a, b) :multiply -> multiply(a, b) :divide -> divide(a, b) end ...

Анонімні функції в Elixir

Анонімні функції (lambda-функції) — це функції без імені, які можуть бути присвоєні змінним, передані як аргументи або повернуті з інших функцій. Вони є основою функціонального програмування в Elixir. Базовий синтаксис Анонімні функції створюються за допомогою ключових слів fn та end : # Проста анонімна функція add = fn a, b -> a + b end # Виклик анонімної функції (з крапкою!) result = add.(5, 3) # result = 8 # Функція без параметрів greet = fn -> "Привіт!" end greet.() # "Привіт!" # Багаторядкова функція calculate = fn x, y -> sum = x + y product = x * y {sum, product} end calculate.(4, 5) # {9, 20} Важливо: Для виклику анонімних функцій використовується крапка . перед дужками: func.(args) . Це відрізняє їх від іменованих функцій. Скорочений синтаксис (&) Elixir пропонує скорочений синтаксис для простих анонімних функцій за допомогою оператора & : ...

Шпаргалка по Docker та Docker Compose

Docker - Робота з образами Завантаження образу docker pull nginx docker pull nginx:latest docker pull nginx:1.21 Список локальних образів docker images docker image ls Видалення образу docker rmi nginx docker rmi nginx:1.21 docker image rm nginx Видалення всіх невикористовуваних образів docker image prune docker image prune -a Побудова образу з Dockerfile docker build -t myapp:1.0 . docker build -t myapp:latest -f Dockerfile.prod . Тегування образу docker tag myapp:1.0 myapp:latest docker tag myapp:1.0 myregistry.com/myapp:1.0 Відправлення образу в registry docker push myregistry.com/myapp:1.0 Docker - Робота з контейнерами Запуск контейнера docker run nginx docker run -d nginx docker run -d --name mynginx nginx docker run -d -p 8080:80 nginx docker run -d -p 8080:80 -v /host/path:/container/path nginx docker run -d -e MY_VAR=value ...