что такое спагетти код

Что такое «спагетти код»?

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Код «Спагетти» (от английского словосочетания spaghetti code) — простыми словами, это уничижительное жаргонное описание некачественного программного продукта, который в силу различных факторов приходит ко всё менее оптимизированному виду. Иногда неправильно называют «лапша код» (относится к штрих-коду).

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

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Почему спагетти код — это ругательство?

Предприниматель может обвинить разработчика в создании кода спагетти и выставить неустойку. Организация в этой ситуации здорово рискует. После долгих лет работы и инвестиций в проект, ИТ-менеджеров и другие ресурсы, поддержка становится всё более дорогостоящей. В конце концов, спагетти код сделает её нерентабельной.

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Как избежать спагетти кода?

Попытки привлечь других программистов приводят к значительным потерям по времени и не гарантируют результат. Новым исполнителям приходится исследовать и перекодировать инфраструктуру проекта только для того, чтобы что-то перестало «ломаться». Затем им приходится изучать годы выполненной работы, часто управляемой разными разработчиками, чтобы определить источник проблемы, если её вообще возможно решить.

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

Усердие и внимание к деталям

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

Тестирование модулями

Регулярные тесты должны выполняться модульно. Комплексный подход хорош на прохождении определённых этапов развития проекта. Однако внимание деталям уделяется больше всего на промежуточных модульных тестированиях.

Проверяйте программистов

Дополнительная пара глаз не помешает. Если вы столкнетесь с признаками кода спагетти, обратитесь к другому программисту или другой команде разработчиков (например, на аутсорсинге), чтобы убедиться в опасениях и внести изменения пока ещё не поздно.

Фреймворки полегче

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

Принцип «слоёного теста»

В крупных проектах «Spaghetti Code» — неизбежность. Реализуйте в таком случае архитектуру «слоёной» разработки. Так легче локально корректировать запутанный код и сохранять функциональность других слоёв.

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

В англоязычном сообществе софт ещё обзывают:

PS: приятного аппетита, наши дорогие айтишники и предприниматели!

Обратитесь в компанию ИТ-аутсорсинга для дальнейшей экспертной поддержки и консультации по этой теме и любым другим техническим вопросам.

Источник

Убираем спагетти-код

Два подхода к упорядочиванию хаоса.

Когда мы делали свой Трелло-планировщик из Бутстрапа и нашего списка задач, у нас появился спагетти-код. Это значит, что для простоты и скорости решения мы скопировали одинаковые куски кода, которые делают почти одно и то же. У них внутри одинаковая логика, но разные входные данные, и мы их просто скопировали-вставили.

У такого подхода к программированию есть несколько проблем:

Единственное, когда можно использовать такой подход — если нужно что-то быстро протестировать и понять, работает оно или нет. Если не работает — значит, мы сэкономили время и не стали тратить его на неудачное решение. А если всё работает как нужно, значит, настало время переписать код в нормальном виде. Для этого нам понадобится некоторое подобие объекта, но не на основе класса, а созданное вручную.

Мы хотели ООП, но не смогли

Изначально мы хотели на этом примере показать силу классов и объектов в объектно-ориентированном программировании. Но, разобравшись, поняли, что классы только всё усложнят, не принеся нам существенной пользы.

Поэтому мы будем использовать объекты, но без классов. А силу классов мы показали в игре на Питоне — посмотрите, вам понравится.

Новый тип переменной: объект

У переменной типа «объект» есть одна отличительная особенность: она состоит как бы из двух частей — свойства и значения. Мы про это говорили в статье про объекты в ООП, и здесь всё то же самое — у объекта меняются только значения свойств. Поясним на примере языка JavaScript.

Сделаем переменную-объект, у которой будет два свойства — имя и возраст:

Чтобы поменять имя, нужно написать название переменной и через точку указать название свойства, которое хотим изменить:

Свойств у объекта может быть сколько угодно:

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

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

Собираем дубли

