Re[4]: Императивная парадигма
От: AlexCab LinkedIn
Дата: 22.07.11 10:33
Оценка:
Здравствуйте, Klapaucius, Вы писали:
AC>>ИМХО лет через 20-120 создадут ИИ и необходимость ЯП отпадёт принципе
K>Почему тогда необходимость в языке программирования вдруг отпадет?
Я имел виду языки программирования в том виде в каком они есть сейчас, то есть как интерфейс человек-машина.

K>Просто наличие "последовательности вычислений" это вопрос трактовки...

Вопрос(интересующий меня) не в "наличии последовательности вычислений", а в подходе который вы используете когда пишете программу, вы как бы "говорите" компьютеру:
ИП — "сделай это, затем то, затем третье..."
ДП — "это должно быть таким, то должно находится здесь..."
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[6]: Императивная парадигма
От: AlexCab LinkedIn
Дата: 22.07.11 10:35
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>1. ИП — деструктивное изменение данных.
VD>2. ФП — преобразование (с копированием) данных.
VD>...
То есть можно сказать что:
Чистое процедурное программирование — последовательность шагов выполнения, произвольный доступ к памяти из любого места программы и тп.
Чистое функциональное программирование — вычисление значения функций, детерминированность функций и тп.
А ЯП включающий свойства обоих парадигм(как в случае процедур не изменяющих ничего кроме своих параметров) не является "чистым".
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[27]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 22.07.11 10:36
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


S>>Покажи как это будет выглядеть на примере Dictionary<TKey,TValue>.Add.


U>А чего-нибудь попроще нельзя? Мне как-то лень лезть в рефлектор, разбираться в не самой очевидной механике и думать как ее наилучшим образом свести к вызовам свободных функций с минимумом обвязки над ними.

Давай тогда List<T>.Add. Пойдет?

S>>Как ты собираешься исключительно свободными функциями доставать элементы из items?


U>Откуда взялось требование "исключительно"? Объясни, как из:


U>

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


U>можно сделать вывод, что функции должны быть "исключительно" свободными?

С "исключительно" я перегнул. Но мне кажется и с львиной ты тоже. Если даже взять одни только штатные коллекции, то львиную долю функциональности вынести в свободные функции не получится. Потоки/файлы — нет. Строки и текст — нет. Контролы — тоже нет. Более менее свободен лишь Math.

Хорошую степень свободы как-правило имеют методы работы с функциональными структурами данных. Но это за счет того что там не нужно управлять версиями, емкостью, счетчиком элементов, низлежащими структурами данных, не нужно все это держать в согласованном состоянии.
Re[5]: Императивная парадигма
От: Undying Россия  
Дата: 22.07.11 10:38
Оценка:
Здравствуйте, AlexCab, Вы писали:

AC>ИП — "сделай это, затем то, затем третье..."

AC>ДП — "это должно быть таким, то должно находится здесь..."

i = 5;

Сделай, чтобы i равнялось 5.
i должно равняться 5.

И где здесь принципиальная разница?
Re[28]: Императивная парадигма
От: Undying Россия  
Дата: 22.07.11 11:04
Оценка:
Здравствуйте, samius, Вы писали:

S>Давай тогда List<T>.Add. Пойдет?


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

S>С "исключительно" я перегнул. Но мне кажется и с львиной ты тоже. Если даже взять одни только штатные коллекции, то львиную долю функциональности вынести в свободные функции не получится. Потоки/файлы — нет. Строки и текст — нет. Контролы — тоже нет. Более менее свободен лишь Math.


Не нужно заменять вызовы функций классов вызовами свободных функций, т.к. понятно, что если мы запихали функцию в класс, то скорей всего сделали либо из соображений инкапсуляции, либо полиморфизма, и соответственно замена вызова на свободную функцию невозможна. Есть задача заменить реализацию функции класса на вызовы свободных функций с минимумом обвязки над ними, т.к. это резко упрощает и понимание реализации и резко увеличивает возможности по повторному использованию функциональности.
Re[29]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 22.07.11 11:14
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


S>>Давай тогда List<T>.Add. Пойдет?


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

Array.Resize

S>>С "исключительно" я перегнул. Но мне кажется и с львиной ты тоже. Если даже взять одни только штатные коллекции, то львиную долю функциональности вынести в свободные функции не получится. Потоки/файлы — нет. Строки и текст — нет. Контролы — тоже нет. Более менее свободен лишь Math.


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


А, ну это ExtractMethod, разве что с гипертрофированным уклоном в свободные функции. С причинами выделения метода я согласен, разве что делать его свободным совсем не обязательно.
Re[30]: Императивная парадигма
От: Undying Россия  
Дата: 22.07.11 11:26
Оценка:
Здравствуйте, samius, Вы писали:

S>А, ну это ExtractMethod, разве что с гипертрофированным уклоном в свободные функции. С причинами выделения метода я согласен, разве что делать его свободным совсем не обязательно.


От ExtractMethod как члена класса толку немного, т.к. по вынесенному методу, по-прежнему нельзя ни понять то с какой частью состояния класса этот метод работает, ни использовать его функциональность в другом классе.
Re[31]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 22.07.11 12:16
Оценка: +1
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


S>>А, ну это ExtractMethod, разве что с гипертрофированным уклоном в свободные функции. С причинами выделения метода я согласен, разве что делать его свободным совсем не обязательно.


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

А есть такая цель? Если ты разработчик этого класса — открой код. Если пользователь — кури доку.
U>, ни использовать его функциональность в другом классе.
Если можно вынести что-то вроде Array.Resize, то это как-правило выносится. А от выноса List<T>.Capacity в SetListCapacity<T>(ref T[] listUnderlyingArray, ref int listCapacity, int newCapacity), как правило, толку не будет в другом классе.
Re[7]: Императивная парадигма
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.07.11 13:45
Оценка: +4
Здравствуйте, AlexCab, Вы писали:

AC>То есть можно сказать что:

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

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

AC>А ЯП включающий свойства обоих парадигм(как в случае процедур не изменяющих ничего кроме своих параметров) не является "чистым".


Реально чистым функциональным языком можно назвать только математику, точнее лямбда-исчисления Чёрча .

"Чистыми" называют языки в которых ИП четко выделен и не довольно неудобен. Но реально ИП поддерживается всеми без исключениями языками общего назначения. Любой ввод-вывод — это ИП. Для абстрагирования от ИП придумывают разную фигню вроде передачи мира в качестве параметров или указателей на которые может быть только одна ссылка на единицу времени. Но по сути — это всего лишь попытка обезопасть программиста и скрыть от него страшную правду — мир императивен.

Посему я для себя давно уже решил, что поиск чистоты — это бессмысленное занятие. ФП хорошо там где обрабатываются данные, когда есть исходные данные и их нужно преборазовать в некоторую форуму. Любую программу можно разбить на куски представимые таким образом, даже GUI.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[32]: Императивная парадигма
От: Undying Россия  
Дата: 22.07.11 19:05
Оценка:
Здравствуйте, samius, Вы писали:

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

S>А есть такая цель? Если ты разработчик этого класса — открой код. Если пользователь — кури доку.

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

U>>, ни использовать его функциональность в другом классе.

S>Если можно вынести что-то вроде Array.Resize, то это как-правило выносится. А от выноса List<T>.Capacity в SetListCapacity<T>(ref T[] listUnderlyingArray, ref int listCapacity, int newCapacity), как правило, толку не будет в другом классе.

Заставь дурака богу молиться, он и лоб расшибет.
Re[33]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 22.07.11 19:46
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


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

S>>А есть такая цель? Если ты разработчик этого класса — открой код. Если пользователь — кури доку.

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

Интригует такое слышать от противника Linq-а.

U>>>, ни использовать его функциональность в другом классе.

S>>Если можно вынести что-то вроде Array.Resize, то это как-правило выносится. А от выноса List<T>.Capacity в SetListCapacity<T>(ref T[] listUnderlyingArray, ref int listCapacity, int newCapacity), как правило, толку не будет в другом классе.

U>Заставь дурака богу молиться, он и лоб расшибет.

Ну я может не понимаю, о чем ты говоришь? От примера со словарем ты отказался, со списком — предложил вынести метод, который уже вынесен. Покажи уже на чем-нибудь увеличение читаемости на порядок за счет перевода метода класса в свободные... И желательно с потенциальным реюзом вынесенного.
Re[34]: Императивная парадигма
От: Undying Россия  
Дата: 23.07.11 14:33
Оценка:
Здравствуйте, samius, Вы писали:

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

S>Интригует такое слышать от противника Linq-а.

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

S>Ну я может не понимаю, о чем ты говоришь? От примера со словарем ты отказался, со списком — предложил вынести метод, который уже вынесен. Покажи уже на чем-нибудь увеличение читаемости на порядок за счет перевода метода класса в свободные... И желательно с потенциальным реюзом вынесенного.


На маленьком примере это будет невидно, привести большой пример не позволяет формат форумного общения.
Re[6]: Императивная парадигма
От: Ziaw Россия  
Дата: 23.07.11 15:14
Оценка:
Здравствуйте, Undying, Вы писали:

U>i = 5;


U>Сделай, чтобы i равнялось 5.

U>i должно равняться 5.

U>И где здесь принципиальная разница?


Слабовато с утрированием. Надо убрать присваивание и оставить только i.

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

select 5 as i from dual


