Словарик философствующего информатика: различия между версиями

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
Строка 177: Строка 177:




==Метамоделирование==
===Метамоделирование===


Метамоделирование — это одновременно и процесс и некоторая методология (идеология),
Метамоделирование — это одновременно и процесс и некоторая методология (идеология),

Версия от 16:57, 21 февраля 2007

Слова обладают удивительной магической силой. Стоит произнести слово «эволюция» в компании биологов, как немедленно загораются глаза, открываются рты, и вот уже идёт эмоциональный спор, видимо, продолжающий незаконченный вчерашний. Физики загораются от слов «кошка Гейзенберга», «тёмная материя», «универсальная теория поля». Веб-разработчики — от слов «Web 2.0» и «Ruby on Rails».

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

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

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

Концепция

Склонность к систематизации — признак слабоумия.

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

Ценность данного словарика может быть достигнута только тогда, когда описания

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

Безусловно, каждое описываемое здесь слово следует снабдить ссылкой на статью в Википедии.

Ещё несколько рекомендации к отбору слов:

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

Почему сие не поместить в Википедию?

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

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

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

Об авторах

Идея данного словаря витала в воздухе. На страницах Википедии и Викиучебника встречаются тексты по информатике, в которых делаются попытки коротко написать о многом. Затравку из первых 20 понятий сделали Непейвода Н. Н. и Ворожцов А. В. Часть текстов была взята из страницы Ruby/Идеология (по матеориалам книги "Программист-прагматик" Эндрю Ханта и Дэвида Томаса).

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

Структура словарика

На первом этапе предлагается всё писать на одной странице. Со временем, возможно, будем использовать разбиение на кусочки, размещаемые с префиксом «Словарик философствующего информатика:» или без него.

Архитектура компьютера. Вычислимость и вычисления

Исполнитель

Виртуализация

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

Параллелизм

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

Одной из важных проблем является извлечение пользы из параллелизма в условиях тонкого (медленного и/или ненадёжного) информационного канала между исполнителями.

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

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

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

Программирование. Языки программирования

Алгоритм

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

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

Стили (парадигмы) программирования

Функциональное программирование

Продукционное программирование

Автоматное программирование

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

Автоматное программирование (называемое в FP программированием от состояний) наиболее адекватно тогда, когда действия глобальны, а условия локальны. Оно может быть реализовано множеством способов (программа, интенсивно использующая go to, система объектов, в которой каждое конкретное состояние описано как наследник общего объекта «состояние программы», и т.п.) Оно требует, чтобы конкретные локальные действия и описания были упрятаны в реализации процедур, изменяющих состояние системы, поскольку автоматное программирование глубоко концептуально противоречит, в частности, структурному. Концептуальные противоречия между автоматным и сентенциальным программированием намного менее резкие.

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


Моделирование

Моделирование

Читаем в Википедии: «Модели́рование — исследование объектов познания на их моделях; построение и изучение моделей реально существующих предметов, процессов или явлений с целью получения объяснений этих явлений, а также для предсказания явлений, интересующих исследователя.»

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

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

Итак:

Модель — это формализованное описание чего-либо, то есть чётко, однозначно определяющие, и (в идеальном случае) интерпретируемое компьютером, описание на некотором формальном (строго определённом) языке.


См. также


Метамоделирование

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

См. также:

Концептуальность

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

Как и всякое философская концепция концептуальность является одной стороной некоторого баланса. Ему противостоит концепция «прагматичности при получении нужного функционала»:

Рассмотрим два полюса:

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

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

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

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

Имитационное моделирование

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

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

Нормативное моделирование

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

Нормативное моделирование является основным методом изучения мира со стороны богословов. Блестящими примерами нормативного моделирования явились работы Галилео Галилея и Исаака Ньютона (законы механики были сформулированы для инерциальных систем, которых в природе не существует), Г. Менделя (законы наследственности были открыты на уникальном примере растения и признака, где наследственные факторы выделялись в чистом виде; практически всегда они не являются чистыми и подвержены действию окружающей среды и других наследственных факторов) и Р. Вольтерра (построившего модель «хищник-жертва» на основе идеи обратных связей в природе и тем самым заложившим основы теории экологического равновесия). Менее удачным, но весьма показательным, примером нормативного моделирования является теория эволюции Ч. Дарвина

Неформализуемое понятие

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

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

Концептуальное противоречие

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

Разработка программного обеспечения

Характеристики программного средства

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

  • функциональность (functionality)
  • надежность (reliability)
  • легкость и удобность применения (usability)
  • эффективность (efficiency)
  • мобильность (portability)


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