Пройдёмся по нашему старому коду из прошлой статьи и соберём все одинаковые переменные, которые отличаются только цифрами:

Первые две переменные задают ссылку на объект и маску для сравнения элементов, а вторые две отвечают за количество задач в колонках.

Свернём эти 16 переменных в один большой объект:

Теперь, зная только номер колонки, мы можем обратиться к объекту, маске и количеству задач в колонке. Сначала это может показаться громоздким, но на самом деле сокращает наш финальный объём программы в 4 раза.

Чтобы избавиться от дублей в коде, используют циклы или выносят повторяющийся код в отдельную функцию. На самом деле вариантов больше, но основные — эти.

Используем цикл

Циклы применяют в тех случаях, когда спагетти-код по очереди используется несколько раз, где отличаются только порядковые номера элементов. В нашем случае это функция showTasks(). Она берёт по очереди все элементы из локального хранилища и по очереди же сравнивает их с шаблоном — для первой, второй, третьей или чётвёртой колонки. Единственное, чем отличаются фрагменты — маской и колонкой, куда их отправлять:

Сделаем то же самое в цикле, используя нашу большую переменную-объект. Для этого мы организуем цикл от 0 до 3 (потому что нумерация элементов массива начинается с нуля) и по очереди проверяем все значения:

Код сократился в 4 раза, читать стало проще, и всё меняется в одном месте. Красота.

Делаем отдельную функцию

У нас есть вот такой огромный кусок кода, который делает одно и то же, только с разными элементами.

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

Что дальше

Мы только что убрали почти весь спагетти-код из нашего проекта. Почти — потому что у нас осталось два неопрятных фрагмента:

Оба фрагмента можно оптимизировать, например, с помощью jQuery.

Попробуйте сделать это сами, пока это не сделали мы 🙂

Источник

ТОП-10 признаков плохого кода: хардкод и спагетти-код в примерах на JavaScript

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Многие программисты не знают, что пишут плохой код.

Скорее всего, конкретно вы уже заходили на GitHub, сохранить свой код, посмотреть на чужой. А теперь посмотрите на собственные старые проекты, написанные годом ранее — вы удивитесь, насколько лучше стали ваши навыки с того момента.

Большинство младших программистов (и даже некоторые более опытные) не знают, как отличить хороший код от плохого. Когда программа заработает — они сразу идут дальше. К тому же, если они работают в одиночку, то никогда даже не узнают, что пишут плохой код.

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

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

1. Повсюду скопированный код

Подобное случается с каждым программистом, стоит только перестать стараться писать чистый код.

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

Конечно, ведь всегда проще скопировать-вставить, чем написать функцию. Но вопрос состоит в том, когда подобный метод применим, а когда — только навредит кодовой базе?

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

2. Одинаковые функции, но разный интерфейс

Постоянство — качество хорошего программиста: старайтесь следовать шаблону, ведь вам придется написать еще очень много функций.

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

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

3. Хардкод

Все ненавидят жесткий кодинг, “хардкод”. Хорошо, что его появление легко заметить и предотвратить. Проанализируйте следующий фрагмент кода:

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

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

Большинство проектов подключаются к облачным сервисам. Если ваши проекты синхронизированы с какими-либо из них, то лучше сразу получать данные из облака согласно его стандарту.

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

4. Слишком длинные и сложные условия

Определение достаточно абстрактное, так что же имеется в виду?
Во-первых, не стоит писать “ спагетти-код” — слишком конкретные и длинные условия со множеством проверок и категорий.

Тем не менее, второй совет — противоположность первого:
НЕ пишите сложные условия ради экономии в пару строк. Если вам придется написать две лишние строки, но код станет понятнее, то пишите эти строки с уверенностью. Проанализируйте следующие два примера:

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

5. Велосипед вместо встроенной функции

Непонятно, почему до сих пор далеко не каждый разработчик на земле применяет встроенные инструменты и функции.

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

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

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

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

6. Игра в загадочные имена

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

