Frontend | Вопросы собесов
Сайт easyoffer.ru Реклама @easyoffer_adv ВП @easyoffer_vp Тесты t.me/+T0COHtFzCJkwMDUy Задачи t.me/+_tcX2w2EmvdmMTgy Вакансии t.me/+CgCAzIyGHHg0Nzky
Mostrar más📈 Análisis del canal de Telegram Frontend | Вопросы собесов
El canal Frontend | Вопросы собесов (@easy_javascript_ru) en el segmento lingüístico de Ruso es un actor destacado. Actualmente la comunidad reúne a 18 272 suscriptores, ocupando la posición 7 345 en la categoría Tecnologías y Aplicaciones y el puesto 36 940 en la región Rusia.
📊 Métricas de audiencia y dinámica
Desde su creación el невідомо, el proyecto ha mostrado un crecimiento acelerado, reuniendo a 18 272 suscriptores.
Según los últimos datos del 15 junio, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de -134, y en las últimas 24 horas de -7, conservando un alto alcance.
- Estado de verificación: No verificado
- Tasa de interacción (ER): El promedio de interacción de la audiencia es 9.73%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 5.72% de reacciones respecto al total de suscriptores.
- Alcance de las publicaciones: Cada publicación recibe en promedio 1 778 visualizaciones. En el primer día suele acumular 1 046 visualizaciones.
- Reacciones e interacción: La audiencia responde de forma activa: el promedio de reacciones por publicación es 9.
- Intereses temáticos: El contenido se centra en temas clave como ставь, браузер, html, border, flex.
📝 Descripción y política de contenido
El autor describe el recurso como un espacio para expresar opiniones subjetivas:
“Сайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp
Тесты t.me/+T0COHtFzCJkwMDUy
Задачи t.me/+_tcX2w2EmvdmMTgy
Вакансии t.me/+CgCAzIyGHHg0Nzky”
Gracias a la alta frecuencia de actualizaciones (últimos datos recibidos el 16 junio, 2026), el canal mantiene la vigencia y un amplio alcance. La analítica demuestra que la audiencia interactúa activamente con el contenido, lo que lo convierte en un punto de referencia dentro de la categoría Tecnologías y Aplicaciones.
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, которые предоставляют постоянное двустороннее соединение.
Ставь 👍 и забирай 📚 Базу знаний
¡Ya disponible! Investigación de Telegram 2025 — los principales insights del año 
