• Как дата-саентисты в ВК делают рекламу эффективной
    0

    Одно дело когда реклама реально полезна, т.е. потенциально ты можешь купить товар и останешься доволен, другое — когда это откровенный развод. Я писал модераторам, скидывал линки на прувы о том что это мошенники, реакции 0. Лично мне бы было стыдно работать над этим, а они ещё и на хабр стать ю запили.

  • Аки Феникс
    +2

    А вы не задумывались, во что бы превратилась компания, если бы все вели себя так как вы, приходили в таком же каком состоянии итд? Вы ничем не лучше остальных людей, и все вот эти рассказы о том что я делаю свою работу так классно, лучше всех, но директор меня не любит звучат по детски(подучить линуху, ну понятно) и как правило далеки от реальности, незаменимых людей нет, в серьезной компании вас бы вышвырнули сразу.

  • Spring + Firebird + REST. Часть 1 Конфигурирование проекта
    +1
    Здравствуйте, я посмотрел ваш код на гитхабе и написал несколько замечаний с рекомендациями, вообщем небольшое такое код-ревью провёл, раз уж вы выложили код на хабр:)

    1. для чего в CProductService аннотации @Transactional над самим классом и методами create и update? Они явно лишние на мой взгляд, что касается метода delete, я не помню его поведение в случае попытки удалить несуществующую сущность, по-моему падает эксепшн — что лучше, 2 раза сходить в БД или ловить эксепшны, вопрос спорный, если у кого есть какие мысли — пишите, мне тоже интересно
    2.Хьюстон, тут у нас явно проблемы…
    final CProduct [] arr=new CProduct[1];
            arr[0]=null;
            findAll().stream().forEach(x -> {if(name.compareTo(x.getName()) == 0){
                arr[0]=x;
            }});
    
            if(arr[0] != null){
                return arr[0];
            }else{
                throw new CProductNotFoundException(name);
            }

    a. Почему findAll()? вытаскивать все продукты из БД и бегать по ним стримом на стороне сервера в будущем будет очень жирно, тем более что уже есть метод productRepository.findByName
    b.
    name.compareTo(x.getName()) == 0
    — весьма странное решение, если вы не собираетесь ничего сортировать, достаточно equals или equalsIgnoreCase
    с. создавать массив с 1 элементом чтобы его поменять… примерно тоже самое будет выглядеть как-нибудь вот так:
    productRepository.findByName(name) 
                             .stream()
                             .filter(it -> it.getName().equalsIgnoreCase(name))
                             .findAny()
                             .orElseThrow(() -> new CProductNotFoundException(name))
    

    Но вообще я не понял смысла этого метода т.к. уже есть findByName, и по сигнатуре они похожи:
    public List<CProduct> findByName(String name)
    public CProduct findOne(String name) throws CProductNotFoundException 
    

    … можно было сделать что-то вроде:
            List<CProduct> products = productRepository.findByName(name);
            if (products.isEmpty()){
                throw new CProductNotFoundException(name);
            }
            return products.get(0);
    

    но ещё короче было бы сделать всё в репозитории с помощью аннотации Query(nativeQuery = true, ...)
    3. пункт 1 и 2 актуальны для всех сервисов как оказалось, т.к. там везде примерно одинаково
    4. вообще в моей практике пакет с @RestController'ами всегда так и называли — controller, реже — rest… но это уже на ваше предусмотрение, просто resources я ещё не встречал
    5. пакеты названы то в единственном числе, то во множественном — нужно единообразие
    6. возвращать из контроллеров ResponseEntity.ok нет смысла, они итак будут по-умолчанию 200, если нужны разные статусы, тогда ок, но можно было бы это делать через @ControllerAdvice, т.к. как правило логика примерно одинакова
    7. CHomeResource возвращает статику, можно было бы возвращать чистый html из ресурсов
    8. в CMViewRepResource
    @GetMapping
        public ResponseEntity<byte[]> report(String moduleName){
            byte[] bytes = null;
            try {
                bytes = jreportService.getMainReportPdfAsBytes(main_template_path);
                return ResponseEntity.ok()
                        .header("Content-Type", "application/pdf; charset=UTF-8")
                        .header("Content-Disposition", "inline; filename=\"" + moduleName + ".pdf\"")
                        .body(bytes);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

    очень странно что вы возвращаете null, когда у вас есть ResponseEntity, можно возвращать код с ошибкой
    9. совсем нет логирования
    10. JasperReportService не бин, он не будет инжектиться в CMViewRepResource, будет NPE
    11. лучше пользоваться интерфейсами, когда пишите сервисы