Frontend | Вопросы собесов
Сайт easyoffer.ru Реклама @easyoffer_adv ВП @easyoffer_vp Тесты t.me/+T0COHtFzCJkwMDUy Задачи t.me/+_tcX2w2EmvdmMTgy Вакансии t.me/+CgCAzIyGHHg0Nzky
Show more📈 Analytical overview of Telegram channel Frontend | Вопросы собесов
Channel Frontend | Вопросы собесов (@easy_javascript_ru) in the Russian language segment is an active participant. Currently, the community unites 18 272 subscribers, ranking 7 345 in the Technologies & Applications category and 36 940 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 18 272 subscribers.
According to the latest data from 15 June, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -134 over the last 30 days and by -7 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 9.73%. Within the first 24 hours after publication, content typically collects 5.72% reactions from the total number of subscribers.
- Post reach: On average, each post receives 1 778 views. Within the first day, a publication typically gains 1 046 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 9.
- Thematic interests: Content is focused on key topics such as ставь, браузер, html, border, flex.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Сайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp
Тесты t.me/+T0COHtFzCJkwMDUy
Задачи t.me/+_tcX2w2EmvdmMTgy
Вакансии t.me/+CgCAzIyGHHg0Nzky”
Thanks to the high frequency of updates (latest data received on 16 June, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
Repository в Service через конструктор.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Service {
private final Repository repository;
@Autowired
public Service(Repository repository) {
this.repository = repository;
}
public void performAction() {
repository.doSomething();
}
}
🟠Service Locator
Это шаблон проектирования, который предоставляет центральное место для получения зависимостей. Компоненты запрашивают зависимости у локатора служб, вместо того чтобы создавать их напрямую. Пример на Java:
public class ServiceLocator {
private static final Map<Class<?>, Object> services = new HashMap<>();
public static <T> void registerService(Class<T> serviceClass, T service) {
services.put(serviceClass, service);
}
public static <T> T getService(Class<T> serviceClass) {
return serviceClass.cast(services.get(serviceClass));
}
}
// Использование Service Locator
ServiceLocator.registerService(Repository.class, new RepositoryImpl());
Repository repository = ServiceLocator.getService(Repository.class);
repository.doSomething();
🚩Плюсы
➕Улучшение тестируемости
IoC позволяет легко заменять реальные зависимости на моки или стабы в тестах.
➕Уменьшение связности кода
Компоненты становятся менее зависимыми друг от друга, что упрощает их замену и модификацию.
➕Повышение гибкости и расширяемости
Легко добавлять новые зависимости или изменять существующие без изменения кода, использующего эти зависимости.
➕Явное управление зависимостями
Зависимости становятся явными, что улучшает понимание и документирование системы.
Ставь 👍 и забирай 📚 Базу знанийpublic class Service {
private final Repository repository;
public Service(Repository repository) {
this.repository = repository;
}
public void performAction() {
repository.doSomething();
}
}
🟠Внедрение через сеттеры
Зависимости передаются объекту через методы-сеттеры после его создания. Пример на Java:
public class Service {
private Repository repository;
public void setRepository(Repository repository) {
this.repository = repository;
}
public void performAction() {
repository.doSomething();
}
}
🟠Внедрение через интерфейсы
Зависимости передаются объекту через методы, определённые в интерфейсах. Пример на TypeScript:
interface IRepository {
doSomething(): void;
}
class Repository implements IRepository {
doSomething() {
console.log("Doing something...");
}
}
class Service {
private repository: IRepository;
constructor(repository: IRepository) {
this.repository = repository;
}
performAction() {
this.repository.doSomething();
}
}
const repository = new Repository();
const service = new Service(repository);
service.performAction();
🚩Плюсы
➕Улучшение тестируемости
Код становится более модульным и тестируемым, так как зависимости можно легко заменять на моки или стабы в тестах.
➕Улучшение поддерживаемости
Уменьшается связность кода, что упрощает его поддержку и модификацию.
➕Улучшение гибкости
Легче менять реализации зависимостей, не изменяя код, который их использует.
➕Явное указание зависимостей
Зависимости объектов становятся явными, что улучшает понимание кода.
🚩Минусы
➖Усложнение кода
Внедрение DI может усложнить код, особенно если используется слишком много уровней абстракции.
➖Кривая обучения
Понимание и правильное использование DI может потребовать времени и обучения, особенно для разработчиков, незнакомых с паттерном.
➖Перегрузка конструкции
При внедрении большого числа зависимостей через конструктор конструктор может стать перегруженным.
Ставь 👍 и забирай 📚 Базу знанийfrom Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
# Генерация ключа
key = get_random_bytes(16) # 16 байт = 128 бит
# Создание шифра
cipher = AES.new(key, AES.MODE_EAX)
# Шифрование данных
data = b'Secret message'
nonce = cipher.nonce
ciphertext, tag = cipher.encrypt_and_digest(data)
print(f'Ciphertext: {ciphertext}')
# Дешифрование данных
cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, tag)
print(f'Plaintext: {plaintext}')
🚩Асимметричная криптография
Использует пару ключей: открытый ключ и закрытый ключ. Открытый ключ используется для шифрования данных и может быть свободно распространяем, в то время как закрытый ключ используется для дешифрования и должен оставаться в секрете. Это решает проблему передачи ключей, так как отправитель может зашифровать данные открытым ключом получателя, а только получатель сможет расшифровать их с помощью своего закрытого ключа.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
# Генерация пары ключей
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
# Шифрование данных
message = b'Secret message'
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(f'Ciphertext: {ciphertext}')
# Дешифрование данных
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(f'Plaintext: {plaintext}')
🚩Сравнение симметричной и асимметричной криптографии
🟠Ключи
Симметричная: Один ключ для шифрования и дешифрования.
Асимметричная: Пара ключей — открытый для шифрования и закрытый для дешифрования.
🟠Безопасность
Симметричная: Требует безопасной передачи ключа, что может быть сложно.
Асимметричная: Обеспечивает безопасную передачу ключей через использование открытого ключа.
Ставь 👍 и забирай 📚 Базу знанийV(G) = E - N + 2P🚩Пример расчета цикломатической сложности
def example(a, b):
if a > 0:
if b > 0:
return a + b
else:
return a - b
else:
return b
Цикломатическая сложность V(G) будет
V(G) = E - N + 2P V(G) = 6 - 5 + 2*1 V(G) = 3🚩Почему синтаксическая сложность важна 🟠Понимаемость кода Чем выше сложность, тем труднее понять код. Программы с высокой сложностью требуют больше времени для анализа и понимания. 🟠Поддерживаемость Код с высокой сложностью сложнее поддерживать и изменять. Это может привести к большему числу ошибок при внесении изменений. 🟠Тестируемость Более сложный код требует большего количества тестов для покрытия всех возможных путей исполнения. Это увеличивает время и усилия, необходимые для тестирования. 🟠Надежность Программы с низкой сложностью, как правило, более надежны и менее подвержены ошибкам, так как легче понимать и тестировать все возможные сценарии. 🚩Методы уменьшения синтаксической сложности 🟠Рефакторинг Разделение сложных функций на более простые и малые функции. Использование более простых и понятных конструкций. 🟠Удаление дублированного кода Вынос повторяющегося кода в отдельные функции или методы. 🟠Использование комментариев и документации Добавление пояснительных комментариев и документации для сложных участков кода. 🟠Применение паттернов проектирования: Использование проверенных паттернов проектирования для упрощения и структурирования кода. Ставь 👍 и забирай 📚 Базу знаний
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Secure Form</title>
</head>
<body>
<form action="/submit" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username">
<label for="password">Password:</label>
<input type="password" id="password" name="password">
<button type="submit">Submit</button>
</form>
</body>
</html>
Ставь 👍 и забирай 📚 Базу знанийnpm install express jsonwebtoken bcryptjs body-parser
2⃣Создание сервера
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const bodyParser = require('body-parser');
const app = express();
const PORT = 3000;
const SECRET_KEY = 'your_secret_key';
let users = []; // Для простоты используем массив в памяти
app.use(bodyParser.json());
// Регистрация пользователя
app.post('/register', async (req, res) => {
const { username, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 8);
users.push({ username, password: hashedPassword });
res.status(201).send('User registered');
});
// Вход пользователя
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username);
if (!user) {
return res.status(404).send('User not found');
}
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(401).send('Invalid password');
}
const token = jwt.sign({ username: user.username }, SECRET_KEY, { expiresIn: '1h' });
res.json({ token });
});
// Защищенный маршрут
app.get('/protected', (req, res) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).send('Access denied');
}
try {
const decoded = jwt.verify(token, SECRET_KEY);
res.json({ message: 'Protected content', user: decoded });
} catch (err) {
res.status(401).send('Invalid token');
}
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Ставь 👍 и забирай 📚 Базу знанийexpress
const express = require('express');
const app = express();
let messages = [];
let clients = [];
// Endpoint для отправки сообщений
app.post('/messages', (req, res) => {
const message = req.body.message;
messages.push(message);
// Уведомляем всех клиентов
clients.forEach(client => client.res.json({ message }));
clients = [];
res.status(200).send('Message sent');
});
// Endpoint для получения сообщений (лонг-пулинг)
app.get('/messages', (req, res) => {
if (messages.length > 0) {
res.json({ message: messages.pop() });
} else {
clients.push({ req, res });
}
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
Клиентский код на JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Long Polling Example</title>
</head>
<body>
<h1>Long Polling Example</h1>
<div id="messages"></div>
<script>
function pollMessages() {
fetch('/messages')
.then(response => response.json())
.then(data => {
const messageDiv = document.createElement('div');
messageDiv.textContent = `New message: ${data.message}`;
document.getElementById('messages').appendChild(messageDiv);
pollMessages(); // Отправляем новый запрос после получения сообщения
})
.catch(error => {
console.error('Error:', error);
setTimeout(pollMessages, 5000); // Повторный запрос через 5 секунд при ошибке
});
}
// Начинаем лонг-пулинг
pollMessages();
</script>
</body>
</html>
🚩Плюсы
➕Реальное время
Лонг-пулинг позволяет получать данные в реальном времени без необходимости постоянно проверять сервер с частыми запросами.
➕Снижение нагрузки на сервер
По сравнению с обычным пулингом (когда клиент постоянно отправляет запросы с фиксированным интервалом), лонг-пулинг уменьшает количество HTTP-запросов, что снижает нагрузку на сервер.
➕Простота реализации
Лонг-пулинг легче внедрить и поддерживать в сравнении с более сложными технологиями, такими как WebSockets.
🚩Минусы
➖Задержка
Хотя лонг-пулинг уменьшает задержку по сравнению с обычным пулингом, он все же может иметь небольшие задержки в зависимости от времени ожидания и частоты событий.
➖Ресурсоемкость
Держание соединений открытыми в течение длительного времени может быть ресурсоемким для сервера, особенно при большом количестве клиентов.
➖Неоптимальность
Лонг-пулинг менее эффективен по сравнению с WebSockets, которые предоставляют постоянное двустороннее соединение.
Ставь 👍 и забирай 📚 Базу знаний
Available now! Telegram Research 2025 — the year's key insights 
