• Какой хороший ресурс чтобы изучить шаблоны проектирования ООП и все нюансы?

    refactoring.guru - один из наиболее качественных, если говорить о паттернах GoF.
    Ещё книга из серии Head First по паттернам достаточно легко читается.

    Но где применять в реальных задачах - это, в основном, только на практике.
    Ответ написан
    43 комментария
  • Можно ли в DTO валидировать данные?

    @tukreb
    Уже обсуждалось это здесь и не раз, DTO только для передачи данных и точка. Всё остальное происходит вне DTO
    Ответ написан
    5 комментариев
  • Как в данном случае работает наследование?

    TTATPuOT
    @TTATPuOT
    https://code.patriotovsky.ru/
    То, что написано в целом - это самый настоящий говнокод. Класс A не является самостоятельным и при попытке сделать его экземпляр и вызвать A->method() программист получит ошибку в любом случае. Так делать нельзя, независимо от логического обоснования того, что здесь происходит.

    А явление, которое вы наблюдаете называется умными словами позднее статическое связывание (3 пример). Почитать кучу текста всё-таки придётся, этот нюанс в двух словах не объяснить, что вы хотели?
    Ответ написан
    2 комментария
  • Какое приложение написать для понимания ООП?

    Lastor
    @Lastor
    В чем сила, брат? В ньютонах.
    Полноценного понимания не существует.
    Я долго писал в процедурном стиле и долго не мог понять зачем вообще нужны эти классы какие-то.
    Всё решалось функциями. С ростом сложности проекта приходилось передавать в функции всё больше и больше аргументов. Когда аргументов стало слишком много, я стал передавать в качестве аргумента массив с переменными.
    Функция изменяла значения в этом массиве и возвращала.

    Иногда (часто) функция должна была вызвать другую функцию и передать туда этот массив. Количество функций росло, цепочки из них становились всё длиннее и я даже стал путаться в том, какая функция в какой цепочке (трейсе) участвует.
    Тогда я стал раскладывать группы функций по разным подключаемым файлам и называл эти файлы так, чтобы по названию понять какой группе переменных они нужны.

    А потом я случайно узнал, что эти какие-то непонятные методы, которые "являются поведением объектов класса" (как это обычно объясняют) на самом деле просто функции и есть. И оказалось, что можно не пропихивать массив через них, а наоборот - функции сложить в этот массив. Получилось, что класс это такой "массив" в котором есть не только переменные, но и функции. И эти функции могут видеть все эти переменные, даже если не написать global $var. И это было как раз тем, чего я очень желал и радости моей не было предела.
    Кстати, узнал я это, когда забавы ради кодил 2D платформер на C# в Unity.
    Ответ написан
    Комментировать
  • Как учиться быть руководителем?

    Griboks
    @Griboks
    В отличии от программирования и подобных специальностей существуют три базовых способа изучить искусство управления:
    1. вуз
    2. специальные курсы + сертификация
    3. госты+стандарты+книги для расширенного понимания первых двух

    p.s.
    Alexander Lamdan утверждает, что
    Научиться быть руководителем это почти никак. Нужно к этому идти.


    Замечу, что это в корне неправильный подход, который ведёт к самодурству, неэффективной организации труда и коррупции. Вы действительно должны выработать свою точку зрения, но делать это самостоятельно и изолированно от обширных накопленных человечеством знаний займёт слишком много времени и других ресурсов - это путь в никуда для управленца.
    Ответ написан
    7 комментариев
  • Для чего в go.mod добовить зависимости если мы указываем полный путь к ним в коде?

    Для указания версий этих зависимостей. Чтобы бралась не последняя версия, а указанная. Обеспечивает повторяемость релизов и стабильность.
    Ответ написан
    Комментировать
  • Для чего в go.mod добовить зависимости если мы указываем полный путь к ним в коде?

    @deliro
    Сегодня ты используешь пакет vasyan и из него вызываешь vasyan.Hello(5, 6), которая по документации умножает первый аргумент на второй, а завтра пакет vasyan обновляется и Hello удаляется, а у тебя падает компиляция. Но гораздо хуже ситуация, когда завтра пакет vasyan обновляется и теперь Hello прибавляет первый аргумент ко второму, компиляция проходит, всё прекрасно, но в конце месяца к тебе приходит бизнес и садит на бутылку за то, что вы три месяца снимали по 11 долларов с клиентов вместо ожидаемых 30 и таким образом потеряли два миллиона долларов
    Ответ написан
    6 комментариев
  • Как правильно передавать параметры при новом создании экземпляра?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Такое, конечно, можно сделать через статическое свойство со списком экземпляров класса, но зачем нужен такой изврат? В каких реальных целях его применять?
    class A
    {
        private static array $instances = [];
        public readonly int $value;
      
        public function __construct(?int $value = null)
        {
            if ($value !== null) {
                $this->value = $value;
                static::$instances[] = $this;
            }
        }
    
        public function summ(): int
        {
            return array_reduce(
                static::$instances,
                fn($acc, $cur) => $acc + $cur->value,
                0
            );
        }
    }
    
    new A(2);
    new A(3);
    $summ = (new A())->summ();
    print $summ; // 5
    Ответ написан
    Комментировать
  • Как практиковать ООП?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Мне кажется что JavaScript/TypeScript - это плохой старт для изучения ООП. Дело в том что JavaScript исполняющая среда изначально была разработана с слишком вольной интерпретацией объекта. Грубо говоря она настолько flexible что те строгие законы и правила которые навязывает ООП в JavaScript могут быть слишком легко нарушены.

    Поэтому чтобы почувстоввать нужность ООП, как дисциплины. Я-бы предложил Java или C#. Это как в музыке. Нельзя начать сразу ипровизировать джаз на музыкальном инструменте в 5 лет. Надо пойти в музыкальную школу где преподаватели тебе поставят руку правильно. А потом уже после семилетки - муз-училища - консерватории - иди в импровизации. Или даже иди раньше. Но какая-то дисциплина должна быть. ООП - это дисциплина. Не волюнтаризм.
    Ответ написан
    3 комментария
  • Как использовать форк пакета в Го?

    uvelichitel
    @uvelichitel Куратор тега Go
    habrahabr.ru/users/uvelichitel
    Всего две команды:
    подмена
    go mod edit -replace github.com/orig/pkg v1.0.0=github.com/my/fork/pkg v1.0.0

    или на локальный репо
    go mod edit -replace github.com/orig/pkg v1.0.0=/local/path/onyourmachine

    вернуть обратно когда ваш PR закоммитят
    go mod edit -dropreplace  github.com/orig/pkg v1.0.0

    А можно подправить go.mod вручную. В нём должно появиться
    replace github.com/orig/pkg v1.0.0  => github.com/my/fork/pkg v1.0.0

    В исходниках при этом менять импорты не нужно.
    Ответ написан
    1 комментарий
  • Какие стоит создавать интерфейсы?

    @Akela_wolf
    Extreme Programmer
    А если бы, допустим, в у нас был отдельный интерфейс IMove, то мы смогли бы реализовать его в каком угодно модуле/компоненте, например в условном File, ведь мы можем переместить файл. Так же и с ISleep, мало ли что может уснуть, начиная от операционной системы или потока выполнения, заканчивая персонажем в тамагочи.


    Неверно. IMove (точнее будет назвать Movable) имеет смысл в контексте какой-то предметной области. И перемещение файла, перемещение спрайта, перемещение трехмерного объекта, перемещение руки робота - все это разные перемещения. Соответственно и интерфейсы будут разные (расположенные в разных модулях, даже если будут называться одинаково), например:
    filesystem.Movable
    graphics.2d.Movable
    graphics.3d.Movable
    servo.Movable


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

    Вообще главный принцип тут такой: интерфейс должен иметь смысл, описывать некоторую единицу функциональности именно с точки зрения предметной области. Скажем, если в вашей предметной области операция move имеет смысл без операций eat и sleep - её можно выделить в отдельный интерфейс (а можно и не выделять, это зависит от других факторов). Если же операции eat и sleep всегда должны ходить парой и каждый потребитель этого интерфейса нуждается в обеих операциях - они должны быть в одном интерфейсе.
    Ответ написан
    4 комментария
  • Можно ли регистрировать вибрации от телефона?

    @nehrung
    Не забывайте кликать кнопку "Отметить решением"!
    Вы хотите регистрировать инфразвук с частотами десятки герц, и пытаетесь применить для этого пьезокристалл с резонансом 4 кгц. Пьезо - для инфразвука совершенно непригодные датчики, их рабочие частоты - это верхние звуковые и ультразвук.
    Вряд ли будут лучше и датчики на электродинамическом принципе (это понятно хотя бы из того, что проблема воспроизведения басов в мобильном телефоне не решена до сих пор). Но их всё же можно попытаться использовать, если закрепить такой датчик на массивном неподвижном основании, а от его подвижной части провести жёсткий звуковод до того места на вашем телефоне, где вибрация ощущается лучше всего.
    Возможно, наилучшим датчиком, снимающим сигнал вибрации, был бы стандартный датчик положения корпуса, имеющийся в каждом современном смартфоне. Но это лишь моё предположение.
    Ответ написан
    2 комментария
  • Правильно ли я понял принцип инверсии зависимостей?

    @Akela_wolf
    Extreme Programmer
    Главная идея принципа инверсии зависимостей "детали зависят от абстракций, но не абстракции от деталей".
    В приведенном вами примере класс Main зависит от всего: от интерфейса INumberOperation и от обоих классов NumberOperation1, NumberOperation2. То есть тут принцип инверсии зависимостей вообще не работает. Никак.

    Проявляется же он в следующем примере. Пусть у меня есть некая абстрактная логика "прочитай число, выполни над ним операцию, запиши результат". Эта абстрактная логика (потому она и абстрактная) ничего не должна знать ни откуда она читает число, ни какую операцию над ним выполняет, ни куда и как записывает результат. Таким образом, у нас есть модуль, состоящий из
    interface NumberInput {
      int read();
    }
    interface NumberProcessor {
      int process(int a);
    }
    interface NumberOutput {
      void write(int a);
    }
    class Processor {
      private final NumberInput input;  
      private final NumberProcessor processor;
      private final NumberOutput output;
    
      public Processor(NumberInput input, NumberProcessor processor, NumberOutput output) {
        this.input = input;
        this.processor = processor;
        this.output = output;
      }
    
      void process() {
        output.write(processor.process(input.read()));
      }
    }

    Все. Модуль получился очень абстрактным и ни от кого никак не зависящим.
    Затем мы можем сделать реализации этих интерфейсов - они будут зависеть от нашего модуля логики (так как ссылаются на интерфейсы). И это полностью соответствует принципу инверсии зависимостей - детали зависят от абстракций.

    И наконец функция main, которая будет собирать все это в единое целое. Она самое конкретное что есть в нашей программе, так как она имеет дело с конкретными классами, экземпляры которых она создает. Поэтому она зависит от всех модулей - от модуля абстрактной логики и от модулей с реализациями интерфейсов. И тут принцип инверсии зависимостей тоже соблюдается - деталь (в какой именно конфигурации запускается программа) зависит от абстракции (абстрактная логики и конкретные реализации интерфейсов из которых выбирается именно та, которая будет использована)

    Этот принцип очень хорошо объяснен в книге Р.Мартина "Чистая архитектура", по крайней мере у меня все встало на свои места именно после прочтения этой книги.
    Ответ написан
    1 комментарий
  • Как сортировать в Go?

    Способ 1: как вы и хотите, переиспользование функции. Пишем функцию, которая возвращает функцию less
    https://play.golang.org/p/x_zDfZfwm_Q
    func main() {
    	arr := []byte{4, 3, 2, 1, 6, 3, 77, 8, 3}
    	sort.Slice(arr, bytesAsc(arr))
    	fmt.Println(arr)
    }
    
    func bytesAsc(arr []byte) func(i, j int) bool {
    	return func(i, j int) bool {
    		return arr[i] < arr[j]
    	}
    }


    Способ 2: создаем алиас типа, у которого прописаны нужные методы.
    https://play.golang.org/p/ZNkOt_jSUbr
    func main() {
    	arr := []byte{4, 3, 2, 1, 6, 3, 77, 8, 3}
    	sort.Sort(BytesAsc(arr))
    	fmt.Println(arr)
    }
    
    type BytesAsc []byte
    
    func (a BytesAsc) Len() int           { return len(a) }
    func (a BytesAsc) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
    func (a BytesAsc) Less(i, j int) bool { return a[i] < a[j] }
    Ответ написан
    Комментировать
  • Как сортировать в Go?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Если нужна именно функция - можно вот так
    func SortBytes(arr []byte) {
        sort.Slice(arr, func(i, j int) bool {
            return arr[i] < arr[j]
        })
    }
    // потом использовать вот так
    arr := []byte{4, 3, 2, 1, 6, 3, 77, 8,3}
    sortBytes(arr)
    fmt.Println(arr)

    Но я бы использовал тот вариант, который у вас )
    sort.Slice(arr, func(i, j int) bool {
      return arr[i] < arr[j]
    })
    fmt.Println(arr)
    Ответ написан
    5 комментариев
  • Как сортировать в Go?

    2ord
    @2ord
    sorter := func(i, j int) bool {
    		return arr[i] < arr[j]
    	}
    	sort.Slice(arr, sorter)
    Ответ написан
    1 комментарий
  • Стоит ли разбивать css/js для разных страниц?

    Kozack
    @Kozack Куратор тега CSS
    Thinking about a11y
    В общем случае -- стоит.

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

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

    В общем случае -- дробить код сайта на куски и отдавать их частями -- стоит. Но вмеру. А как именно делить -- зависит от вашего случая.
    Ответ написан
    Комментировать