Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу Знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Приложения на Swift могут быть массивными из-за нескольких факторов:
Включает много функций и структур данных, что увеличивает размер бинарного файла.
Современные приложения часто используют множество внешних библиотек и фреймворков, добавляющих объем.
Компиляция для разных архитектур (например, arm64, x86_64) увеличивает размер исполняемого файла.
Большое количество изображений, видео и аудиофайлов увеличивают размер приложения.
Включение символов отладки для разработки и анализа сбоев добавляет объем.
Статические библиотеки увеличивают размер исполняемого файла по сравнению с динамическими.
Поддержка старых версий iOS требует включения дополнительных библиотек и кода.
Использование инструментов для удаления лишних архитектур из финальной сборки.
Сжатие изображений и видео, использование эффективных форматов.
Исключение символов отладки в релизной сборке.
Использование динамических библиотек для уменьшения размера основного исполняемого файла.
Удаление неиспользуемого кода и зависимостей.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
PO вызывает методы description или debugDescription, которые могут изменять состояние объекта.Тяжелые вычисления в методах
description или debugDescription могут замедлить отладку.Доступ к объекту в многопоточной среде может привести к состоянию гонки.
Ошибки в методах
description или debugDescription могут привести к сбоям при использовании PO.Методы, использующие блокировки, могут привести к зависанию отладчика.
Побочные эффекты
class DangerousObject {
var counter = 0
var description: String {
counter += 1 // Изменение состояния
return "Counter: \(counter)"
}
}Производительность
class HeavyObject {
var description: String {
let result = (0..<1_000_000).map { $0 * $0 }.reduce(0, +)
return "Result: \(result)"
}
}Проблемы с потоками
class ThreadUnsafeObject {
var data = [Int]()
var description: String {
return "Data count: \(data.count)"
}
}Краш приложения
class CrashObject {
var description: String {
fatalError("Should not be called")
}
}Зависания
class LockObject {
let lock = NSLock()
var description: String {
lock.lock()
defer { lock.unlock() }
return "Locked"
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это текстовый протокол для общения в реальном времени. Он позволяет пользователям обмениваться сообщениями в каналах (чат-румах) или через личные сообщения.
Объединяют пользователей для обсуждения общих тем.
Прямой обмен сообщениями между пользователями.
Поддерживают несколько каналов и управляют соединениями пользователей.
Программы, используемые для подключения к IRC-серверам и участия в чатах.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Механизм синхронизации
Synchronized под капотом обеспечивает контроль доступа к критическим секциям кода в многопоточных приложениях, предотвращая состояние гонки и гарантируя, что только один поток в данный момент времени имеет доступ к определенному ресурсу.Различные механизмы синхронизации реализуют
Synchronized по-разному, но общая идея заключается в использовании блокировок (локов), чтобы обеспечить эксклюзивный доступ к ресурсу.Это простая блокировка, предоставляемая Foundation framework в Swift:
class ThreadSafeClass {
private var internalState = 0
private let lock = NSLock()
func increment() {
lock.lock()
internalState += 1
lock.unlock()
}
func getState() -> Int {
lock.lock()
let state = internalState
lock.unlock()
return state
}
}DispatchQueue позволяет организовать выполнение кода в синхронном или асинхронном режиме. class ThreadSafeClass {
private var internalState = 0
private let queue = DispatchQueue(label: "com.example.threadSafeQueue")
func increment() {
queue.sync {
internalState += 1
}
}
func getState() -> Int {
return queue.sync {
internalState
}
}
}Эти функции используются для синхронизации в Objective-C и могут быть использованы в Swift.
class ThreadSafeClass: NSObject {
private var internalState = 0
func increment() {
objc_sync_enter(self)
internalState += 1
objc_sync_exit(self)
}
func getState() -> Int {
objc_sync_enter(self)
let state = internalState
objc_sync_exit(self)
return state
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
Выделения в программировании касаются процессов управления памятью, когда память выделяется (аллоцируется) и освобождается (деаллоцируется) для использования программой. В современных языках программирования эти процессы могут быть управляемыми вручную или автоматически.
Статическая аллокация: Память выделяется во время компиляции и существует на протяжении всего времени выполнения программы. Используется для глобальных и статических переменных.
int globalVar = 10; // Статическая память
Стековая аллокация: Память выделяется при вызове функции и освобождается при выходе из функции. Используется для локальных переменных.
void function() {
int localVar = 20; // Стековая память
}Куча (динамическая аллокация): Память выделяется по запросу во время выполнения программы и освобождается вручную (в языках с ручным управлением памятью) или автоматически (в языках с автоматическим управлением памятью, например, через сборщик мусора).
int *ptr = (int*)malloc(sizeof(int) * 10); // Выделение памяти в куче
free(ptr); // Освобождение памяти
Вручную: Программист отвечает за освобождение памяти, выделенной в куче.
free(ptr);
Автоматически: Сборщик мусора (Garbage Collector) автоматически освобождает память, которая больше не используется.
// В Java нет необходимости освобождать память вручную.
C/C++ (ручное управление памятью):
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int*)malloc(sizeof(int) * 5); // Выделение памяти
if (arr == NULL) {
// Ошибка выделения памяти
return 1;
}
// Использование массива
for (int i = 0; i < 5; i++) {
arr[i] = i;
}
// Освобождение памяти
free(arr);
return 0;
}
Python (автоматическое управление памятью):
def create_list():
my_list = [i for i in range(5)] # Выделение памяти автоматически
return my_list # Память освобождается автоматически, когда объект больше не используется
my_list = create_list()
print(my_list)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1🤔1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
Это система документирования, которая используется для описания кода на языке JavaScript. Она позволяет разработчикам комментировать свой код специальными метками и описаниями, что облегчает его понимание и поддержку. Одной из самых популярных систем документирования в JavaScript является JSDoc.
JSDoc позволяет автоматически создавать HTML-документацию из аннотированных комментариев в коде.
JSDoc позволяет описывать типы данных параметров и возвращаемых значений функций.
JSDoc используется для документирования всех аспектов кода, включая функции, методы, классы и модули.
/**
* Adds two numbers together.
* @param {number} a - The first number.
* @param {number} b - The second number.
* @returns {number} The sum of the two numbers.
*/
function add(a, b) {
return a + b;
}
/**
* Represents a person.
* @class
*/
class Person {
/**
* Creates a person.
* @param {string} name - The name of the person.
* @param {number} age - The age of the person.
*/
constructor(name, age) {
this.name = name;
this.age = age;
}
/**
* Greets someone.
* @param {string} [greetName='Stranger'] - The name of the person to greet.
* @returns {string} The greeting message.
*/
greet(greetName = 'Stranger') {
return `Hello, ${greetName}! My name is ${this.name}.`;
}
}
@param — Описание параметров функции.@returns — Описание возвращаемого значения функции.@class — Описание класса.@constructor — Описание конструктора класса.@typedef — Описание типа данных.Комментарии JSDoc помогают другим разработчикам быстрее понять структуру и назначение кода.
Генерация документации упрощает поддержание актуальности документации и кода.
Некоторые инструменты могут использовать JSDoc для улучшения статического анализа кода, предоставляя более точные подсказки и проверки типов.
Для генерации документации с использованием JSDoc требуется установить и использовать инструмент командной строки JSDoc.
npm install -g jsdoc
jsdoc yourJavaScriptFile.js
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔4❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Да, в JavaScript, а также в других языках программирования, концепция Event Emitter (или Event Dispatcher) используется для работы с событиями и позволяет компонентам взаимодействовать друг с другом, подписываясь на события и реагируя на них. В JavaScript это часто реализуется с использованием колбэков.
В JavaScript Event Emitter часто используется с помощью библиотеки
events, которая встроена в Node.js. Вот как это работаетconst EventEmitter = require('events');
const eventEmitter = new EventEmitter();
// Подписка на событие 'event'
eventEmitter.on('event', (message) => {
console.log(`Received event with message: ${message}`);
});// Инициация события 'event'
eventEmitter.emit('event', 'Hello, World!');
В браузере события также часто обрабатываются с использованием колбэков через API, такие как
addEventListener.const button = document.getElementById('myButton');
// Подписка на событие 'click'
button.addEventListener('click', () => {
console.log('Button clicked!');
});// Инициация события 'click'
button.click();
Можно создать собственный класс EventEmitter, который будет использовать колбэки для обработки событий.
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
}
emit(event, ...args) {
if (this.events[event]) {
this.events[event].forEach(listener => listener(...args));
}
}
off(event, listener) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(l => l !== listener);
}
}
}
// Использование:
const emitter = new EventEmitter();
// Подписка на событие
emitter.on('message', (msg) => {
console.log(`Message: ${msg}`);
});
// Инициация события
emitter.emit('message', 'Hello, Event Emitter!');Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯4❤2😁1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это подход к разработке, который фокусируется на моделировании доменной области. Вот основные признаки, по которым можно отличить DDD в приложении:
Ubiquitous Language: Общий язык, используемый всей командой.
Доменные объекты: Сущности, значимые объекты, агрегаты, доменные события.
Доменный слой: Содержит модели, агрегаты, репозитории, доменные сервисы.
Слой приложений: Управляет потоками работы и координирует доменные объекты.
Инфраструктурный слой: Реализация репозиториев, доступ к базам данных.
Презентационный слой: Взаимодействие с пользователем.
Репозитории: Обеспечивают доступ к агрегатам.
Фабрики: Управляют созданием сложных объектов.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Да, Promises часто используются в JavaScript для управления асинхронными операциями, но они сами по себе не пишутся на колбеках. Вместо этого Promises используются как альтернатива колбекам, чтобы упростить управление асинхронным кодом и сделать его более читаемым и предсказуемым. Вот как можно использовать Promises вместо колбеков для управления асинхронным кодом:
function fetchData(callback) {
setTimeout(() => {
callback("Data received");
}, 1000);
}
fetchData((data) => {
console.log(data); // "Data received"
});function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received");
}, 1000);
});
}
fetchData().then((data) => {
console.log(data); // "Data received"
});Promises помогают избежать вложенности колбеков (callback hell), делая код более линейным и читаемым.
Promises обеспечивают единый механизм обработки ошибок с помощью
.catch(), что упрощает отладку.Promises поддерживают цепочки вызовов (
.then()), что упрощает выполнение последовательных асинхронных операций.Современный синтаксис JavaScript включает
async/await, который еще больше упрощает работу с асинхронным кодом на основе Promises, делая его похожим на синхронный код.function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received");
}, 1000);
});
}
async function fetchDataAsync() {
try {
const data = await fetchData();
console.log(data); // "Data received"
} catch (error) {
console.error(error);
}
}
fetchDataAsync();Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1😁1
В Domain-Driven Design (DDD) управление зависимостями важно для создания четко разделенных и легко управляемых компонентов. Это достигается следующими методами:
Инъекция зависимостей позволяет передавать зависимости через конструкторы или сеттеры, снижая связанность и упрощая тестирование.
interface UserRepository {
findById(id: string): Promise<User | null>;
}
class UserService {
private userRepository: UserRepository;
constructor(userRepository: UserRepository) {
this.userRepository = userRepository;
}
public async getUserById(id: string): Promise<User | null> {
return await this.userRepository.findById(id);
}
}Сервисы домена содержат бизнес-логику, не принадлежащую конкретным сущностям или значимым объектам, и могут взаимодействовать с несколькими объектами или внешними сервисами.
class PaymentService {
private paymentGateway: PaymentGateway;
constructor(paymentGateway: PaymentGateway) {
this.paymentGateway = paymentGateway;
}
public async processPayment(order: Order): Promise<boolean> {
return await this.paymentGateway.charge(order.totalAmount);
}
}Анти-коррупционные слои защищают доменную модель от внешних влияний и преобразуют данные в понятные форматы.
class ExternalUserService {
public getUserData(id: string): ExternalUser {
// Получение данных от внешнего сервиса
}
}
class UserService {
private externalUserService: ExternalUserService;
constructor(externalUserService: ExternalUserService) {
this.externalUserService = externalUserService;
}
public getUser(id: string): User {
const externalUser = this.externalUserService.getUserData(id);
return new User(externalUser.id, externalUser.name, externalUser.email);
}
}Контейнеры управляют созданием и жизненным циклом зависимостей, упрощая конфигурацию и разрешение зависимостей.
import "reflect-metadata";
import { Container, injectable, inject } from "inversify";
@injectable()
class UserRepositoryImpl implements UserRepository {
public async findById(id: string): Promise<User | null> {
// Реализация метода
}
}
@injectable()
class UserService {
private userRepository: UserRepository;
constructor(@inject("UserRepository") userRepository: UserRepository) {
this.userRepository = userRepository;
}
public async getUserById(id: string): Promise<User | null> {
return await this.userRepository.findById(id);
}
}
// Конфигурация контейнера
const container = new Container();
container.bind<UserRepository>("UserRepository").to(UserRepositoryImpl);
container.bind<UserService>(UserService).toSelf();
// Разрешение зависимостей
const userService = container.get<UserService>(UserService);
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2