Нету тут: "Сделай, чтобы i равнялось 5" или "i должно равняться 5". Есть: 5 будем назвать i.
Re[35]: Императивная парадигма
От: Sinix  
Дата: 23.07.11 15:51
Оценка:
Здравствуйте, Undying, Вы писали:

U>Свободные бизнес-функции много выше уровнем, нежели linq.


А вот тут я окончательно запутался. Если linq и прочих хелперов stateless-подход только на пользу, то для БЛ (особенно на десктопе) без разделяемого состояния никуда. И, из-за сильной связности типовой БЛ, много не нарефакторишь — не будет у нас сотен строк кода без побочных эффектов. Все способы — IOC/service locator/context propagation — никак не спасут от самой потребности в контексте.

КМК, тут мы гонимся больше за абстрактной чистотой идеи, чем за практичностью.
Re[36]: Императивная парадигма
От: Undying Россия  
Дата: 23.07.11 16:22
Оценка:
Здравствуйте, Sinix, Вы писали:

S>А вот тут я окончательно запутался. Если linq и прочих хелперов stateless-подход только на пользу, то для БЛ (особенно на десктопе) без разделяемого состояния никуда. И, из-за сильной связности типовой БЛ, много не нарефакторишь — не будет у нас сотен строк кода без побочных эффектов. Все способы — IOC/service locator/context propagation — никак не спасут от самой потребности в контексте.


Допустим мы решили написать собственный textBox. Какие задачи перед нами встают? Вывести рамку, вывести текст, найти букву по координате и т.д.

Для того, чтобы вывести рамку нам нужно все состояние textBox'а? Очевидно, нет, например, и текст и выделенный текст для этого совершенно не нужны. А нужны нам graphics, прямоугольник области вывода и какие дополнительные параметры (цвет, кисть, стиль и т.п.) Можем мы оформить вывод рамки как свободную функцию? Да, можем. Аналогично для вывода текста нам тоже нужно далеко не все состояние textBox'а. И опять же ничто не мешает вывод текста оформить как свободную функцию.

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

Завтра мы решили написать свой comboBox. Нужно ли нам что вывод текста в комбобоксе отличался от вывода текста в textBox'е? Скорей всего нет. Смогли ли мы бы использовать вывод текста из textBox'а в comboBox'е, если бы оформили его функцию класса? Скорей всего нет, т.к. возможности наследования и очень ограничены и приводят к множеству проблем. Есть ли какие-то проблемы с использованием функции вывода текста из textBox'а в comboBox'е, если она оформлена как свободная функция? Нет, никаких проблем нет. Т.е. свободные функции выступают в роли кирпичиков, из которых очень легко конструировать в чем-то похожие, но в чем различные объекты. Для того, что похоже мы используем уже имеющиеся свободные функции, для того что различно пишем новые свободные функции.
Re[37]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.07.11 17:13
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, Sinix, Вы писали:


S>>А вот тут я окончательно запутался. Если linq и прочих хелперов stateless-подход только на пользу, то для БЛ (особенно на десктопе) без разделяемого состояния никуда. И, из-за сильной связности типовой БЛ, много не нарефакторишь — не будет у нас сотен строк кода без побочных эффектов. Все способы — IOC/service locator/context propagation — никак не спасут от самой потребности в контексте.


U>Допустим мы решили написать собственный textBox. Какие задачи перед нами встают? Вывести рамку, вывести текст, найти букву по координате и т.д.


U>Для того, чтобы вывести рамку нам нужно все состояние textBox'а? Очевидно, нет, например, и текст и выделенный текст для этого совершенно не нужны. А нужны нам graphics, прямоугольник области вывода и какие дополнительные параметры (цвет, кисть, стиль и т.п.) Можем мы оформить вывод рамки как свободную функцию? Да, можем. Аналогично для вывода текста нам тоже нужно далеко не все состояние textBox'а. И опять же ничто не мешает вывод текста оформить как свободную функцию.


U>Т.е. если начать рассматривать задачи, которые нужно решить при разработке textBox'а, то окажется, что большинство из них могут легко выражены как свободные функции. А кода, который связывает эти свободные функции собственно в textBox, оказывается очень немного.


U>Завтра мы решили написать свой comboBox. Нужно ли нам что вывод текста в комбобоксе отличался от вывода текста в textBox'е? Скорей всего нет. Смогли ли мы бы использовать вывод текста из textBox'а в comboBox'е, если бы оформили его функцию класса? Скорей всего нет, т.к. возможности наследования и очень ограничены и приводят к множеству проблем. Есть ли какие-то проблемы с использованием функции вывода текста из textBox'а в comboBox'е, если она оформлена как свободная функция? Нет, никаких проблем нет. Т.е. свободные функции выступают в роли кирпичиков, из которых очень легко конструировать в чем-то похожие, но в чем различные объекты. Для того, что похоже мы используем уже имеющиеся свободные функции, для того что различно пишем новые свободные функции.