Вы догадались, что делает метод? Никто не догадался. Следовательно, следующий программист, прочитавший код, наверняка проклянет вас. Потому что ему, вероятно, придется вчитываться в каждую строчку функции, долго и постепенно понимая, что она делает.

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

7. Сплошь глобальные переменные

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

Почему? Много причин для превалирования локальных переменных над глобальными. Поговорим о некоторых основных:

Если везде только глобальные переменные, значит, вы плохой программист. Извините за обидное, но правдивое высказывание.

8. Запутанный код

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

Однажды программист ответил, что запутанный код делает компанию зависимой от него — работа ему обеспечена.

Но это очень неправильная концепция, крайне вредная идея. Гораздо лучше руководствоваться следующим:
“Загадочность” — плохо. “Легкость” — хорошо.

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

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

9. Взаимозависимые функции

Код весьма плох, когда функции выполняются исключительно в строгом порядке. Рассмотрим пример:

Функции работают независимо друг от друга.

Решением “на каждый раз” послужит специальный метод-шаблон. Рассмотрим пример на языке программирования JavaScript:

10. Нет понимания сложности алгоритма

Начинающие программисты часто пишут лишние вложенные циклы. Тем более, когда менталитет “ достаточно выполнить работу и запустить код” превращает программиста в неэффективного лентяя. Правда, производительность приложения — скорее дело привычки:

Когда команда не ценит хороший код и не заботится о качестве, то программисты не заботятся о временной сложности алгоритма и сложности алгоритма по памяти

Если вы разбираетесь в оценке сложности алгоритмов и пишете эффективный код — он даст вам силы, а если не обращаете внимание на детали реализации, то не сможете изменить шаблоны, остановившись в развитии профессиональных навыков.

Многие программисты даже не знают про “ сложность алгоритма по памяти” или “memory complexity”. Если вы не знаете, пожалуйста, узнайте, ведь это поможет на собеседованиях.

Выводы

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

Источник

Автоматы против спагетти-кода

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

«Люблю спагетти-вестерны, ненавижу спагетти-код»

«Спагетти-код» — это идеальное выражение для описания ПО, представляющего собой дымящийся хаос и с когнитивной, и с эстетической точки зрения. В этой статье я расскажу о плане из трёх пунктов по уничтожению спагетти-кода:

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

Уродливость спагетти-кода заключается в его сложной условной логике. И хотя жизнь может быть сложно представить без множества хитрых конструкций if-then-else, эта статья покажет вам решение получше.

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Чтобы проиллюстрировать ситуацию со спагетти-кодом, нам нужно для начала превратить это:

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Давайте приступим к готовке.

Неявное состояние

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

Вот простой пример:

Что на самом деле делает эта проверка? Очевидно, она делит числовую прямую на две части, но что означают эти части? Думаю, вы можете сделать логичное предположение, но проблема в том, что код на самом деле не сообщает этого явно.

Если я действительно подтвержу, что она проверяет, является ли вода ТВЁРДОЙ [прим. пер.: по шкале Фаренгейта вода замерзает при +32 градусах], то что будет логически означать возвращаемое false?

Хотя проверка разделила числа на две группы, на самом деле существует три логических состояния — твёрдое тело, жидкость и газ (SOLID, LIQUID, GAS)!

То есть эта числовая прямая:

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

разделена проверкой условия следующим образом:

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Заметьте, что произошло, потому что это очень важно для понимания природы спагетти-кода. Булева проверка разделила числовое пространство на две части, но НЕ категоризировала систему как настоящую логическую структуру из (SOLID, LIQUID, GAS). Вместо этого проверка разделила пространство на (SOLID, всё остальное).

Вот похожая проверка:

Визуально это будет выглядеть так:

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Мне всё равно никогда не нравился твой код

