\documentclass[j-spec.tex]{subfiles}
\usepackage{spreadtab}

\begin{document}
\section{Семинар: Интерфейсы и API}
\subsection{Инструментарий}
\begin{itemize}
\item \href{https://docs.google.com/presentation/d/1OBDGtC5dJz7Tu9zEJDayETOKZL0aPXne3Y8VUOGZUUU/edit?usp=share_link}{Презентация} для преподавателя, ведущего семинар;
\item \href{https://drive.google.com/file/d/1LWyE8aEy4-1gsognqhXIXwDcoLviVge4/view}{Фон} GeekBrains для проведения семинара в Zoom;
\item JDK любая 11 версии и выше;
\item \href{https://www.jetbrains.com/idea/download}{IntelliJ IDEA Community Edition} для практики и примеров используется IDEA.
\end{itemize}

\subsection{Цели семинара}
\begin{itemize}
\item Практика создания и проектирования интерфейсов;
\item передача и обработка сообщений с использованием интерфейсов;
\item Применение существующих интерфейсов для обработки исключений;
\item Отделение графического, сетевого и логического слоёв для приложения «Сетевой чат».
\end{itemize}

\subsection{План-содержание}
\noindent
\begin{spreadtab}{{longtable}{|p{37mm}|l|l|p{90mm}|}}
\hline
 @ Что происходит         & @ Время     & @ Слайды & @ Описание \\
\hline
\endhead
 @ Организационный момент & 5 tag(beg)  & @ 1-5    & @ Преподаватель ожидает студентов, поддерживает активность и коммуникацию в чате, озвучивает цели и планы на семинар. Важно упомянуть, что выполнение домашних заданий с лекции является, фактически, подготовкой к семинару \\
\hline
 @ Quiz                   & 5           & @ 6-18   & @ Преподаватель задаёт вопросы викторины, через 30 секунд демонстрирует слайд-подсказку и ожидает ответов (по минуте на ответ) \\
\hline
 @ Рассмотрение ДЗ лекции & 10          & @ 19-24  & @ Преподаватель демонстрирует свой вариант решения домашнего задания с лекции, возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов \\
\hline
 @ Вопросы и ответы       & 10          & @ 25     & @ Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы \\
\hline
 @ Задание 1              & 30          & @ 26-30  & @ Отделение бизнес-логики и графического интерфейса \\
\hline
 @ Перерыв (если нужен)   & 5           & @ 31     & @ Преподаватель предлагает студентам перерыв на 5 минут (студенты голосуют) \\ 
\hline
 @ Задание 2              & 30          & @ 32-36  & @ Создание и частичная реализация интерфейсов для улучшения понимания механизмов взаимодействия объектов \\
\hline
 @ Задание 3              & 10          & @ 37-40  & @ Написать абстрактный пример применения интерфейсов с реализацией по умолчанию и наследование \\
\hline
 @ Домашнее задание       & 5           & @ 41-42  & @ Объясните домашнее задание, подведите итоги урока \\ 
\hline
 @ Рефлексия              & 10 tag(end) & @ 43-44  & @ Преподаватель запрашивает обратную связь \\ 
\hline
 @ Длительность           & sum(cell(beg):cell(end)) & & \\
\hline
\end{spreadtab}

\subsection{Подробности}
\subsubsection*{Организационный момент}
\begin{itemize}
\item \textbf{Цель этапа:} Позитивно начать урок, создать комфортную среду для обучения.
\item \textbf{Тайминг:} 3-5 минут.
\item \textbf{Действия преподавателя:}
  \begin{itemize}
  \item Запрашивает активность от аудитории в чате;
  \item Презентует цели курса и семинара;
  \item Презентует краткий план семинара и что студент научится делать.
  \end{itemize}
\end{itemize}

\subsubsection*{Quiz}
\begin{itemize}
\item \textbf{Цель этапа:} Вовлечение аудитории в обратную связь.
\item \textbf{Тайминг:} 5--7 минут (4 вопроса, по минуте на ответ).
\item \textbf{Действия преподавателя:}
  \begin{itemize}
  \item Преподаватель задаёт вопросы викторины, представленные на слайдах презентации;
  \item через 30 секунд демонстрирует слайд-подсказку и ожидает ответов.
  \end{itemize}
\item \textbf{Вопросы и ответы:}
  \begin{enumerate}
   \item Множественное наследование в Java (3)
    \begin{enumerate}
    \item запрещено;
    \item разрешено;
    \item разрешено для интерфейсов. 
    \end{enumerate}
   \item Интерфейсы позволяют (2)
    \begin{enumerate}
    \item удобно создавать новые объекты, не связанные наследованием;
    \item единообразно обращаться к методам объектов, не связанных наследованием;
    \item полностью заменить наследование.
    \end{enumerate}
   \item Поле в интерфейсе (2)
    \begin{enumerate}
    \item невозможно;
    \item public static final;
    \item private final.
    \end{enumerate}
   \item Обработчик исключений для графического потока (2)
    \begin{enumerate}
    \item это статический метод;
    \item это интерфейс;
    \item реализован JVM.
    \end{enumerate}
  \end{enumerate}
\end{itemize}

\subsubsection*{Рассмотрение ДЗ}
\begin{itemize}
\item \textbf{Цель этапа:} Пояснить не очевидные моменты в формулировке ДЗ с лекции, синхронизировать прочитанный на лекции материал к началу семинара.
\item \textbf{Тайминг:} 15-20 минут.
\item \textbf{Действия преподавателя:}
  \begin{itemize}
  \item Преподаватель демонстрирует свой вариант решения домашнего задания из лекции;
  \item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов.
  \end{itemize}
\item \textbf{Домашнее задание из лекции:}
  \begin{itemize}
  \item Полностью разобраться с кодом -- это задание не нужно обсуждать, возможно просто спросить, кто действительно сел, взял в руки карандаш и блокнот, и попытался разобраться с кодом с лекции. Похвалить тех, кто это действительно сделал.
  \item Для приложения с шариками описать появление и убирание шариков по клику мышки левой и правой кнопкой соответственно

    \textbf{Вариант решения}

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

    \begin{lstlisting}[language=Java,style=JCodeStyle]
if (e.getButton() == MouseEvent.BUTTON1) {
    interactables[objectsCount++] = new Ball(e.getX(), e.getY());
} else if (e.getButton() == MouseEvent.BUTTON3) {
    if (objectsCount == 1) return;
    objectsCount--;
}
    \end{lstlisting}

    Для обеспечения работоспособности данного кода необходимо добавить в мячик конструктор, принимающий начальные координаты

    \begin{lstlisting}[language=Java,style=JCodeStyle]
Ball(int x, int y) {
    this();
    this.x = x;
    this.y = y;
}
    \end{lstlisting}
    
  \item Написать, выбросить и обработать такое исключение, которое не позволит создавать более, чем 15 шариков.

    \textbf{Вариант решения}

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

    \begin{lstlisting}[language=Java,style=JCodeStyle,caption={Собственно, исключение}]
public class BallsOverflowException extends RuntimeException {
    BallsOverflowException() {
        super("Balls overflow, 15 allowed!");
    }
}
    \end{lstlisting}

    По очевидным причинам выбрасывать исключение там, где добавляются шарики -- не логично, поэтому необходимо выбрасывать или на апдейте или на рендере.
    \begin{lstlisting}[language=Java,style=JCodeStyle,caption={Место выброса исключения}]
private void update(MainCanvas canvas, float deltaTime) {
    for (int i = 0; i < objectsCount; i++) {
        interactables[i].update(canvas, deltaTime);
    }
    if (objectsCount >= 15)
        throw new BallsOverflowException();
}  
    \end{lstlisting}

Для обработки исключений в Swing необходимо установить обработчик исключений для потока. сделаем этим обработчиком «себя».
    \begin{lstlisting}[language=Java,style=JCodeStyle,caption={Обработка исключения}]
private MainWindow() { //constructor
    Thread.setDefaultUncaughtExceptionHandler(this);
}

@Override
public void uncaughtException(Thread t, Throwable e) {
    if (e.getClass().equals(BallsOverflowException.class)) {
        System.out.println(e.getMessage());
    }
}  
    \end{lstlisting}

  \item ** Написать ещё одно приложение, в котором на белом фоне будут перемещаться изображения формата png, лежащие в папке проекта.

    \textbf{Вариант решения}

    Главным отличием приложения будет работа с изображением. Такова была идея примера -- тиражируемость приложения. То есть вообще весь код может быть взят из шариков или квадратиков, но в главном рисуемом объекте должен происходить не рендеринг примитива, а рендеринг картинки.

    \begin{lstlisting}[language=Java,style=JCodeStyle,caption={}]

public class Ball extends Sprite {
    private Image img = null;
    private float vX;
    private float vY;

    Ball() {
        halfHeight = 64; // logo size magic numbers
        halfWidth = 62;
        try {
            img = ImageIO.read(new File("logo.png"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        vX = 100f + (float) (Math.random() * 200f);
        vY = 100f + (float) (Math.random() * 200f);
    }

    @Override
    public void render(MainCanvas canvas, Graphics g) {
        g.drawImage(img, (int) getLeft(), (int) getTop(), null);
    }
}

    \end{lstlisting}
  \end{itemize}
\end{itemize}
  
\subsubsection*{Вопросы и ответы}
\begin{itemize}
\item \textbf{Ценность этапа} Вовлечение аудитории в обратную связь, пояснение неочевидных моментов в материале лекции и другой проделанной работе. 
\item \textbf{Тайминг} 5-15 минут
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Преподаватель ожидает вопросов по теме прошедшей лекции, викторины и продемонстрированной работы;
  \item Если преподаватель затрудняется с ответом, необходимо мягко предложить студенту ответить на его вопрос на следующем семинаре (и не забыть найти ответ на вопрос студента!);
  \item Предложить и показать пути самостоятельного поиска студентом ответа на заданный вопрос;
  \item Посоветовать литературу на тему заданного вопроса;
  \item Дополнительно указать на то, что все сведения для выполнения домашнего задания, прохождения викторины и работы на семинаре были рассмотрены в методическом материале к этому или предыдущим урокам.
  \end{itemize}
\end{itemize}

\subsubsection*{Задание 1}
\begin{itemize}
\item \textbf{Ценность этапа} Отделение бизнес-логики и графического интерфейса.
\item \textbf{Тайминг} 25-30 мин
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Выдать задание студентам;
  \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций;
  \item Пояснить студентам пользу и необходимость следования паттерну MVC, проговорить важность разделения логики и открывающиеся возможности при правильном проектировании.
  \end{itemize}
\item \textbf{Задание}:
  \begin{itemize}
  \item На предыдущем семинаре было описано окно сервера приложения, содержащее две кнопки (старт и стоп) и текстовое поле журнала. Необходимо вынести логику работы сервера в класс \code{ChatServer}, а в обработчиках кнопок оставить только логику нажатия кнопки и журналирования сообщений от сервера.

Для достижения цели необходимо описать интерфейс «слушатель сервера», с методом «получить сообщение», вызывать его с одной стороны, и реализовать с другой.  
  \textbf{Вариант решения}

    \begin{lstlisting}[language=Java,style=JCodeStyle]
//ChatServerListener.java
package ru.gb.jdk.two.sem;

public interface ChatServerListener {
    void onMessageReceived(String msg);
}

//ChatServer.java

package ru.gb.jdk.two.sem;

public class ChatServer {
    private boolean isServerWorking;
    private final ChatServerListener listener;
    
    ChatServer(ChatServerListener listener) {
        isServerWorking = false;
        this.listener = listener;
    }
    
    public void start() {
        if (isServerWorking) {
            listener.onMessageReceived("Server is already working");
            return;
        }
        listener.onMessageReceived("Server started");
        isServerWorking = true;
    }
    
    public void stop() {
        if (!isServerWorking) {
            listener.onMessageReceived("Server is stopped");
            return;
        }
        listener.onMessageReceived("Server stopped");
        isServerWorking = false;
    }
}

//ServerWindow.java
//constructor
server = new ChatServer(this);

btnStop.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        server.stop();
    }
});

btnStart.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        server.start();
    }
  });

