Как можно улучшить код? (NonBlocking Threads)

Добрый день. Задача: хочу разобраться с клиентом сервером через NonBlocking операции… Для это я хочу передать серверу число и сделать некие вычисления (выбрано ряд Фибоначи)…
Вроде как всё работает, но я понимаю, что это плохой код с ООП. Подскажите, пожалуйста, на ошибки, как можно улучшить - что можно убрать (уверен, что тут опять плохое ООП). Пожалуйста, помогите…

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
 
public class Client {
    public static void main(String[] args) throws IOException {
        // Определяем сокет сервера
        InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",
                24334);
        final SocketChannel socketChannel = SocketChannel.open();
// подключаемся к серверу
        socketChannel.connect(socketAddress);
        // Получаем входящий и исходящий потоки информации
        try (Scanner scanner = new Scanner(System.in)) {
// Определяем буфер для получения данных
            final ByteBuffer inputBuffer = ByteBuffer.allocate(2 << 10);
            String msg;
            while (true) {
                System.out.println("Enter message for server...");
                msg = scanner.nextLine(); // как-то передать int
//                if ("end".equals(msg)) break;
                String b =  msg;
                socketChannel.write(
                        ByteBuffer.wrap(
                                b.getBytes(StandardCharsets.UTF_8)));
                Thread.sleep(2000);
                int bytesCount = socketChannel.read(inputBuffer);
                System.out.println(new String(inputBuffer.array(), 0, bytesCount,
                        StandardCharsets.UTF_8).trim());
                inputBuffer.clear();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            socketChannel.close();
        }
    }
}
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.lang.*;
 
public class Server {
    public static void main(String[] args) throws IOException {
        // Занимаем порт, определяя серверный сокет
        final ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.bind(new InetSocketAddress("localhost", 24334));
        while (true) {
// Ждем подключения клиента и получаем потоки для дальнейшей работы
            try (SocketChannel socketChannel = serverChannel.accept()) {
// Определяем буфер для получения данных
                final ByteBuffer inputBuffer = ByteBuffer.allocate(2 << 10);
                while (socketChannel.isConnected()) {
// читаем данные из канала в буфер
                    int bytesCount = socketChannel.read(inputBuffer);
// если из потока читать нельзя, перестаем работать с этим клиентом
                    if (bytesCount == -1) break;
// получаем переданную от клиента строку в нужной кодировке и очищаем буфер
                    final String msg = new String(inputBuffer.array(), 0, bytesCount,
                            StandardCharsets.UTF_8);
                    long nOfFibonacci = Long.parseLong(msg);
                    inputBuffer.clear();
                    Finonacci finonacci = new Finonacci(nOfFibonacci);
                    System.out.println("Получено сообщение от клиента: " + finonacci);
// отправляем сообщение клиента назад с пометкой ЭХО
                    socketChannel.write(ByteBuffer.wrap(("Эхо: " +
                            finonacci).getBytes(StandardCharsets.UTF_8)));
                }
            } catch (IOException err) {
                System.out.println(err.getMessage());
            }
        }
    }
}
public class Finonacci {
    private long nOfFibonacci;
 
 
    public Finonacci(long nOfFibonacci) {
        long num1 = 0;
        long num2 = 1;
        long counter = 0;
        long result = 0;
        while (counter < nOfFibonacci) {
            int num3;
//            System.out.print(num1+" ");
            num3 = (int) (num2 + num1);
            result = num1;
            num1 = num2;
            num2 = num3;
            counter++;
        }
        this.nOfFibonacci = result;
 
    }
 
    @Override
    public String toString() {
        return "" +this.nOfFibonacci;
    }
}

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

Лучше начать с более универсальных улучшений.

Например, тут какие-то странности с отступами, комменты почему-то в начале строки (обычно их пишут на том же уровне отступов, что и код, и обычно редакторы кода/IDE с этим помогают автоматически).
Можно добавить какой-нибудь линтер в проект/CI, чтобы он ругался на плохое форматированние, плохой/опасный код и т.д. )

И многие комменты только повторяют то, что и так в коде написано. Обычно такие комменты только вредят (надо не забыть обновить при изменении кода т.д.). Обычно комменты полезны когда они добавляют какую-то полезную инфу (почему эта странная штука сделана именно так), объясняют какие-то не очевидные вещи, оптимизации, особенности внешней системы (“тут баг ХХХ в этом древнем сервисе, поэтому пришлось YYY”).

Автоматические тесты еще можно добавить (JUnit, …). Хотя бы для изолированных от ввода/вывода штук (чистых функций), типа вычисления фибоначчи.

1 симпатия