Надёжность - это когда ПС поставили на военную технику, а его разработчик спит спокойно.

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

Эффективность - это отношение уровня услуг, предоставляемых ПС пользователю при заданных условиях, к объему используемых ресурсов. То есть, скорость и точность работы (или актуальность и полнота услуг, предоставляемых ПС), деленное на вычислительную мощь исполнителя.

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

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

Но для разработчиков важна другая характеристика ПС:

  • сопровождаемость - это совокупность свойств ПС, которая позволяют минимизировать усилия по внесению изменений для устранения в нем ошибок и по его модификации в соответствии с изменяющимися потребностями пользователей.

Эта характеристика касается не качества работы ПС, а качества архитектуры и качество исходного кода ПС:

  • концептуальная продуменность архитектуры, которая делает систему простой, легко понимаемой и расширяемой
  • самодокументированность кода
  • самопроверяемость кода

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

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

Сложность

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

Абстракция

Подпорка

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

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

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

Причин возникновения подпорок две:

  • отсутствие концептуальной целостности архитектуры, то есть ошибка, допущенная на этапе проектирования системы;
  • несовершенность реального мира.

От первой причины избавиться очень сложно, от второй — невозможно.

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

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

Призрак

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

Очень часто призраки — это пререквизиты (условия на входные данные), которые явно не следует из предшествующих строк кода.

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

Есть более прозаичные примеры призраков: число шагов цикла while, либо инварианты циклов, либо требование упорядоченности массива, явно не следующее кода.

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

Принцип самодокументированности кода (code self-documentation) провозглашенный в теории коллективной разработки программ гласит «Призраков быть не должно!»

Но что же делать? — Пишите коментарии!

Reuse: методология повторного использования

Reuse: методология повторного использования (переиспользование) — применение готовых программных модулей (уже использованных в другой программе либо кем-то другим) при создании нового программного обеспечения. Процент переиспользуемых программных решений является критерием качества организации работы (не путать с качеством самой работы!) программистского коллектива. Различные средства модульности и объектности создавались прежде всего с целью облегчить переиспользование.

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

Именно благодаря применению переиспользования удается создавать действительно сложные системы.

Но излишнее стремление к переиспользование часто приводит к следующим негативным последствиям:

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

Сформулируем это другими словами:

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

Серьёзное программирование — это всегда не массовое производство, а производство уникальных изделий.

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

См. также

Ортогональность

/Ортогональность

Цикл разработки программного обеспечения

Проектирование

Проектирование — это поиск ответа на вопрос, как должна быть реализована система.

Это второй этап процесса разработки программного обеспечения (первый — генерация концептуальной идеи).

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

Область знаний «Системный анализ» претендует на описание базовых принципов, позволяющих избежать ошибок во время проектирования:

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

Множество предлагаемых в различных учебниках принципов является достаточно эклектичным набором противоречивых идей. Основной же принцип всякого проектирования это:

  • достижения баланса между дуальными концепциями,

как то, «универсальность и расширяемость — простота и достижение конкретной функциональности», «концептуальная целостность - полнота и удобство функциональности», «многофункциональность — внутренняя простота и поддерживаемость».

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

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

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

См. также

В Википедии

Тестирование

/Тестирование

Тупое кодирование

Прототипирование

Прототипирование — это быстрая «черновая» реализация базовой функциональности для анализа работы системы в целом. Для прототипирования используют языки высокого уровня абстракции (Java, Python, Haskell, ...). После этапа прототипирования обязательно следуют этапы пересмотрения архитектуры системы, разработки, реализации и тестирования конечного продукта. На этапе разработки подготавливают систему тестов, по работе которых буду судить о качестве продукта. При реализации решения обычно используют другой, «более машинноориентированный» язык программирования (Си, Си++, ...), пишут более аккуратный документированный код, а на тестирование системы тратят сравнительно большое количество усилий для достижения качественного результата. На этапе прототипирования выявляются важные архитектурные ошибки, вносятся поправки в интерфейсы модулей (перераспределяется функциональность между кусочками системы). Прототипирование по мнению многих программистов является самым приятным этапом разработки, так как малыми усилиями создается нечто более-менее работающее. Кроме того, во время прототипирования на программистов обычно «снисходит понимание» и они начинают «видеть», как система должна быть устроена.

Несвязность и закон Деметра

/Несвязность и закон Деметра

Wizards: «волшебники», частично автоматизирующие разработку систем

/Злые волшебники

Self-documentation

Self-verification

Экстремальное программирование

Демон

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