2017-12-22 66 views
1

아래의 클래스를 사용하여 동기식 또는 비동기식 방식으로 소켓을 사용하여 메시징 큐에 데이터를 보내고 있습니다.클래스에서 코드 중복을 최소화 하시겠습니까?

현재로서는 아래 코드에서 많은 코드를 복제하고 있습니다. 나는 동기 또는 비동기 적으로 데이터를 전송하는 데 사용되는 5 가지 방법을 아래에 가지고 있으며 이러한 방법을 다시 작성하는 것이 더 좋은 방법 일 것이라고 생각합니다.

public class SendRecord { 
    private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); 
    private final Cache<Long, PendingMessage> cache = 
     CacheBuilder 
      .newBuilder() 
      .maximumSize(2000000) 
      .concurrencyLevel(100).build(); 

    private static class Holder { 
    private static final SendRecord INSTANCE = new SendRecord(); 
    } 

    public static SendRecord getInstance() { 
    return Holder.INSTANCE; 
    } 

    private SendRecord() { 
    executorService.scheduleAtFixedRate(new Runnable() { 
     @Override 
     public void run() { 
     handleRetry(); 
     } 
    }, 0, 1, TimeUnit.SECONDS); 
    } 

    private void handleRetry() { 
    List<PendingMessage> messages = new ArrayList<>(cache.asMap().values()); 
    for (PendingMessage message : messages) { 
     if (message.hasExpired()) { 
     if (message.shouldRetry()) { 
      message.markResent(); 
      doSendAsync(message); 
     } else { 
      cache.invalidate(message.getAddress()); 
     } 
     } 
    } 
    } 

    // called by multiple threads concurrently 
    public boolean sendAsync(final long address, final byte[] encodedRecords) { 
    PendingMessage m = new PendingMessage(address, encodedRecords, true); 
    cache.put(address, m); 
    return doSendAsync(m); 
    } 

    // called by above method and also by handleRetry method 
    private boolean doSendAsync(final PendingMessage pendingMessage) { 
    Optional<SocketHolder> liveSocket = SocketManager.getInstance().getNextSocket(); 
    ZMsg msg = new ZMsg(); 
    msg.add(pendingMessage.getEncodedRecords()); 
    try { 
     // this returns instantly 
     return msg.send(liveSocket.get().getSocket()); 
    } finally { 
     msg.destroy(); 
    } 
    } 

    // called by send method below 
    private boolean doSendAsync(final PendingMessage pendingMessage, final Socket socket) { 
    ZMsg msg = new ZMsg(); 
    msg.add(pendingMessage.getEncodedRecords()); 
    try { 
     // this returns instantly 
     return msg.send(socket); 
    } finally { 
     msg.destroy(); 
    } 
    } 

    // called by multiple threads to send data synchronously without passing socket 
    public boolean send(final long address, final byte[] encodedRecords) { 
    PendingMessage m = new PendingMessage(address, encodedRecords, false); 
    cache.put(address, m); 
    try { 
     if (doSendAsync(m)) { 
     return m.waitForAck(); 
     } 
     return false; 
    } finally { 
     cache.invalidate(address); 
    } 
    } 

    // called by a threads to send data synchronously but with socket as the parameter 
    public boolean send(final long address, final byte[] encodedRecords, final Socket socket) { 
    PendingMessage m = new PendingMessage(address, encodedRecords, false); 
    cache.put(address, m); 
    try { 
     if (doSendAsync(m, socket)) { 
     return m.waitForAck(); 
     } 
     return false; 
    } finally { 
     cache.invalidate(address); 
    } 
    } 

    public void handleAckReceived(final long address) { 
    PendingMessage record = cache.getIfPresent(address); 
    if (record != null) { 
     record.ackReceived(); 
     cache.invalidate(address); 
    } 
    } 
} 

위의 방법을 다시 쓰는 것이 더 좋은 방법이 있습니까?

+1

내가 투표를하고있어 리팩토링에 고전하고 우수한 도서있다 – GhostCat

답변

-1

Java 코드를 줄이는 두 가지 방법이 있습니다.

  1. Kotlin으로 전환하십시오.

Java 프로젝트에서 단일 kotlin 파일을 사용하거나 전체 프로젝트를 변환 할 수 있습니다. Eclipse와 Android Studio는 전체 프로젝트를 Java에서 Kotlin으로 변환 할 수 있습니다.

Kotlin 클래스 내에서 Java 클래스를 사용할 수 있으며 그 반대의 경우도 마찬가지입니다.

Kotlin에서 기본 인수를 사용할 수 있습니다.

fun doSendAsync(pendingMessage: PendingMessage, socket: Socket = SocketManager.getInstance().getNextSocket().get().getSocket()) 

소켓이 통과되면 사용됩니다. 그렇지 않으면 SocketManager.getInstance(). getNextSocket(). get(). getSocket()이 사용됩니다.

private boolean doSendAsync(final PendingMessage pendingMessage, final Socket socket) 

private boolean doSendAsync(final PendingMessage pendingMessage) 

에 대한 메소드 선언 될
    더 복잡한 방법
  1. 보내기 기본 속성을.

Java를 사용하려면 다음을 수행하십시오.

private boolean doSendAsync(final PendingMessage pendingMessage) { 
    return doSendAsync(pendingMessage), SocketManager.getInstance().getNextSocket().get().getSocket()); 
} 
2

언뜻보기에 "추출 방법"리팩터링을 몇 번 사용할 수 있습니다.

이 코드는 반복 :

ZMsg msg = new ZMsg(); 
    msg.add(pendingMessage.getEncodedRecords()); 
    try { 
     // this returns instantly 
     return msg.send(liveSocket.get().getSocket()); 
    } finally { 
     msg.destroy(); 
    } 

그래서 그것에서 개인 무효 sendMsg 같은 것을()합니다. 이 코드는

PendingMessage m = new PendingMessage(address, encodedRecords, false); 
    cache.put(address, m); 
    try { 
     if (doSendAsync(m, socket)) { 
     return m.waitForAck(); 
     } 
     return false; 
    } finally { 
     cache.invalidate(address); 
    } 

그래서 그것의 다른 방법을 반복합니다. 일반적으로

는 요청이 codereview.stackexchange.com에 속하는 코드를 작업을 검토 할 수 있기 때문에 오프 주제로이 질문을 닫습니다 https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672