// method implementation
@Override
public void onMessageReceived(String msg) {
    log.append(msg + "\n");
}

\end{lstlisting}

  \item [$*_1$] Отделить функционал логгирования сообщений сервера для простоты изменения способа оповещения пользователя.
  
  \textbf{Вариант решения}

    \begin{lstlisting}[language=Java,style=JCodeStyle]
@Override
public void onMessageReceived(String msg) {
    putMessageToLog(msg);
}

private void putMessageToLog(String msg) {
    log.append(msg + "\n");
}
    \end{lstlisting}

  \end{itemize}
\end{itemize}

\subsubsection*{Задание 2}
\begin{itemize}
\item \textbf{Ценность этапа} Создание и частичная реализация интерфейсов для улучшения понимания механизмов взаимодействия объектов.
\item \textbf{Тайминг} 25-30 мин
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Выдать задание студентам;
  \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций;
  \item Если группа студентов справилась с заданием, а времени осталось более 5 минут, выдавать группе задания «со звёздочкой».
  \end{itemize}
\item \textbf{Задание}:
  \begin{itemize}
  \item Создать интерфейсы \code{ServerSocketThreadListener} и \code{SocketThreadListener}, содержащие методы, соответствующие событиям сервера и клиента чата. Реализовать созданные интерфейсы простым логированием. Со стороны клиента -- только \code{SocketThreadListener}, со стороны сервера -- оба интерфейса.
    
  \textbf{Вариант решения}

