Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > В чем здесь быдлокодинг?


Автор: apv1989 14.6.2011, 15:36
Здравствуйте, учусь java (api в основном, язык то, конечно, си-стайл знаком), хотя в общем то программирую не первый год и это не первый мой язык ООП.
Да вот только когда старший программист увидел этот код, полез сначала на потолок, потом с него упал, потом закатился под стол, корчась толи от боли, то ли от смеха, не знаю в общем.
Вердикт был: зарефакторить абсолютно все. Каждую строчку буквально. 
Что тут такого страшного, скажите пожалуйста?

Код

public class ViewPhoto extends HttpServlet {
    private void sendPhoto(byte[] photo, HttpServletResponse resp) throws IOException {
        resp.setHeader("Cache-Control", "no-cache");
        resp.setHeader("pragma", "no-cache");
        String format = ImageIO.getImageReaders(ImageIO.createImageInputStream(new ByteArrayInputStream(photo))).next().getFormatName().toLowerCase();
        String mimeType = "image/" + format;
        resp.setContentType(mimeType);
        resp.setContentLength(photo.length);
        OutputStream out = resp.getOutputStream();
        out.write(photo);
        out.close();
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int id = Integer.valueOf(req.getParameter("id"));
        String table = req.getParameter("writeTo");
        String type = req.getParameter("type");


        try {
            AddPetService service = BeanProvider.getBean();
            if ("mzsr".equals(table)) {
                MzsrAddressee addressee = service.getMzsrAddressee(id);
                if ("small".equals(type) && addressee.getBossSmallPhoto() != null) {
                    sendPhoto(addressee.getBossSmallPhoto(), resp);
                    return;
                } else if ("big".equals(type) && addressee.getBossPhoto() != null) {
                    sendPhoto(addressee.getBossPhoto(), resp);
                    return;
                }
            }
            if ("kiosk".equals(table)) {
                KioskAddressee addressee = service.getKioskAddressee(id);
                if ("small".equals(type) && addressee.getBossSmallPhoto() != null) {
                    sendPhoto(addressee.getBossSmallPhoto(), resp);
                    return;
                } else if ("big".equals(type) && addressee.getBossPhoto() != null) {
                    sendPhoto(addressee.getBossPhoto(), resp);
                    return;
                }
            }
        } catch (NamingException e) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        getServletContext().getRequestDispatcher("/i/no_photo.jpg").forward(req, resp);
    }
}


Автор: danilych 14.6.2011, 16:38
Цитата

A typical design mistake made by inexperienced developers is to mix different types of logic
(e.g., presentation logic, business logic, and data access logic) in a single large module. This
reduces the module’s reusability and maintainability...

из книги Spring Recipes A Problem-Solution Approach Gary Mak

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

Автор: dobrolub 14.6.2011, 19:15
Я бы переписал логику более прямолинейно. (см. правильный коммент от самотника, внизу)

Код

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int id = Integer.valueOf(req.getParameter("id"));
        String table = req.getParameter("writeTo");
        String type = req.getParameter("type");
        try {
            AddPetService service = BeanProvider.getBean();
            AbstractAddressee addressee = null;
            if ("mzsr".equals(table))
              addressee = service.getMzsrAddressee(id);
            else if ("kiosk".equals(table))
              addressee = service.getKioskAddressee(id);
             
            byte[] photo = null;
            if (addressee == null) {
            }
            else if ("big".equals(type)) {
               photo = addressee.getBossPhoto();
            }
            else if ("small".equals(type)) {
               photo = addressee.getBossSmallPhoto();
            }
           
            if (photo != null)
               sendPhoto(photo, resp);
            else
               getServletContext().getRequestDispatcher("/i/no_photo.jpg").forward(req, resp);
        } catch (NamingException e) {
            e.printStackTrace();

            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }

Автор: Samotnik 14.6.2011, 19:17
apv1989, слишком много вложенных if/else конструкций и вызовов метода sendPhoto

Добавлено через 2 минуты и 38 секунд
dobrolub, даже решение выложил  smile 

Автор: apv1989 15.6.2011, 09:13
Спасибо всем.

Чувствую себя индусом.  smile 

C удовольствием бы AbstractAddressee сделал, но это две сущности JPA, абсолютно одинаковые, но привязанные к разным таблица, а mappedsuperclass использовать нельзя. 

Автор: powerOn 15.6.2011, 12:27
я бы посмотрел в сторону http://www.industriallogic.com/xp/refactoring/composeMethod.html рефакторинга.

Автор: COVD 15.6.2011, 15:49
Цитата

Чувствую себя индусом

Главное, не используйте этот жаргон - "индус", "быдлокод". Это дурной тон. И все получится. 

Автор: Samotnik 15.6.2011, 17:22
Цитата(COVD @  15.6.2011,  15:49 Найти цитируемый пост)
Главное, не используйте этот жаргон - "индус", "быдлокод". Это дурной тон. И все получится.  

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

Автор: dobrolub 15.6.2011, 19:10
Код

public interface PhotoProvider {
  byte []getPhoto();
  byte []getSmallPhoto();
}

public class MzsrAddressee implements PhotoProvider {
 ...
}

public class KioskAddressee implements PhotoProvider {
  ...
}

...
  - AbstractAddressee adressee;
...
  + PhotoProvider photoProvider = null;
            if ("mzsr".equals(table))
              photoProvider = (PhotoProvider)service.getMzsrAddressee(id);
            else if ("kiosk".equals(table))
              photoProvider = (PhotoProvider)service.getKioskAddressee(id);

...

Автор: v2v 20.6.2011, 18:42
1. Вместо строк смол, биг, киоск и т.д. использовать констатны.
2. Избежать дубликации кода (строчки 25-30 и 35-40 в отдельный метод).

Автор: Rasool 22.6.2011, 17:44
А как присутствующие относятся к книге "Рефакторинг. Улучшение существующего кода" Мартина Фаулера в переводе С.Маккавеева? По ней можно учиться культуре программирования?

Автор: powerOn 22.6.2011, 22:27
Цитата(Rasool @  22.6.2011,  18:44 Найти цитируемый пост)
А как присутствующие относятся к книге "Рефакторинг. Улучшение существующего кода" Мартина Фаулера в переводе С.Маккавеева?


хорошо, но лучше в оригинале.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)