Ответы пользователя по тегу Java
  • Как реализуется принцип открытости/закрытости в случае "ветвления" расширений в Java?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    основной — наследование.


    Наследование типов а не классов. То есть через интерфейсы.

    В Java нет множественного наследования.


    В Java есть возможность делать композицию типов путем имплементации множества интерфейсов. А с учетом того что в Java8 у вас теперь есть возможность делать "дефолтные" имплементации методов в интерфейсах - у вас есть "правильное" наследование.

    Через некоторое время, этот класс захотят расширить по OCP — унаследуются, и сделают класс Бармен.


    А как потом быть если мы захотим сделать робота бармена? Я это к тому что "человек" не всегда будет являться базовым типом "бармена".

    В целом Dmitry Roo вам верно сказал. "Бармен" это профессия. Свойство человека. У человека может быть много профессий:

    class Human
    {
        Profession[] professions;
    }


    Таким образом мы можем крутить и вертеть как хотим.
    Ответ написан
    Комментировать
  • Где осуществлять валидацию пользовательского ввода в архитектуре MVC?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Давайте размышлять что такое валидация и зачем она нам нужна:

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

    Такие правила как "у пользователя должен быть уникальный email" могут быть проверены только там, где достаточно информации. Например - некий репозиторий пользователей, или DAO. При попытке "сохранить" мы уже делаем проверку. Или мы можем делать это просто повесив ограничение на уникальность на уровне базы данных. Это уже не столь важно.

    Различие тут в том, что все это будет вызывать ошибки. То есть мы не сможем вогнать систему в "невалидное состояние" но пользователь не сможет получить список ошибок, которые он совершил вводя какие-то данные. Все что он получит - отдельные ошибки.

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

    В простых случаях, когда данные из запроса втупую мэпятся на "модель данных", мы можем проверять уже результат. Но в случае с логикой сложнее CRUD это уже не выйдет. Точнее это уже чуть сложнее. К примеру мы передали несуществующий айдишник связанной сущности. Мы запросим данные, получим нул, и валидатор выдаст нам что-то вроде "Извините, но вот эта штука обязательна к заполнению". А пользователь такой "чтааа? Я ж заполнил!" Вот если бы ему приходило сообщение мол "Выбранная вами штука не существует" - тогда ладно, но подавляющее большинство так не запаривается.

    Словом... тут нужно исходить не из "где это делается в MVC" а из "а кому это нужно и какие цели вы приследуете".

    Если что, MVC это не все приложение, это лишь способ разделить ответственность. Приложение ничего не должно знать о UI и все. То есть валидация входящих данных вполне может лежать на уровне контроллера поскольку это ему нужно сформировать список ошибок и запихнуть их к полям формы. С другой стороны, часть валидации может происходить вообще вне "MVC", где-то внутри, на уровне модели предметной области.

    Нельзя из букв "M", "V" и "C" составить слово вечность. Именно по этой причине MVC как подход для организации GUI уже лет 20 как не используется в чистом виде.
    Ответ написан
    Комментировать
  • Отличия абстрактного класса от интерфейса?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    В чем отличие абстрактного класса от интерфейса в Java?


    Все упирается в понятие "тип". В былые времена, то есть во времена языка Simula, из которого черпали вдохновение создатели C++, были только классы. И на классах базировалась система типов. Причем механизм наследования был реализован так, как реализован, исключительно для экономии памяти, которая в те времена была очень дорогой.

    Для того чтобы достичь полиморфизма, мы должны иметь возможность объявлять абстрактные типы. Мол "любая хрень которая имеет такой тип будет работать как надо". Потому в языках типа C++ появились абстрактные классы. Поскольку иногда нам хочется делать композицию абстрактных типов, в C++ реализовали множественное наследование.

    В Java, которая во многом черпала вдохновения из C++ и smalltalk, решили ввести еще одну сущность - интерфейсы. Это был своего рода упрощенный способ задать абстрактный базовый тип. По итогу чтобы не решать проблему бриллианта (или ромба) от множественного наследования было решено отказаться и дать возможность классам имплементить несколько интерфейсов.

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

    В целом абстрактные классы нужны тогда, когда вам нужно наследование. Обычно это в ситуациях, когда у вас есть несколько классов, которые должны иметь общий абстрактный тип (то есть нельзя выделить наиболее слабого по ограничениям предка). Например если мы делаем цепочку классов String <- Email, то тут нет смысла в абстрактных классах так как тип String уже включает в себе подмножество типов Email.

    В целом в java8 уже ввели возможность интерфейсам иметь базовую реализацию, так что не удивлюсь если со временем от ключевого слова extends в принципе откажутся, избавившись от лишней сущности.

    Так же рекомендую к прочтению: www.javaworld.com/article/2073649/core-java/why-ex...
    Ответ написан
    9 комментариев
  • Чем отличается JDBC от ORM?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Для начала упростим JDBC до общего случая Data Access Object (DAO).

    Суть DAO сводится к тому, что у нас есть объект, инкапсулирующий в себе работу с хранилищем данных. Ну то есть весь SQL и все детали работы с хранилищем вшиты в него. Причем их может быть множество (не пихать же вообще всю работу с базой данных в один объект).

    Словом, основная задача DAO - предоставить механизм работы с базой данных скрывая детали внутри себя.

    ORM (Object-relational mapping) - это, если опять же упростить, общая идея конвертации "объектов" между системами с несовместимыми типами. Ну то есть как объекты из базы мэпятся на объекты.

    Если под ORM брать мощные реализации вроде Hibernate, то тут становятся очевиднее минусы конкретно этой реализации. А именно - работать это будет эффективно когда вам нужно построить объектную модель логики приложения, нежели модель данных. Такие подходы хорошо работают в приложениях с реально сложной логикой, где вам бы хотелось в коде передать суть того, как все работает в реальности. Например как именно происходит автоматизация бизнес процесса. С реальными объектами и т.д.

    Для вещей вроде генерации репортов ORM такого плана приносят больше вреда чем пользы. ORM очень хорошо работают в операциях на запись, ито только если речь идет о взаимодействии небольшого количества объектов (пара сотен например, или десятков но не тысяч), когда логика взаимодействий этих объектов сложная, или правил много. Если вам скажем нужно обновить все значения в таблице - сделать это через SQL намного удобнее.

    Ну и в целом, ORM и DAO это весьма разные концепции, они о разных вещах. То есть у вас может быть использовано и ORM и DAO. Или ORM внутри использующее DAO... это не столь важно.
    Ответ написан
    9 комментариев
  • Какие существуют технологии для адаптации сайта к людям с ограниченными выозможностями?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Например есть задумка, о том чтобы включить на сайт лупу


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

    или перевод всего в текст.

    Как это поможет слабовидящим?

    Так же интересует возможность полного управлением функционалом сайта лишь с помощью клавиатуры.


    хоткеи? Причем тут люди с ограниченными возможностями?

    Короче мое мнение: вы придумываете никому не нужные фичи. Ими никто не будет пользоваться и они никому не помогут.
    Ответ написан
    1 комментарий
  • Как лучше организовать отложенные http-запросы?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    beanstalkd

    либо я вас не понял. В этом случае лучше опишите какую задачу вы хотите решить.
    Ответ написан
    4 комментария
  • Сложно ли выучить React-Native?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    https://facebook.github.io/react-native/docs/getti... - и вперед.

    p.s. Характеристики в духе "сложно" или "легко" не имеют смысла. Вам либо нужно либо нет.
    Ответ написан
    3 комментария
  • Для каких задач используется OpenJDK, а для каких Oracle JDK в чем принципиальное различия?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    OpenJDK имеет лицензию GNU GPL.
    Ответ написан
    Комментировать
  • На чем проще программировать под windows?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    C# .NET для windows максимально эффективны. Если же вам нужна кросплатформенная разработка - уже можно думать.

    С другой стороны есть куча других вариантов, вроде html5 + js.
    Ответ написан
    Комментировать
  • Где найти паттерны "правильных" частей системы?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Вот проектируя большой проект с нуля ты уже оперируешь не паттерновыми объектами а частами систем


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

    Большие проекты начинают проектировать с более высокого уровня. Сначала принимают решение о том, какое разделение на слои у нас будет (для проектов со сроками жизни ~10+ лет имеет смысл позагоняться и вводить гексагональную архитектуру, для проектов со сроками жизни <= строк поддержки фреймворка можно не сильно париться), какие компоненты можно выделить, а уже потом дробить эти большие компоненты на компоненты поменьше.

    Затем уже приступать к проектированию каждого отдельного компонента на уровне классов.

    Так же если у нас сложная предметная область - проектируют модель предметной области. Обычно тут "паттерны" сами собой получаются тупо при снижении связанности между объектами.

    > Собственно вопрос: существует ли сборник всех этих лучших практик?

    вне контекста не бывает лучших практик, есть просто практики. В этом плане можно например Фаулера почитать, он очень качественно описывает практики, их плюсы и минусы.

    В целом же я бы рекомендовал вам познакомиться поближе с принципами SOLID и GRASP. Последнее мало кто знает, но понимание, например, что такое высокое зацепление, сильно влияет на то, как вы будете проектировать систему.
    Ответ написан
    Комментировать
  • Как сделать многопоточный чат?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    у вас должен быть один основной поток, где вы ожидаете подключения. При подключении у вас создается сокет, который вы кидаете в отдельный тред.

    Socket clientSocket = serverSocket.accept();

    То есть у вас не верно логика работы построена. Вы при получении соединения начинаете сразу же с ним работтать, а вам нужно в цикле слушать новые соединения и для каждого запускать тред.

    Хочу отдельно отметить, что при увеличении количества потоков производительность будет падать. При достижении отметки в пару сотен клиентов например. В этом случае лучше переключаться на event loop/микротреды/корутины.
    Ответ написан
    1 комментарий
  • Можно сказать что у компилятора из Android SDK свой диалект Java?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    у Android своя реализация Java Runtime, так что метод main ему не нужен, там чуточку другие правила в этом плане.

    Считайте что это просто отдельная реализация Java. Но с точки зрения синтаксиса различий нет, так что говорить о другому диалекте не приходится.
    Ответ написан
    2 комментария
  • Что за шаблон Декоратор, и зачем он нужен?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    То что вы реализовали - не декоратор. Декоратор это интерфейсы а не абстрактные классы.

    суть шаблона Декоратор


    Декоратор, это такой шаблон, при котором мы "расширяем" поведение объекта без изменения оного. При этом важная состовляющая - интерфейс объекта не меняется.

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

    К примеру при использовании контейнера зависимостей, мы можем обернуть какой-то сервис в декоратор временно, и в декораторе логировать аргументы и результат выполнения методов. Скажем это нужно только для быстрого дебага. Делаем быстренько декоратор, подсовываем его вместо настоящей реализации (обычно это одна строчка в di-конфиге) и вуаля. Мы не вносили изменений в код а стало быть не могли ничего сломать случайно. История изменений будет выглядеть красиво. Да и тестировать такие вещи намного проще.
    Ответ написан
    Комментировать
  • Невытесняющая многозадачность в Java (Coroutine, Fibers), почему не Callable?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    callback hell. Мы же не хотим из-за модели выполнения код особо переписывать.
    Ответ написан
    Комментировать
  • MVC: Кто должен отвечать за спрайты?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Решил сделать простую игру.


    MVC для приложений, для игр оно не применимо так как у вас UI и предметная область слишком уж сильно связаны друг с другом, а MVC ставит перед собой цель именно "развязать" их. Конфликт идет уже в фразе:

    Модель хранит в себе спрайт.


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

    Короче для игрушек обычно применяют чуть другой паттерн, под названием ECS (Entity-Component-system), которы позволяет разделить обязанности чуть-чуть подругому.

    p.s. но если вернуться к MVC - то третий вариант. А что до
    Но за хранение состояний должна отвечать модель.

    Модель отвечает не столько за хранение состояния, сколько вообще за обработку оного. Ну то есть внешний мир о внутреннем состоянии ничего не знает, но это не значит что внешний мир не может попросить кусочек состояния для себя и потом его хранить. View так же может хранить состояние связанное с view и не влияющее ни на что другое.
    Ответ написан
    1 комментарий
  • Для каких задач Java лучше подходит, чем С++?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Правда ли, что зная С++ можно быстро перейти на любой ооп язык?


    Относительно быстро, да. В принципе C++ должен дать вам неплохой фундамент.

    Читал, что С++ имеет больше в сравнении с java рычагов управления памятью.


    В Java код выполняется через JVM, со сборщиками мусора и т.д. То есть получить там seg fault или утечку памяти банально сложнее. Это налагает определенный оверхэд, хотя JIT компиляторы генерируют неплохой и довольно эффективный код, так что если брать среднего девелопера на C++ и среднего девелопера на Java - у последнего просто расход на память будет сильно больше, но в целом же в большинстве случаев особой разницы в производительности вы не увидите. Да и не сильно это важно с учетом скорости разработки (что важнее обычно).
    Ответ написан
    2 комментария
  • Одинаковые куски кода в разных классах допустимо или нубство?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    нубство. Выносите общее в методы, в общие зависимости. Почитайте про DRY.

    Дублирование позволительно если это... ну тупой код и от дублирования никуда не деться. Но у вас тут какие-то выражения, логика, поведение дублируется. А это уже нубство.
    Ответ написан
    3 комментария
  • Чем связать php и java?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    pub/sub на rabbitmq/zeromq/activemq и т.д. Можно конечно RPC организовать но...
    Ответ написан
  • Как тестировать DAO слой на Java с Mockito?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Мокают сам DAO, никто в здравом уме не мокает Connection/DataSource и т.д. поскольку поддерживать такие тесты выходит слишком дорого - проще написать простенький интеграционный тест, который использует реальную базу данных.
    Ответ написан
    Комментировать