\begin{lstlisting}[language=Java,style=JCodeStyle]
package ru.gb.jdk.two.sem.network;

import java.net.Socket;

public interface SocketThreadListener {
    void onSocketStart(Socket s);
    void onSocketStop();

    void onSocketReady(Socket socket);
    void onReceiveString(Socket s, String msg);

    void onSocketException(Throwable e);
}

package ru.gb.jdk.two.sem.network;

import java.net.ServerSocket;
import java.net.Socket;

public interface ServerSocketThreadListener {
    void onServerStart();
    void onServerStop();
    void onServerSocketCreated(ServerSocket s);
    void onServerSoTimeout(ServerSocket s);
    void onSocketAccepted(ServerSocket s, Socket client);
    void onServerException(Throwable e);
}
\end{lstlisting}

\begin{lstlisting}[language=Java,style=JCodeStyle]
  // Server

/**
 * Server socket thread methods
 * */
@Override
public void onServerStart() { listener.onMessageReceived("Server thread started"); }

@Override
public void onServerStop() { listener.onMessageReceived("Server thread stopped"); }

@Override
public void onServerSocketCreated(ServerSocket s) { listener.onMessageReceived("Server socket created"); }

@Override
public void onServerSoTimeout(ServerSocket s) {
    // listener.onMessageReceived("Accept timeout");
}

@Override
public void onSocketAccepted(ServerSocket s, Socket client) { listener.onMessageReceived("client connected"); }

@Override
public void onServerException(Throwable e) { e.printStackTrace(); }

/**
 * Socket Thread listening
 * */
@Override
public synchronized void onSocketStart(Socket s) { listener.onMessageReceived("Client connected"); }

@Override
public synchronized void onSocketStop() { listener.onMessageReceived("Client dropped"); }

@Override
public synchronized void onSocketReady(Socket socket) { listener.onMessageReceived("Client is ready"); }

@Override
public synchronized void onReceiveString(Socket s, String msg) { listener.onMessageReceived(msg); }

@Override
public void onSocketException(Throwable e) { e.printStackTrace(); }

// Client
@Override
public void onSocketStart(Socket s) { log.append("Started" + "\n"); }

@Override
public void onSocketStop() { log.append("Stopped" + "\n"); }

@Override
public void onSocketReady(Socket socket) { log.append("Ready" + "\n"); }

@Override
public void onReceiveString(Socket s, String msg) { log.append(msg + "\n"); }

@Override
public void onSocketException(Throwable e) { e.printStackTrace(); }
\end{lstlisting}
  
  \item [$*_1$] Создать классы -- \code{ServerSocketThread} и \code{SocketThread}, соответственно слушателям, то есть реализовать в классе конструкторы с возможностью сохранения ссылки на слушателей. Создать экземпляр \code{ServerSocketThread} из объекта \code{ChatServer}, а \code{SocketThread} из \code{ClientGUI}. На данном этапе, не важно, где именно будут создаваться эти объекты.

  \textbf{Вариант решения}
    
  \begin{lstlisting}[language=Java,style=JCodeStyle]
package ru.gb.jdk.two.sem.network;

public class ServerSocketThread {
    private ServerSocketThreadListener listener;

    public ServerSocketThread(ServerSocketThreadListener listener) {
        this.listener = listener;
    }
}

package ru.gb.jdk.two.sem.network;

public class SocketThread {
    private final SocketThreadListener listener;

    public SocketThread(SocketThreadListener listener) {
        this.listener = listener;
    }  
}

// Server
private ServerSocketThread server;


public void start() {
    if (isServerWorking) {
        listener.onMessageReceived("Server is already working");
        return;
    }
    server = new ServerSocketThread(this);
    listener.onMessageReceived("Server started");
    isServerWorking = true;
}

//Client
private void connect() {
    SocketThread socketThread = new SocketThread(this);
}
\end{lstlisting}

  \end{itemize}
\end{itemize}

\subsubsection*{Задание 3}
\begin{itemize}
\item \textbf{Ценность этапа} Написать абстрактный пример применения интерфейсов с реализацией по умолчанию и наследованием.
\item \textbf{Тайминг} 10-15 мин
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Выдать задание студентам;
  \item Подробно объяснить, что именно требуется от студентов, избегая упоминания конкретных языковых конструкций;
  \end{itemize}
\item \textbf{Задание}:
  \begin{itemize}
  \item Описать команду разработчиков. В команде разработчиков могут находиться бэкендеры, которые в состоянии писать серверный код, фронтендеры, которые могут программировать экранные формы, и фуллстэк разработчики, совмещающие в себе обе компетенции. Реализовать класс фулстэк разработчика, создать экземпляр и последовательно вызвать все его методы.
  
  \textbf{Вариант решения}

  \begin{lstlisting}[language=Java,style=JCodeStyle]
package ru.gb.jdk.two.sem.devs;

public interface Backender { void developServer(); }

public interface Frontender { void developGUI(); }

public interface Fullstack extends Backender, Frontender {
}

public class FullstackDeveloper implements Fullstack {
    @Override
    public void developServer() { System.out.println("Server done"); }

    @Override
    public void developGUI() { System.out.println("GUI done"); }
}

public class Main {
    public static void main(String[] args) {
        FullstackDeveloper dev = new FullstackDeveloper();
        dev.developGUI();
        dev.developServer();
    }
}
\end{lstlisting}
  
  \item [$*_1$] Добавить возможность при создании экземпляров классов любых интерфейсов -- добавлять их в один массив, например, \code{Developer[] team = {...};}

  \textbf{Вариант решения}

  К первому решению добавляется маркерный интерфейс «Разработчик». Очевидно, что нельзя для этого интерфейса вызвать более точные методы фуллстэк разработчика.
  \begin{lstlisting}[language=Java,style=JCodeStyle]
package ru.gb.jdk.two.sem.devs;

public interface Developer {
}

public interface Backender extends Developer { void developServer(); }

public interface Frontender extends Developer { void developGUI(); }

public class Main {
    public static void main(String[] args) {
        Developer dev = new FullstackDeveloper();
    }
}

\end{lstlisting}

\end{itemize}
\end{itemize}

\subsubsection*{Домашнее задание}
\begin{itemize}
\item \textbf{Ценность этапа} Задать задание для самостоятельного выполнения между занятиями. В данном семинаре домашнее задание не предусмотрено в связи со сложностью заданий семинара. Необходимо досконально разобраться в написанном (и запланированном коде) и взаимосвязях объектов. Также возможно уточнить, что задания семинара направлены на написание многопоточного сетевого чата, но, поскольку это будет достаточно сложный проект, его написание приводится постепенно
\item \textbf{Тайминг} 5-10 минут.
\item \textbf{Действия преподавателя}
  \begin{itemize}
  \item Пояснить студентам в каком виде выполнять и сдавать задания
  \item Уточнить кто будет проверять работы (преподаватель или ревьювер)
  \item Объяснить к кому обращаться за помощью и где искать подсказки
  \item Объяснить где взять проект заготовки для дз
  \end{itemize}
\item \textbf{Задания}
  \begin{enumerate}
  \item [5-25 мин] Выполнить все задания семинара, если они не были решены, без ограничений по времени;

    \textbf{Все варианты решения приведены в тексте семинара выше}
  \item [5 мин] 1. Дописать третье задание таким образом, чтобы в идентификатор типа \code{Developer} записывался объект \code{Frontender}, и далее вызывался метод \code{developGUI()}, не изменяя существующие интерфейсы, только код основного класса. 
  
    \begin{lstlisting}[language=Java,style=JCodeStyle]
public class Main {
    public static void main(String[] args) {
        Developer dev = new FrontendDeveloper();
        if (dev instanceof Frontender) {
            ((Frontender) dev).developGUI();
        }
    }
}
    \end{lstlisting}
  \end{enumerate}
\end{itemize}

\subsubsection*{Рефлексия и завершение семинара}
\begin{itemize}
\item \textbf{Цель этапа:} Привести урок к логическому завершению, посмотреть что студентам удалось, что было сложно и над чем нужно еще поработать
\item \textbf{Тайминг:} 5-10 минут
\item \textbf{Действия преподавателя:}
  \begin{itemize}
  \item Запросить обратную связь от студентов.
  \item Подчеркните то, чему студенты научились на занятии.
  \item Дайте рекомендации по решению заданий, если в этом есть необходимость
  \item Дайте краткую обратную связь студентам.
  \item Поделитесь ощущением от семинара.
  \item Поблагодарите за проделанную работу.
  \end{itemize}
\end{itemize}

\newpage
\end{document}
