• Куда стоит пойти учиться новичку?

    @AlexHell
    фундаментальные знания и навыки никто не отменял

    а то бывает идут конкретно сайтики клепать, а не понимают что серв и клиент это разные машины могут быть (а не абстрактная система, или "сайт" не ясно каким образом работают), что там разные технологии могут использоваться, а они не думают как по сети передаются данные, на каких языках ранее писались эти сайты, и какие протоколы и технологии юзались и юзаются, не думают о безопасности, не думают о вычислительной сложности, о том как в БД хранятся данные и как они хранятся на диске, и как извлекаются, куда перебрасываются когда вы делаете эти самые БД запросы т.е между ОЗУ и медленным диском, между ОЗУ и очень медленной сетью

    этим я хотел сказать что нужно учиться всему по-немногу - чтобы представлять КАК оно все работает, не обязтельно учить все тонкости ассемблера и железа, но представлять что там внутри под капотом каждой технологии - это нужно

    учиться - нужно.. нужно всегда.. и идти в ВУЗ или на курсы онлайн это только начало
    Ответ написан
    Комментировать
  • Как привести blob (>32k) к строке?

    @AlexHell
    без ORM - чисто JDBC
    https://www.ibm.com/support/knowledgecenter/ssw_ib...
    byte[] outByteArray = blob1.getBytes(startingPoint, (int)endingPoint);
    потом конкретируете в string с нужной кодировкой
    Ответ написан
    Комментировать
  • Как улучшить модуль обработки дерева?

    @AlexHell
    Это вот все не типизированное - ни конкретных классов\функций, а по имени передается 'setCurrentEdited' который текстовым поиском искать надо, и его опции value: false - плохо с точки зрения архитектуры

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

    p.s. а еще model, modes - очень плохое название, во 1х это отличие всего в одном символе, и в теле метода будет путаница (ктото пропустит последнюю букву), вот чисто по опыту вам скажу
    к тому же modes вообще не говорит что это за режим
    лучше - actions

    что до
    - масштабируемости
    - скорости
    .. то это вам замерять в своих условиях.. боитесь медленной интерпретации динамических имен функций и передачи им параметров? почитайте доки, может кто еще ответит
    Ответ написан
    2 комментария
  • Как должна выглядеть модель. Какие шаблоны использовать?

    @AlexHell
    если много параметров и возможно расширение - можно Спецификацию использовать (в которой будет например кол-во товаров, их тип, может еще что в будущем)

    для простого случая - создавайте 1 базовый класс, и 2 подкласса
    общий метод содержит все что только может быть
    ICalculator
    {
    int GetCost(int count)
    }

    FixedCalculator : ICalculator
    {
    int _cost;

    FixedCalculator (int cost)
    {
    _cost = cost;
    }

    int GetCost(int count)
    {
    return count * _cost;
    }

    ProgressionCalculator : ICalculator
    {
    int _costBase; // базовая цена плюс..
    int _costDiscount; // скидка (минус процент или минус фикс) за каждые Step штук
    int _costDiscountStep;

    ProgressionCalculator(int cost, int costDiscount, int costDiscountStep)
    {
    _cost = cost;
    _costDiscount = costDiscount;
    _costDiscountStep = costDiscountStep;
    }

    int GetCost(int count)
    {
    return FORMULA
    }
    Ответ написан
    Комментировать
  • What layer should contain Queries in DDD?

    @AlexHell
    example with 2 types (Article and User):

    * InfrastructureLowLevel (know nothing about higher levels)
    - DatabaseImplementation
    - IQuery[TResult]
    .. can combine SQL for DB query, or invoke specific IRepository methods (override-able in IRepository)
    - IRepository[TQuery, TResult]
    methods:
    \ TResult GetSingleByQueiry(TQuery IQuery)
    \ List[TResult] GetMultiByQueiry(TQuery IQuery)
    .. invokes DatabaseImplementation
    .. invokes IQuery for specific actions - conditions by type

    * InfrastructureHighLevel (semi-domain, know about InfrastructureLowLevel):
    - Article
    - User
    - ArticleQuery : IQuery[Article]
    - UserQuery : IQuery[User]
    - ArticleRepository : IRepository[ArticleQuery, Article]
    - UserRepository : IRepository[UserQuery, User]

    * BisinessDomain (higher\highest level, know about InfrastructureHighLevel):
    - MyLogic
    usage:
    User user = UserRepository.GetSingleByQueiry(UserQuery)
    Article article = ArticleRepository.GetSingleByQueiry(ArticleQuery)
    Ответ написан
    Комментировать
  • Java+netty+kafka: как перейти от многопоточности к мультиплексированию?

    @AlexHell
    Я прочитал ответ от Сергей Горностаев в принципе согласен со 2м вариантом, если я его понял, но дополню как бы сделал я:
    - кто-то отправляет сообщение к netty серверу "write"
    - netty делает добавление в InMemory очередь для kafka (мгновенно)
    - netty оповещает остальным заинтересованным (если клиент уже приконекчен, иначе он получит все пакеты в момент конекта) TCP пакет "notify" (мгновенно) чтобы потом клиент послал "readAll" если данные сразу слать не хочется, либо сразу пакет со всеми данными ему шлется предназначенными ему
    - (если клиент еще не был приконекчен) заинтересованный клиент конектится и netty отдает ему все его сообщения (не комитит пока) из InMemory
    - клиент шлет "commit" - netty фиксирует в InMemory до какого сообщения клиент дочитал, и отправляет в очередь также в kafka

    по сути получается одна лишняя очередь, куда сохраняются KafkaTask
    и еще текущее состояние InMemory (видимо с удалением когда клиент уж точно прочитал)

    в этой очереди из InMemory в отдельном потоке или даже пуле, как и при БД - происходит запись в kafka реально для персистентности
    я правильно понял цели?

    если бы не персистентность то можно было бы без kafka обойтись даже и просто клиент шлет "write" и всем остальным клиентам рассылается "data" если они уже онлайн или складывается в InMemory и только в момент приконекта клиента отдается

    когда персистентность нужна - добавляется только лишняя очередь чтоб в нее в итоге сохранялось, остальное все то же, и при перезапуске сервака - данные из kafka (или БД) бы восстанавливались в InMemory (если их не прям очень много, иначе может отложенным таском в потоке другом)
    Ответ написан
    Комментировать
  • Как правильно реализовать клиент-серверную структуру в данном случае?

    @AlexHell
    Помоему более-менее еще написано, не совсем говнокод, можно улучшить
    если 2 контроллера - и это у вас разные Окна / Формы, то никакий из нихз не надо насоледовать от TCPConnection и TCPConnectionListener, надо сделать гдето Singleton
    public static MyConnectionToServer
    {
      private static readonly TCPConnection Connection
        = new .. (OnMessageReceived);
      private static readonly Dictionary<string, List<Action<MessageBase>>> Listeners = new ..;
    
      public static void SendToServer<T>(RequestBase request) { /* send */ }
    
      private static void OnMessageReceived(string message)
      {
      // все сообщения наследовать например от MessageBase
      // но в подклассах еще новые данные
      // в MessageBase только string MessageType
    
      // это десериализует только тип по сути, остальное игнорит
      MessageBase messageBase = Deserialize<MessageBase>(message); 
    
      MessageBase concreteMessage = DeserializeConcrete(messageBase.MessageType, message);
      Dispatch(messageBase.MessageType, concreteMessage);
    }
    
      private static T DeserializeConcrete<T>(string messageType, string message)
      {
        switch (messageType)
        {
          case "type1": return Deserialize<MessageType1>(message);
          case "type2": return Deserialize<MessageType2>(message);
        }
      }
    
      private static void Dispatch(string messageType, T concreteMessage) where T: MessageBase
      {
      // юзать Listeners по messageType и в них передать concreteMessage
      }
    
      public static void AddListener<T>(string messageType, Action<T> onReceived)
      {
        // добавить в Dictionary по messageType
      }
    
      public static void RemoveListener<T>(string messageType, Action<T> onReceived)
      {
        // удалить из Dictionary по messageType
      }
    }
    
    а из каждого Контроллера Окна вызывать
    AddListener("type1", (message) => ProcessType1(message));
    
    и в конце RemoveListener("type1") чтобы не утекло
    Ответ написан
    Комментировать
  • Как разрабатывать программы с фоновыми задачами?

    @AlexHell
    java concurrency in practice - один из соавторов Doug Lee
    применимо и к другим языкам если в принципах разобраться
    не связано с GUI т.е применяется на серверах для ускорения распараллеливания (очереди, локи, lock free - но это сложней)
    Ответ написан
    Комментировать
  • К какому слою относится Repository и как возвращать Business object?

    @AlexHell
    class User {Id, Name, Age}
    
    class UserRepository
    {
     User GetUserById(long Id)
      {
      string[] data = {select from Users where id = Id}
      return new User() {Id = Id, Name = data[0], Age = data[1] };
      }
    
      void PutUser(User)
      {
        {insert into Users}
      }
    }


    Зачем вам UserEntity? Если у вас доменный объект User - везде его и передавайте, и Repo олжен его же вертать при чтении из БД и его же принимать чтоб сохранять в БД.

    Если вопрос в EntityFramework (и иже с ними ORM) с обязательным отнаследованием от базового Entity класса - ну сделайте маппинг опять же внутри UserRepo и не отдавайте вообще никогда вовне UserEntity, всмысле как private class например чисто для namespace / пакета
    Ответ написан
    Комментировать
  • NoSql vs Реляционные СУБД. Как правильно выбрать СУБД, чтобы потом не было мучительно больно?

    @AlexHell
    Юзайте SQL базу с которой знакомы, т.е можете конфиг настроить, подтюнить, производительность замерьте и все будет быстро. На счет NoSQL - вообще сомнительная наработка как по мне, все можно в SQL, с prepared statement если на парсинг SQL времени много (только по рез-там тестов).
    Ответ написан
    Комментировать
  • Нужно ли сжимать данные при передаче клиент-сервер? Как должен работать сервер?

    @AlexHell
    Не правильно " отдельный поток на отдельный коннект со всей логикой" , автору лучше смотреть на асинхронные сокеты, на java есть netty. Если серв голый CPP также то не подскажу, но есть также асинхронные серваки 100%.

    Смысл того что я далее пишу в том чтобы
    1) не пострадать от огромного числа перключений контекста ОС изза сотен или тысяч потоков
    2) не плодить лишние lock в game логике

    Логика работы netty как фреймвор сетевой, можно слушать событие получения данных из сокета и их сразу обрабатывать в 1 из 4 потоков, без блокировок, внешнего взаимодействия (бд и т.п блокируют и долго отрабатывают поэтому нельзя), либо ставить в очередь (lock на структуре данных, например ArrayBlockingQueue) и во внешнем worker потоке обрабатывать. Если хотите можно многопоточно обрабатывать, но чтобы был толк - лучше разделить разные worker по разным источникам (например 1 worker thread на четные GameId, 2й на нечетные, все Game имеют GameId который назначается при старте игры).

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

    Если у вас шутер или экшен сетевой, с архитектурой может подойти:
    -- клиент шлет N раз (3 раза в сек у вас, но в шутерах делают и 30 раз)
    -- серв расчитывает игровые тики (столкновения, попадания, урон, движения) U раз
    -- серв шлет Y раз ответы клиентам (в отдельном таске и цикле вероятно, чтобы все клиенты получали отсечку после расчета одного и того же игрового тика сервом) в шутерах делаю 30 раз в сек, может отчаться от N)

    Но вообще при расчетах на серваке, на клиентах еще может пригодиться интерполяция и предсказания (экстраполяция) (т.к. в моменты пока от серва нет данных - надо чтобы чтото двигалось) или машина времени (откатывать, если предсказал неверно).
    Ответ написан
    Комментировать
  • Как ускорить вставку данных в таблицу с 500 млн записей?

    @AlexHell
    Тут пишут про "не лучшее решение" а для каких задач? Автор скажите как пользоваться планируете! Для чтения много запросов? Пропорция чтения / записи какая? 80 чтений, 20 записи? Тогда индексы не удалять точно. Да и вообще вредные советы в духе "вставить пакетно без индексов".. угу, а потом ждать пока индексы построятся по этим миллионам? А если у человека записи идут постоянные, т.е это не 100% чтений, ему что удалять каждый раз индексы, вставлять данные, и заного индексы создавать? Удалять индексы можно 1 раз, для огромного пакета и при отсутствии последующих вставок в течении продолжительного времени, иначе пересоздавать и удалять - не вариант.

    Далее, советовали поменять на InnoDB - полностью поддерживаю. MyISAM очень привередлив и может легко корруптится (пруф сейчас не найду), и рекомендуется уж большие то базы (а особенно важные, даже не большие, но большие особенно) точно держать в InnoDB или xtraDB (MariaDB улучшенная версия InnoDB). Там восстановление после сбоев адекватное. По скорости работы надо проводить конкретные замеры для вашей нагрузки (чтений, записи, вашего железа), чтобы еще найти момент на котором MyISAM будет быстрее, что не факт. А восстановление после сбоев дорогого стоит.

    Что касается основного подхода: держите индексы в ОЗУ, впрочем Mysql сам это и делает, когда выделяете достаточно оперативки. в MyISAM опции погуглите для задания (если на нем останетесь). А для InnoDB нужно задавать следующие параметры
    innodb_buffer_pool_size=1024M
    innodb_log_buffer_size=4M
    innodb_log_file_size=48M
    innodb_log_files_in_group = 2
    по их настройке есть целые статьи и книги (от Зайцева в оригинале найдите если нужны подробности). От себя скажу что innodb_buffer_pool_size основная опция для держания всего в ОЗУ, если не умещаются индексы, данные, т.е. по замерам идет подкачка на диск смотрите read/write по дискам.. под linux iostat -dx 5 ; vmstat 5 ; iotop в помощь
    innodb_log_buffer_size и innodb_log_file_size задается от размера вставок, чтобы не копились в оперативке слишком много или мало - влияет на сброс лога на диск, читайте подробности и настраивайте по своей нагрузке на запись, точные цифры никто не скажет (правило настройки есть в книге и статьях).
    innodb_flush_log_at_trx_commit - доп опция, читайте что делает, может пригодиться, но для надежности лучше default.

    Если есть достаточное железо т.е. ОЗУ и диски в raid 10, то InnoDB (xtraDB) обеспечат вам адекватную вставку в 500млн таблицу с вашей несложной структурой. И чтение из нее обеспечат.

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

    Хотя по вашей базе я не вижу где тут прямо очень часто надо что-то менять. Новые юзеры часто добавляются? Данные меняются каких полей и как часто? Может не всю таблицу привели и там еще что-то?
    Ответ написан
    Комментировать
  • Как сделать рекурсивный бинарный поиск?

    @AlexHell
    смысл бинарного поиска это постепенное сдвигание границ, т.е [0, 10] интервал для array превращается в [0, 5] потом в [2, 5] потом в [4,5] потом проверяется элемент [4]

    За точность не гарантируюю, но то что пришло на ум
    public static int BinSearchLeftBorder(long[] array, long value, int left, int right)
    {
    if (left == right)
    {
    if (array[left] == value) return left;
    return -1;
    }

    var m = (left + right) / 2;
    if (array[m] < value)
    return BinSearchLeftBorder(array, value, m, right-1 );
    return BinSearchLeftBorder(array, value, left, m);
    }

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

    для вашего примера с 2 прямо по середине, бин-поиск обычный завершится сразу на 1м шаге и найдет в индексе [4] значение == 2.
    Ответ написан
    Комментировать
  • Как передать данные из java-класса в нативный блок кода, написанного на C++?

    @AlexHell
    Я не подскажу с тем подходом, который вы использовали.
    Пробовал только такой тулзой https://github.com/nativelibs4java/JNAerator сгенерировал к уже существующему DLL (от стима) класс Java, в котором получилось вида
    public interface LibrarySteamAppTicket extends Library {
    byte SteamEncryptedAppTicket_BDecryptTicket(uint8 rgubTicketEncrypted, int cubTicketEncrypted, uint8 rgubTicketDecrypted, IntByReference pcubTicketDecrypted, Pointer rgubKey, int cubKey);
    ...
    }

    и вызывал так
    private static LibrarySteamAppTicket Library = (LibrarySteamAppTicket) Native.loadLibrary("sdkencryptedappticket64" , LibrarySteamAppTicket.class);
    // причем sdkencryptedappticket64.dll лежит рядом с jar при релизе (или в netBeans проекте в корне)

    ...
    byte ret = Library.SteamEncryptedAppTicket_BDecryptTicket(..)

    Причем DLL создана была явно не для java, а произвольную можно.
    Ответ написан
    Комментировать
  • Какую систему контроля версий лучше использовать в Unreal Engine?

    @AlexHell
    точно не SVN (в отлчие от HG/GIT он имеет другую модель ветвления/мерджа и т.п.) замучаетесь поддерживать, и лучше имхо держать все в одном месте т.е. 1 репозитории на 1 из сайтов, хотя при огромном размере ассетов есть варианты, я склоняюсь к GIT, но возможен и Perforce (не юзал но слышал что большие студии юзают)
    Ответ написан
    Комментировать
  • Как сделать конфигуратор в unreal engine?

    @AlexHell
    Я на UE не писал, но в геймдеве работаю. Мое мнение: общая архитектура из 3 основных моментов:
    1) делаете модель (машины в вашем примере) из множества составных частей (моделей, материалов к ним приататченным, шейдеров) чтобы каждую можно было заменять / красить отдельно
    2) делаете скрипт где задаете связь: в простом случае - статично натаскиваете связь между шейдеровыми свойствами вроде цвета - и параметру в скрипте, можно и связи на меш/игровой объекто чтобы меш заменять, на unity это так делается примерно
    3) UI которым меняете свойства с использованием промежуточного скрипта
    Ответ написан
    Комментировать
  • Шаблон проектирования - посредник (Mediator) объясните на простейшем примере как он работает?

    @AlexHell
    если не ошибаюсь, приведу пример из геймдева: список слотов SlotList, и сам слот Slot, вот коллега (colleague) это Slot и их много, а медиатор (mediator) это SlotList т.е. посредник который координирует все слоты, причем событие клика по (x,y) на сцене мы передаем в медиатор, а он решает в какой слот мы попали (циклом например сравнивает bounding box), также мы можем обратиться к медиатору чтобы заполнить его список слотов например передать какой-то Dto или список Dto для визуализации в слотах, а уже медиатор расставит в каждом слоте свою картинку и текст

    вот другой пример (но детально там не разбирался) https://github.com/marwie/Design-Patterns-in-Unity...
    Ответ написан
    Комментировать
  • Как начать использовать шаблон спецификация?

    @AlexHell
    дам ответ на вопрос более общий по "шаблону <спецификация>" - это как раз-таки класс с методом инкапсулирующие знания о чем либо, зачастую создание или алгоритм работы, с подробностями аргументов (которых может быть много и они не обязательные)

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

    более конкретно по вашему вопросу не ясно вот это
    "Проще говоря, мне нужно указывать условия для метода findBy($criteria) которая внутри в зависимости от типа ресурса будет конвертироваться в формат условия который понимает ресурс."
    что есть "в зависимости от типа ресурса" - какие виды ресурсов?
    вообще у вас должна быть начинка "реальной работы", для случая спецификации: когда в вашем findBy вызываются специфичные методы которые в спецификации есть, возможно надо и с другими шаблонами/сущностями сгруппировать, например из спецификации вызывать конкретный метод одного из полиморфных преобразователей (IImplementer, Implementer1, Implementer2) или полиморфный билдер, допустим в методе Invoke(IImplementer) вашей спецификации будет дергаться кокнертные методы IImplementer которые для случая с API будут готовить одну строку по http а для случая с sql бд будут генерить sql строку, аппендить ее к результату или аналогичное
    Ответ написан
    3 комментария
  • Какая у файлов бывает архитектура?

    @AlexHell
    обычно современные форматы файлы бывают:
    -- бинарные
    * по разному сериализованные через protobuf, BSON, свой бинарный manual coded формат
    -- текстовые
    * json, xml, yaml

    exe содержит PE header и т.п.
    doc специфичный формат для MS, его можно читать/писать специальными библиотеками
    Ответ написан
    Комментировать
  • Как в микросервисах ограничивать доступ на уровне сущностей?

    @AlexHell
    Я сам не реализовывал микросервисы, но недавно на хабре читал про JSON Web Token да вот на википедии даж https://ru.wikipedia.org/wiki/JSON_Web_Token
    и вот еще про Access + Refresh Token https://habrahabr.ru/company/Voximplant/blog/323160/
    смысл в том есть служба аутентификации и выдачи токена, она своим секретным ключем шифрует токены (1 access или 2 access + refresh) и выдает клиенту, в простом случае я бы записал туда ID юзера и его Роль (админ, обычный юзер), и передавал с клиента на каждый микросервис, который его проверяет:
    -- в 1м из вариантов расшифровывает секретным ключем - тогда каждый микросервис знает о секрет ключе основном которым подписывал сервис аутентификации
    -- во 2м варианте юзаем ассимметричное шифрование т.е секрет знает толькосервис аутентификации а другие его беспроблемно расшифруют (меньше подвергаемся утечке ключа если много сервисов и не всем мы доверяем)

    во всех случаях сервис к которому обращается клиент не должен обращаться к сервису аутентификации что не замедляет скорость работы.
    Ответ написан
    Комментировать