А чем же тебя не устроила Graphics.DrawText? Тем что несвободна? Кстати, я так и не понял, свободные функции в твоем определении как-то связаны с детерминированностью и сайд эффектами? Пример-то какой-то уж сайд-эффектный больно.
Re[35]: Императивная парадигма
От: samius Япония http://sams-tricks.blogspot.com
Дата: 23.07.11 17:17
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, samius, Вы писали:


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

S>>Интригует такое слышать от противника Linq-а.

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

Дай-ка определение свободной функции. А то у тебя Array.Resize вышел вроде как свободным, и оказался уровнем выше линка.

S>>Ну я может не понимаю, о чем ты говоришь? От примера со словарем ты отказался, со списком — предложил вынести метод, который уже вынесен. Покажи уже на чем-нибудь увеличение читаемости на порядок за счет перевода метода класса в свободные... И желательно с потенциальным реюзом вынесенного.


U>На маленьком примере это будет невидно, привести большой пример не позволяет формат форумного общения.

Может дашь ссылку на какой-то ресурс, где об этом сказано?
Re[37]: Императивная парадигма
От: Sinix  
Дата: 23.07.11 17:20
Оценка:
Здравствуйте, Undying, Вы писали:

U>Для того, чтобы вывести рамку нам нужно все состояние textBox'а? Очевидно, нет, например, и текст и выделенный текст для этого совершенно не нужны.


Неа — всё это может влиять на рендеринг, два примера: автосайз текстбокса, шаблон "рыбий глаз" — размер текста увеличивается при выделении. Кроме того, фон рамки зависит от кучи флагов состояния — начиная с системных параметров и заканчивая фокусом (тот же accepts enter = false перенесёт альтернативный фокус (тот, что срабатывает по нажатию на enter) на кнопку по умолчанию).

Суммируя: даже набор нужных параметров для отрисовки зависит от текущего состояния текстбокса. Ну сделаем мы тонну static-методов и будем передавать не сам контрол, а отдельные его поля — как это повлияет на их "чистоту"?

Самый правильный (имхо) подход здесь — разнесение построения декларативного visual tree и собственно рендеринга. Как это выстреливает можно посмотреть на примере WPF.
Во-первых, вы можем манипулировать самим visual tree — начиная с анимаций по условию и заканчивая полной сменой шаблона.
Во-вторых, мы можем использовать информацию о состоянии контрола не только для рендеринга, но и для hit testing и accessibility (aka win automation).
В третьих, мы теперь можем относительно легко перенести стек рендеринга на удалённую машину — см RemoteFX.

В принципе, такой подход можно условно обозвать чистым — код отрисовки освобождён от ответственности за сохранение состояния контрола. Одна проблема: даже у Graphics из GDI+, при всей его простоте, приходится сохранять состояние самого стека рендеринга между вызовами.

Другими словами: "чистоту" кода можно повысить, инкапсулируя внутреннее состояние внутри слоя. Тут я всеми руками-ногами за. А вот избавиться от состояния совсем — не получится. Поэтому проще переиспользовать кирпичики-классы, чем изобретать 1025й способ эмулировать this.
Re[38]: Императивная парадигма
От: Undying Россия  
Дата: 23.07.11 17:55
Оценка:
Здравствуйте, samius, Вы писали:

S>А чем же тебя не устроила Graphics.DrawText? Тем что несвободна? Кстати, я так и не понял, свободные функции в твоем определении как-то связаны с детерминированностью и сайд эффектами? Пример-то какой-то уж сайд-эффектный больно.


Graphics.DrawText это свободная функция и очень полезная функция. Но она является низкоуровневой по сравнению со свободной функцией отрисовки текста textBox'а, т.к. к примеру ничего не знает о том, что часть текста может быть выделенной и ее надо выводить по другому. Соответственно над Graphics.DrawText будет много обвязочного кода, а над свободной функцией вывода текста в textBox'е обвязки практически не будет, т.к. и вызовы Graphics.DrawText и обвязка над ними внутрь этой самой функции и уйдут.
Re[36]: Императивная парадигма
От: Undying Россия  
Дата: 23.07.11 18:01
Оценка:
Здравствуйте, samius, Вы писали:

S>Дай-ка определение свободной функции. А то у тебя Array.Resize вышел вроде как свободным, и оказался уровнем выше линка.


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

U>>На маленьком примере это будет невидно, привести большой пример не позволяет формат форумного общения.

S>Может дашь ссылку на какой-то ресурс, где об этом сказано?

Не знаю. Толчок в этом направлении мне дал Darkgray. Дальше сам.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.