Search
Write a publication
Pull to refresh
2
0
Send message

Спасибо! Это то, что нужно для новичка. Я только начал изучать Go после 5 лет питона. Было очень интересно и сразу стало понятно, с чего можно начать, и что гуглить, чтобы сделать лучше.

У меня есть отличный опыт, как я, зная лишь python и Javascript, смог выучить C# при помощи вайб-кода.

По началу это действительно выглядит пугающе и интригующе, ты просто берёшь и вставляешь то, что тебе написал ИИ. И оно работает в большинстве случаев. Но чем больше рос проект, тем сложнее ИИ было следить за зависимостями, и все больше он галлюционировал, и все больше вносил багов.

В итоге, в какой-то момент, погрузившись в принципы работы с новым для меня языком, стало сильно проще писать код самому, чем проходить эти бесконечные итерации вайба и заставлять его генерировать правильный код.

Инверсия зависимостей - это не про расположение модулей друг относительно друга. Не важно, вложены модули у вас друг в друга или расфасованы по папкам или библиотекам. Инверсия зависимостей - это способ связывания сущностей из этих модулей.

Вот пример нарушения инверсии зависимостей

# manager.py - какой-то модуль нижнего уровня

class MyManager:
  def manage(self):
    print("hello world, i am a manager")


# runner.py - верхнеуровневый модуль

from manager import MyManager


class Runner:
  def __init__(self):
    self.manager = MyManager()  # жёсткая связь с низкоуровневыми модулем

  def run(self):
    self.manager.manage()


# main.py - точка входа

from runner import Runner


runner = Runner()
runner.run()

>>> hello world, i am a manager

Здесь прямая жёсткая зависимость между классами. Если мы захотим новое поведение, придётся создавать новый менеджер, и новый раннер, который наследуется от старого и переопределяет зависимость. Попробуем инвертировать зависимость, для этого нам понадобится абстрактный класс или интерфейс.

# manager.py - какой-то модуль нижнего уровня

class Manager:
  def manage(self):
    raise NotImplementedError


class MyManager(Manager):
  def manage(self):
    print("hello world, i am a manager")


# runner.py - верхнеуровневый модуль

from manager import Manager


class Runner:
  def __init__(self, manager: Manager):
    self.manager = manager  # образовалась мягкая связь

  def run(self):
    self.manager.manage()


# main.py - точка входа

from manager import MyManager
from runner import Runner

manager = MyManager()
runner = Runner(manager)
runner.run()

>>> hello world, i am a manager

Теперь мы инвертировали зависимость, сделали её более мягкой. Модули слабее связаны между собой. Если захотим новое поведение в раннере, мы просто имплементируем новый менеджер, а раннер переиспользуем.

При этом абсолютно без разницы, где находится абстрактный класс Manager. Он может быть где угодно, пока не ломает ваши импорты. Мы можем перенести его в модуль runner.py или положить где-то в common.py - на вкус разработчика и как договоритесь в команде.

Если монолит такой большой, что прогретый процесс требует 32+ гига оперативы, то масштабировать такое горизонтально будет сильно накладно.

А некоторые, при запуске монолита, делают долгоживущие подключения в базы и в другие сервисы, которые множить тоже нежелательно.

Но для небольших (относительно) монолитов, с ленивой инициализацией модулей и подключений - почему бы и нет, вполне рабочее решение.

Для каждого проекта есть 3 важные вехи, которые нужно заполнять друг за другом и без которых не обходится планирование фичи:

  • Бизнес требования - что хочет бизнес от приложения. Описание бизнес процессов.

  • Дизайн - технический и интерфейсный. Под техническим подразумевается архитектура проекта, бизнес логика, ограничения, используемые инструменты. Под интерфейсным - дизайн для фронтенда, контракты API, бизнес логика компонентов

  • Связи - используемые библиотеки и их версии, зависимости от других сервисов

Чтобы дать задачу джуну, нужно заполнить все три пункта, чтобы было максимально очевидно, что и как делать. А после нужно тщательно проверять на ревью.

Чтобы дать задачу мидлу, достаточно остановиться на дизайне, а связи отдать на его усмотрение, предварительно обговорив некоторые детали. А ревью кода можно проводить не так досконально, как у джуна.

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

Ничто так не заставляет волноваться сильнее, чем совет интерьера "попей водички", когда он видит, что ты волнуешься. Мной это воспринимается как агрессия, включается защитная реакция "с чего ты взял, что я вообще волнуюсь" и все интервью в принципе можно заканчивать, так как дальнейший тон резко меняется.

Я уже два года использую Honor 50 с быстрой зарядкой 66 w. Установлено приложение AccuBattery, которое следит за циклами зарядки и даёт подсказки как правильно заряжать свой телефон. Так вот, с 16.01.2022 по 18.04.2024 моя батарея прошла 128 циклов, текущая ёмкость составляет 3914 mAh, при заявленной 4300 mAh, тоесть примерно 91%. При этом я стараюсь не заряжать телефон выше 80%, приложение даже выдаёт уведомление при превышении. И не дожидаюсь полного разряда, могу поставить на зарядку и на 30%. Сама зарядка занимает по времени считанные минуты, не больше 20.

Предыдущие телефоны я ставил заряжаться на ночь, там не было быстрой зарядки. И батарея у них погибала стабильно раз в год.

Теперь я с уверенностью могу сказать, что время, которое батарея проведёт подключенная к зарядке больше всего влияет на её состояние, а не величина тока. Зарядка на 80% продлевает время жизни почти в 2 раза. Быстрая зарядка только улучшает ситуацию, так как батарея подключена к току минимум времени.

Information

Rating
8,458-th
Registered
Activity

Specialization

Backend Developer, Fullstack Developer
Senior
Python
Docker
PostgreSQL
Django
Redis
Fastapi
Golang
MongoDB
High-loaded systems
Linux