Глава 17 · Архитектура

Архитектура TicTacToeApp

app.root, а не class TicTacToeApp(tk.Tk) — та же композиция, что и в главе 16.

app HAS-A root — не наследование от Tk

Композиция против наследования
Возможно, но не нужно
class TicTacToeApp(tk.Tk):
    def __init__(self):
        super().__init__()
        ...
Как в главе 16
class TicTacToeApp:
    def __init__(self, root):
        self.root = root
        ...
Что использовать сегодня: Наследование от tk.Tk технически работает, но не нужно и не согласуется с тем, как строились приложения в главе 16. app.root (композиция, «HAS-A») — тот же паттерн, что и у Tip Calculator Pro и редактора заметок.

Объектный граф приложения

app : TicTacToeApproot = Tkstate = GameStatebuttons = list[Button]status_var = StringVarscore_var = StringVar
app хранит виджеты и ССЫЛКУ на состояние — не наоборот.

Домен против UI — разделение ответственности

Чистая доменная логика (без Tkinter)UI-логика (внутри TicTacToeApp)
find_winner(board)on_cell_click / attempt_move — вызывает домен, потом render
is_draw(board)on_cell_enter / on_cell_leave — превью
index → row/columnrender() — рисует виджеты ИЗ модели (state)
new_round() / new_match() — жизненный цикл
Проверка «можно ли протестировать без окна?»
Хороший тест архитектуры: если для проверки функции обязательно открывать окно Tkinter — это, вероятно, UI-логика. Если можно вызвать её с обычными списком/строкой и получить результат — это доменная логика, и её МОЖНО было бы вынести в отдельный модуль.
Практика: собираем объектный граф TicTacToeApp
Модуль tkinter открывает нативное окно Python — выполните локально в VS Code, PyCharm или Jupyter
Практика выполняется локально
Открыть практику →