Или еще лучше… ресторан! Я хотел бы разобрать известную аналогию в мире программирования, чтобы помочь нам лучше понять архитектуру MVC: аналогия с рестораном.

«MVC» означает «модель», «представление» и «контроллер». Это три основных элемента, которые работают вместе, чтобы разделить обязанности, которые входят в работающее приложение с полным стеком. В аналогии с рестораном Модель представлена ​​кухней, Вид представлен покупателем, а Контроллер представлен официантом. Давайте рассмотрим каждую роль отдельно, а также несколько примеров кода, чтобы разобраться в этом подробно.

Просмотр — Клиент

«Вид» в веб-приложении — это то, что видит пользователь и с чем может взаимодействовать. По сравнению с рестораном это было бы эквивалентно тому, как клиент читает меню и делает заказ вместе с официантом. Представление — это интерфейс нашего кода, которым управляют языки/фреймворки, такие как JavaScript и React.

Давайте посмотрим на пример, который я привел ниже. Здесь я вытащил фрагмент кода, представляющий запрос GET, отправленный клиентом в моем проекте Flatiron School Phase 3:

function RecipeDetails () {
    const [recipe, setRecipe] = useState({
        reviews: []
    })
    const { id } = useParams()

    useEffect(() => {
        fetch(`http://localhost:9292/recipes/${id}`)
        .then(res => res.json())
        .then(recipeData => setRecipe(recipeData))
    }, []) 

***

export default RecipeDetails;

В моем родительском компоненте App.js, который не указан выше, я настроил Route из DOM React Router, который соответствующим образом отображает вышеупомянутый компонент Recipe Details, когда пользователь хочет узнать больше о конкретном рецепте в моем приложении. Пользователь может «узнать больше» о рецепте, щелкнув ссылку, которая перенаправляет его на URL-адрес, относящийся к подробностям рецепта.

Метод useEffect() в строке 7 отправляет запрос GET к серверной части моего приложения, чтобы получить объект данных, представляющий рецепт фокуса. Затем этот объект рецепта сохраняется в состоянии, которым можно манипулировать и представлять на странице. Пользователь может даже не знать, что он — как клиент делает заказ в ресторане — только что отправил запрос на сервер приложения, перейдя на страницу «более подробной информации» конкретного рецепта.

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

Контролер — Официант

В ресторане клиент очень редко напрямую общается с поваром на кухне. Вместо этого она разговаривает с официантом, который передает это сообщение кухонному персоналу от ее имени. Точно так же контроллеры приложений в полнофункциональном приложении Ruby действуют как переход между представлением (клиентом) и моделью (сервером).

Контроллер может наследоваться от Sinatra — драгоценного камня Ruby, который позволяет разработчикам легко создавать веб-приложения, создавая маршруты. Как только контроллер приложения запущен и работает, он ожидает и прослушивает различные типы запросов. Эти запросы основаны на маршрутах, указанных во внешних URL-адресах. Получив запрос (будь то GET, POST, PATCH или DELETE), управляемый Sinatra контроллер должен передать эту информацию в базу данных.

class ApplicationController < Sinatra::Base
  set :default_content_type, 'application/json'

***
  
get "/recipes/:id" do
    recipe = Recipe.find_by(id: params[:id])
    if recipe
      recipe.to_json(
        include: [:reviews]
      )
    else
      "404 - Recipe not found"
    end
  end

***

end

Выше приведен пример маршрута Sinatra из моего проекта Фазы 3. В моем контроллере приложения я определил маршрут, который будет отвечать на запрос выборки, сделанный в моем интерфейсном компоненте Recipe Details. Этому маршруту предписывается использовать параметр :id, указанный в URL-адресе запроса GET, и работать с базой данных, чтобы найти связанный рецепт.

Как только наш, так сказать, «заказ выполнен», контроллер (например, официант) передает ответ базы данных пользователю, который его запросил. Он делает это, сначала отображая объект в формате JSON и отправляя его через Интернет туда, где возник этот запрос.

Модель — Кухня

Наконец, модели представляют собой базу данных, в которой хранятся все наши данные и другая важная информация для нашего приложения. Каждая созданная модель представляет переменную другого класса, представляющую всю таблицу данных в базе данных. Поскольку данные часто связаны друг с другом, наши Модели могут определять эти ассоциации с помощью макросов, таких как :belongs_to и :has_many.

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

Ниже приведен пример ответа, переданного серверной частью в формате JSON:

// 20230221140812
// http://localhost:9292/recipes/1

{
  "id": 1,
  "name": "Molten Lava Cake",
  "instructions": "Start by preheating your oven to 400 degrees F. Next, go ahead and coat the 2 ramekins with non-stick spray. After that, you want to melt the chocolate and butter in the microwave until smooth. Now, add the powdered sugar and stir. Then, add both the egg and the egg yolk and mix completely. Add flour and cocoa powder and stir to combine. In ramekins, divide the batter and bake for 13 minutes, or until the edges are firm but the center is jiggly. Allow the cake to cool for 2 minutes, then invert it onto a serving plate. Finally, top your Gordon Ramsay Molten Lava Cake with some powdered sugar.",
  "image_url": "https://ourtableforseven.com/wp-content/uploads/2021/12/3-4-1.jpg.webp",
  "hours": 1,
  "ingredients": "chocolate, butter, powdered sugar, eggs, flour, cocoa powder",
  "cuisine_type": "dessert",
  "isFavorited": true,
  "chef_id": 1,
  "reviews": [
    {
      "id": 2,
      "comment": "Gordon Ramsay never fails - my favorite chef does it again!!!!! best lava cake you'll ever try.",
      "rating": 5,
      "recipe_id": 1,
      "author_name": "GordanRamsayStan1000"
    },

Затем эта информация может быть преобразована в читаемый объект на интерфейсе в React, сохранена в состоянии и использована для отображения информации для пользователя.

Вы можете понять, почему модель часто сравнивают с кухней ресторана. Он отвечает за обработку заказа от клиента и отправку ответа — АКА, еда!

В заключение

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

Источники изображений:

https://achingtentacles.tumblr.com/post/159039881083

https://wifflegif.com/tags/26983-krabby-patty-gifs

https://getyarn.io/yarn-clip/ccf59356-0e54-4a29-9821-b728d385f6e0/gif

https://tenor.com/view/squidward-patrick-spongebob-squarepants-frustrated-restaurant-gif-3480132