Показанный выше код подразумевает существование трёх состояний вещества — SOLID, LIQUID, GAS. Однако согласно научным данным на самом деле есть четыре наблюдаемых состояния, в которые включается плазма (PLASMA) (на самом деле есть и множество других, но нам будет достаточно и этого). Хотя никто не готовит пасту из плазмы, если этот код будет опубликован на Github, а затем его форкнет какой-нибудь аспирант, изучающим физику высоких энергий, то нам придётся поддерживать и это состояние тоже.

Однако при добавлении плазмы показанный выше код наивным образом будет выполнять следующее:

Вполне вероятно, что старый код при добавлении ко множеству состояний плазмы сломается в ветвлениях else. К сожалению, ничто в структуре кода не помогает сообщить о существовании нового состояния или повлиять на изменения. Кроме того, любые баги скорее всего окажутся малозаметными, то есть, найти их будет сложнее всего. Просто скажи «нет» насекомым в спагетти.

Если вкратце, то проблема заключается в следующем — булевы проверки используются для определения состояний косвенно. Логические состояния часто не объявляются и не видны в коде. Как мы увидели выше, когда система добавляет новые логические состояния, существующий код может сломаться. Чтобы избежать этого, разработчики должны заново изучить каждую отдельную условную проверку и ветвление, чтобы убедиться, что пути кода по-прежнему верны для всех соответствующих им логических состояний! Это основная причина деградации больших фрагментов кода при их усложнении.

Хоть и не существует способов полностью избавиться от условных проверок данных, любая минимизирующая их техника будет снижать сложность кода.

Давайте теперь рассмотрим типичную объектно-ориентированную реализацию класса, создающую очень простую модель объёма воды. Класс будет управлять изменениями состояния вещества воды. Изучив проблемы классического решения этой задачи, мы затем обсудим новую нотацию под названием Frame и покажем, как она может справляться с обнаруженными нами трудностями.

Сначала доведите воду до кипения…

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

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

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

(Примечание: этот псевдокод написал я. Пользуйтесь им в работе только на свой страх и риск.)

По сравнению с первым примером этот код имеет определённые улучшения. Во-первых, жёстко заданные «магические» числа (32, 212) заменены на константы границ температур состояний (WATER_SOLID_TEMP, WATER_GAS_TEMP). Это изменение начинает делать состояния более явными, хотя и косвенным образом.

В этом коде также появляются проверки «защитного программирования», которые ограничивают вызов метода, если он находится в неподходящем для операции состоянии. Например, вода не может замерзать, если она не является жидкостью — это нарушает закон (природы). Но добавление сторожевых условий усложняет понимание назначения кода. Например:

Эта условная проверка делает следующее:

Во-вторых, код проверяет, не является ли вода жидкой, чтобы узнать, не нужно ли возвращать ошибку.

С первого раза разобраться в этом двойном отрицании состояний совсем непросто. Вот упрощение, которое немного снижает сложность выражения:

Этот код понять проще, потому что состояние isLiquidWater выражено явно.

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

Frame Machine Notation

Frame Machine Notation (FMN) — это предметно-ориентированный язык (Domain Specific Language, DSL), определяющий категоричный, методологический и простой подход к заданию и реализации различных типов автоматов. Для простоты я буду называть автоматы Frame просто «машинами», потому что эта нотация может определять теоретические критерии для любых отличающихся типов (машин состояний, магазинных автоматов и вершины эволюции автоматов — машин Тьюринга). Чтобы знать о различных видах автоматов и их применении, рекомендую изучить страницу в Википедии.

Хотя теория автоматов может быть интересной (ОЧЕНЬ сомнительное заявление), в этой статье мы сосредоточимся на практическом применении этих мощных концепций для создания систем и написания кода.

Для решения этой задачи Frame вводит стандартизированную нотацию, работающую на трёх интегрированных уровнях:

Frame — это нотация, отличающаяся некоторыми важными аспектами:

Сейчас я познакомлю вас с двумя самыми важными объектами первого уровня в Frame — Frame Events и Frame Controllers.

Frame Events

FrameEvents являются неотъемлемой частью простоты нотации FMN. FrameEvent реализуется как структура или класс, которые минимум имеют следующие переменные-члены:

В нотации Frame используется символ @, идентифицирующий объект FrameEvent. Каждый из обязательных атрибутов FrameEvent имеет специальный токен для доступа к нему:

Часто нам не обязательно указывать то, с чем работает FrameEvent. Так как большинство контекстов одновременно работают только с одним FrameEvent, нотацию однозначно можно упростить так, чтобы она использовала только селекторы атрибутов. Следовательно, мы можем упростить доступ:

Такая нотация поначалу может показаться странной, но вскоре мы увидим, как такой простой синтаксис для событий сильно упрощает понимание кода FMN.

Frame Controllers

Frame Controller — это объектно-ориентированный класс, упорядоченный чётко заданным образом для реализации машины Frame. Типы контроллеров идентифицируются префиксом #:

это эквивалентно следующему объектно-ориентированному псевдокоду:

Очевидно, что этот класс не особо полезен. Чтобы он мог что-то делать, контроллеру нужно хотя бы одно состояние для ответа на события.

Контроллеры структурируются таким образом, чтобы содержать блоки различного типа, которые идентифицируются по тире, окружающим имя типа блока:

В контроллере может быть не более одного экземпляра каждого блока, а типы блоков могут содержать только определённые типы подкомпонентов. В этой статье мы исследуем только блок -machine-, который может содержать только состояния. Состояния идентифицируются по токену префикса $.

Здесь мы видим FMN для контроллера, содержащего машину только с одним состоянием:

Вот реализация приведённого выше кода FMN:

Реализация блока machine состоит из следующих элементов:

После задания этих основ реализации блока machine, мы можем увидеть, как хорошо объект FrameEvent взаимодействует с машиной.

Блок интерфейса

Взаимодействие FrameEvents, управляющих работой машина — это сама суть простоты и мощи нотации Frame. Однако мы ещё не ответили на вопрос, откуда же берутся FrameEvents — как они попадают в контроллер, чтобы управлять им? Один из вариантов: внешние клиенты сами могут создавать и инициализировать FrameEvents, а затем напрямую вызывать метод, на который указывает переменная-член _state:

Гораздо лучшей альтернативой будет создание общего интерфейса, оборачивающего прямой вызов переменной-члена _state:

Однако наиболее беспроблемный способ, соответствующий обычному способу создания объектно-ориентированного ПО — это создание общих методов, отправляющих событие от лица клиента во внутреннюю машину:

Frame определяет синтаксис для блока интерфейса, который содержит методы, превращающие вызовы в общий интерфейс для FrameEvents.

У блока interface ещё много других особенностей, но этот пример даёт нам общее представление о том, как это работает. Дальнейшее объяснение я дам в следующих статьях серии.

Теперь давайте продолжим изучение работы автомата Frame.

Обработчики событий

Хоть мы и показали, как определять машину, у нас пока нет нотации с которой можно что-нибудь делать. Для обработки событий нам нужно 1) иметь возможность выбора события, которое нужно обрабатывать и 2) привязать его к выполняемому поведению.

Вот простой контроллер Frame, обеспечивающий инфраструктуру для обработки событий:

Как сказано выше, для доступа к атрибуту _msg события FrameEvent нотация FMN использует скобки из вертикальных линий:

FMN также использует токен знака возведения в степень, обозначающий оператор возврата. Показанный выше контроллер будет реализован следующим образом:

Здесь мы видим, насколько чётко нотация FMN соответствует паттерну реализации, который удобен в понимании и кодинге.

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

Однофокусные машины

Выше мы рассматривали контроллер без состояний, который был довольно бесполезным.

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

Для начала давайте посмотрим, как будет реализован класс со всего одним (подразумеваемым) состоянием:

Здесь не объявляется и даже не подразумевается никакого состояния, но давайте предположим, что если код что-то делает, то система находится в состоянии «Working».

Визуализировать эту ситуацию можно с помощью таблицы привязок событий:

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Теперь давайте рассмотрим FMN, которая демонстрирует тот же функционал и соответствует той же таблице привязок:

Вот как выглядит реализация:

Можно заметить, что мы также ввели новую нотацию для оператора return, которая обозначает вычисление выражения и возврат результата интерфейсу:

Этот оператор эквивалентен

Включаем плиту

Пока мы видели контроллер с 0 состояний и контроллер с 1 состоянием. Они ещё не особо полезны, но мы уже на пороге чего-то интересного.

Чтобы сварить нашу пасту, нужно для начала включить плиту. Ниже показан простой класс Switch с единственной булевой переменной:

Хоть с первого взгляда это и не очевидно, но показанный выше код реализует следующую таблицу привязок событий:

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Для сравнения, вот FMN для того же поведения:

Теперь мы видим, насколько точно нотация Frame соответствует цели нашего кода — привязке события (вызова метода) к поведению на основании состояния, в котором находится контроллер. Кроме того, структура реализации также соответствует таблице привязок:

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

Изменяем состояние

Оператор изменения состояния выглядит следующим образом:

А вот соответствующая таблица привязки событий:

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Новое событие |toggle| теперь запускает изменение, которое просто циклически переключается между двумя состояниями. Как же можно реализовать операцию изменения состояния?

Проще некуда. Вот реализация Switch2:

Можно также внести в Switch2 последнее улучшение, чтобы он не только позволял переключаться между состояниями, но и явным образом задавать состояние:

В отличие от события |toggle|, если |turnOn| передаётся, когда Switch3 уже включен или |turnOff|, когда он уже выключен, то сообщение игнорируется и ничего не происходит. Это небольшое улучшение даёт клиенту возможность явно указывать состояние, в котором должен находиться переключатель:

Последний этап эволюции нашего переключателя показывает, насколько просто будет понимать предназначение контроллера FMN. Соответствующий код демонстрирует, насколько просто его реализовать с помощью механизмов Frame.

Создав автомат Switch, мы можем включить огонь и начать готовку!

Зондируем состояние

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

Однако это предположение не всегда верно. В некоторых ситуациях требуется проверка (или «зондирование») данных для определения текущего логического состояния:

В нашей ситуации такой метод можно реализовать следующим образом:

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

Механизм реализации выглядит так:

Метод зондирования состояния — это пример нотации Frame для управления состоянием заданным образом. Далее мы также изучим важную нотацию для управления FrameEvents.

Наследование поведений и диспетчер

Наследование поведений и диспетчер — это мощная парадигма программирования и последняя тема о нотации Frame в данной статье.

Frame использует использует наследование поведений, а не наследование данных или других атрибутов. Для этого состояния отправляют FrameEvents другим состояниям, если исходное состояние не обрабатывает событие (или, как мы увидим в следующим статьях, просто хочет передать его дальше). Эта цепочка передачи событий может уходить на любую нужную глубину.

Для этого машины можно реализовывать с помощью техники под названием method chaining. Нотация FMN для передачи события из одного состояния в другое — это диспетчер =>:

Этот оператор FMN можно реализовать следующим образом:

Теперь мы видим, насколько просто объединять в цепочки методы состояний. Давайте применим эту технику к достаточно сложной ситуации:

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Благодаря изученным нами техникам реализация будет очень простой:

Машина для воды

что такое спагетти код. Смотреть фото что такое спагетти код. Смотреть картинку что такое спагетти код. Картинка про что такое спагетти код. Фото что такое спагетти код

Вот как выглядит полная реализация FMN:

А теперь реализация:

Заключение

Автоматы — это базовая концепция компьютерных наук, которую слишком долго использовали только в специализированных областях разработки ПО и оборудования. Основная задача Frame заключается в создании нотации для описания автоматов и задания простых паттернов написания кода или «механизмов» для их реализации. Я надеюсь, что нотация Frame изменит взгляд программистов на автоматы, обеспечив простой способ их практического применения в повседневных задачах программирования, и, разумеется, позволит избавить их от спагетти в коде.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *