601 lines
30 KiB
TeX
601 lines
30 KiB
TeX
|
\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}
|