Почему бы опустить закрывающий тег?


374

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

Современные версии PHP устанавливают флаг output_buffering в php.ini. Если включена выходная буферизация, вы можете установить HTTP-заголовки и куки-файлы после вывода HTML-кода, поскольку возвращаемый код не отправляется в браузер немедленно.

Каждая книга хорошей практики и вики начинаются с этого «правила», но никто не приводит веских причин. Есть ли еще одна веская причина, чтобы пропустить конечный тег PHP?


3
возможный дубликат [почему в некоторых скриптах они пропускают закрывающий тег php?>] ( stackoverflow.com/questions/3219383/… )
Гордон

@Christian - Вы имеете в виду, что использование output_buffering является ленивым, или отключение ?>ленивым?
Эль Йобо

4
@ Гордон - я не думаю, что это обман, ОП знает очевидные причины, просто хочет знать, полностью ли он решен с помощью буферизации вывода.
Эль Йобо

5
Лучше было бы задать вопрос: зачем включать тег закрытия? Код это зло. Лучший код - это не код вообще. Если проблема может быть устранена, а не решена с помощью кода, это лучше, чем иметь код. В этом случае нет проблем, требующих решения. Код работает без тега закрытия.
still_dreaming_1

19
О, боже, это не место для вкладок против пространств священной войны, смеется :)
Кевин Уилер

Ответы:


322

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

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

  2. У вас могут быть головные боли из-за необъяснимой потери функциональности . Скажем, вы реализуете какой-то платежный шлюз и перенаправляете пользователя на определенный URL после успешного подтверждения платежным процессором. Если произойдет какая-либо ошибка PHP, даже предупреждение или окончание лишней строки, платеж может остаться необработанным, а пользователю все равно может показаться, что счет не выставлен. Это также одна из причин, по которой ненужное перенаправление является злом, и если перенаправление должно использоваться, оно должно использоваться с осторожностью.

  3. Вы можете получить ошибки типа «Загрузка страницы отменена» в Internet Explorer, даже в самых последних версиях. Это связано с тем, что AJAX response / json include содержит что-то, чего он не должен содержать из-за лишних концов строк в некоторых файлах PHP, как я встречал несколько дней назад.

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

  5. Наконец, многие PHP-фреймворки, включая Symfony , Zend и Laravel (об этом нет упоминаний в руководствах по кодированию, но это соответствует их примеру) и стандарт PSR-2 (пункт 2.2), требуют пропуска закрывающего тега. Само руководство по PHP ( 1 , 2 ), Wordpress , Drupal и многие другие программы PHP, я думаю, советую сделать это. Если вы просто привыкли следовать стандарту (и устанавливаете PHP-CS-Fixer для своего кода), вы можете забыть об этом. В противном случае вам всегда нужно будет помнить о проблеме.

Бонус: несколько ошибок (на самом деле один), связанных с этими двумя персонажами:

  1. Даже некоторые известные библиотеки могут содержать лишние окончания строки после ?>. Например, Smarty, даже самые последние версии веток 2. * и 3. * имеют это. Так что, как всегда, следите за сторонним кодом . Бонус в бонусе: регулярное выражение для удаления ненужных окончаний PHP: замените (\s*\?>\s*)$пустой текст во всех файлах, которые содержат код PHP.

Немного другое регулярное выражение , я использовал , чтобы найти метки с Netbeans IDE для Find & Replace диалог: \?>(?s:.){0,10}\Z Краткое объяснение: changeset.hr/blog/miscellaneous/catch-near-eof-with-regex
frnhr

@Cek, он перехватывает любой текст, включая код, который составляет 10 символов или менее после ?>: например, он соответствует-и удалит- ?> Helloв <?php echo "test"; ?> Hello. Мы хотели бы очистить только закрытые теги.
Халил Озгюр

6
Хуже того, apache 2.4.6 с PHP 5.4 фактически выявляет ошибки на наших производственных машинах, когда за закрывающим тегом есть свободное место. Я просто потратил впустую часы, пока, наконец, не сузил ошибку с помощью strace. Здесь ошибка , что апач бросает: [core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11).
Артем Руссаковский

3
@INTPnerd О, вопрос и большинство ответов относятся к заголовку, поэтому я предположил, что любой, кто читает эту ветку, будет иметь представление об этом. Основная проблема и фактическая причина проблем во многих ответах здесь - это ненужные пробелы после ?>, что (как и любой вывод) приводит к отправке заголовков, как только они выводятся. Нет никаких «заголовков HTML» (кроме несвязанного <header>тега HTML5 ).
Халил Озгюр

2
Это должно работать независимо от глобального модификатора: \ s * \?> \ S * \ Z Обратите внимание на '\ Z' в конце. Это гарантирует, что вы захватываете закрывающий тег php тогда и только тогда, когда это последний непробельный пробел в самом конце файла.
Erutan409

122

Причина, по которой вы должны не использовать закрывающий тег php ( ?>), заключается в том, что программист случайно не отправляет дополнительные символы новой строки.

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

Итак, на ваш вопрос:

Есть ли еще одна веская причина пропустить заключительный тег php?

Нет, нет другой веской причины пропускать конечные теги php.

Я закончу с некоторыми аргументами, чтобы не беспокоиться с закрывающим тегом:

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

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


2
> любой программист с полусмысленностью может помнить, чтобы не добавлять лишние пробелы. Более того, любой разработчик, имеющий половину ума, может добавить хук до фиксации к SVC, чтобы автоматически удалять любые конечные пробелы: без суеты и суеты.
BryanH

6
@BryanH, пока у вас нет файла, где конечный пробел абсолютно необходим, но это очень редко.
zzzzBov

1
Вы правы, конечно. Проверьте ответ Марио для некоторых очень крутых альтернатив.
BryanH

> «Причина, по которой вы не должны пропускать закрывающий тег php, заключается в том, что он вызывает дисбаланс в тегах php, и любой программист с полусмысленностью может помнить, чтобы не добавлять лишние пробелы». На Windows, может быть. В UNIX-подобных системах все файлы заканчиваются на \ n, и программы добавляют его для вас. РЕДАКТИРОВАТЬ: Ага! Как отмечено ниже @mario, PHP, на самом деле, это съедает.
Андреа

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

57

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

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

  • PHP на самом деле содержит некоторую магию, чтобы поглотить единичные разрывы строк после ?>закрывающего токена. Хотя это имеет исторические проблемы и оставляет новичков по-прежнему восприимчивыми к нестабильным редакторам и неосознанно перетасовывает их в другие пробелы ?>.

  • Стилистически некоторые разработчики предпочитают рассматривать <?phpи ?>как теги SGML / инструкции по обработке XML, подразумевая согласованность баланса в трейлинг-маркере. (Что, кстати, полезно для включения в класс, связанный с зависимостями, чтобы вытеснить неэффективную автозагрузку файлов.)

  • Несколько необычно открытие <?phpхарактеризуется как ПГПС притон (и полностью осуществимо на binfmt_misc ), тем самым проверки избыточности соответствующего близкого тега.

  • Там очевидное несоответствие между посоветуете классических руководств синтаксиса PHP , предписывающих ?>\nи более недавними (PSR-2) , согласившихся на упущение.
    (Для справки: Zend Framework, постулирующий одно над другим, не подразумевает присущего ему превосходства. Это ошибочное мнение, что эксперты были привлечены к целевой аудитории громоздких API).

  • SCM и современные IDE предоставляют встроенные решения, в основном облегчающие работу с близкими тегами.

Отказ от любого использования ?>тега close просто задерживает объяснение базового поведения PHP и семантики языка, чтобы избежать редких проблем. Это все еще практично для совместной разработки программного обеспечения из-за различий в квалификации участников.

Закрыть варианты тегов

  • Регулярный ?> закрывающий тег также известен как T_CLOSE_TAG, или таким образом «закрыть маркер».

  • Он включает в себя еще несколько воплощений из-за того, что PHP использует волшебную новую строку :

    ?>\n (Перевод строки Unix)

    ?>\r (Возврат каретки, классические MAC)

    ?>\r\n (CR / LF, на DOS / Win)

    PHP не поддерживает перевод строки Unicode NEL(U + 0085).

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

  • Часто упускается из виду, но до тех пор, пока PHP7 не удалит их , обычный <?phpтокен открытия может быть корректно связан с редко используемым в </script>качестве нечетного закрытия токена .

  • « Жесткий закрывающий тег » - даже не один - просто придумал этот термин для аналогии. Концептуально и с точки зрения использования, __halt_compilerоднако, должны быть признаны как близкий знак.

    __HALT_COMPILER();
    ?>
    

    Который в основном имеет токенайзер, отбрасывающий любой код или простые разделы HTML после этого. В частности, заглушки PHAR используют это или его избыточную комбинацию с ?>изображенным изображением.

  • Точно так же делает недействительнаяreturn; нечасто подставит в сценарий включает в себя, оказании любого ?>с конечными пробелами неэффективны.

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

    • Простой интервал, // ? >чтобы избежать обнаружения токенайзером PHP.

    • Или причудливые замены Юникода // ﹖﹥(U + FE56 МАЛЕНЬКИЙ ВОПРОСНИК, U + FE65 МАЛЕНЬКИЙ УГОЛ БРЕКЕТА), которые может понять регулярное выражение.

    Оба ничего не значат для PHP , но могут иметь практическое применение для неосознаваемых PHP или полуосознающих внешних инструментариев. На catум приходят вновь присоединенные скрипты, в результате чего // ? > <?phpконкатенации, которые встраивают-сохраняют прежнее разделение файла.

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

Ручная няня ?>близких меток не очень современна в любом случае. Для этого всегда были инструменты автоматизации (даже если это просто sed / awk или regex-oneliners). В частности:

Теги phptags tidier

https://fossil.include-once.org/phptags/

Которые обычно можно использовать для --unclosephp-тегов для стороннего кода или, скорее, просто для устранения любых (и всех) реальных проблем с пробелами / спецификациями:

  • phptags --warn --whitespace *.php

Он также обрабатывает --longпреобразование тегов и т. Д. Для совместимости во время выполнения / конфигурации.


7
Да, тупые и провокационные фразы привлекают негативных голосов. Из того, что я прочитал с течением времени, закрытие токена не имеет абсолютно никаких недостатков, если вы не работаете с программным обеспечением, которое не может справиться с этим. Если вы на самом деле не можете доказать, что опускание закрывающих токенов - это плохо и очень недолгое занятие, мое понижение остается;)
jpeltoniemi

2
@Pichan: я позволю это. Но я полагаю, вы не совсем поняли, что здесь говорится. Избегать и избегать - это две разные вещи. И проблемы, которые наполовину решены, являются результатом использования змеиного масла.
Марио

6
@mario: Это рекомендация для начинающих . Я не согласен. Во всей Zend Framework отсутствуют закрывающие теги. Я думаю, что это очень личный выбор, я действительно предпочитаю оставить свой <? Php открытым, и я не чувствую себя новичком :)
Даниэле Врут

1
А как насчет HTML? Это тогда нужно? Например, <?php if($var): ?>Hello World<?php endif; ?>??? Мне искренне любопытно, поскольку это не упомянуто специально.
WASasquatch

1
@ WASasquatch Да. Если вы переключаетесь между режимами HTML и PHP, то в любом случае вам понадобятся близкие токены. (Не очень относится к первоначальному вопросу здесь.)
Марио

22

Это не тег ...

Но если он у вас есть, вы рискуете получить пробел после него.

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


10
Если это не тег, что это?
Данидакар

Можете ли вы привести пример? Может быть, мой конфиг php ненормальный, но я не могу воспроизвести проблему.
Данидакар

2
file1.php: <?php $i = 1; ?> затем file2.php:<?php include 'file1.php'; header('Location: http://www.google.com');?>
Квентин

1
Есть и недостатки в буферизации вывода; он использует больше памяти на сервере (так как весь вывод должен храниться в ОЗУ до тех пор, пока он не будет выведен; без буферизации он просто сразу уходит). Это также немного медленнее. В большинстве случаев это не будет проблемой, но я все равно ленив, так почему бы просто не оставить закрывающий тег выключенным? Я использую, phpcsчтобы убедиться, что закрывающий тег остается от каждого моего файла, а затем я не беспокоюсь о буферизации вывода :)
El Yobo

1
@danip: если вы установили флаг output_buffer в файле конфигурации php, вы не сможете воспроизвести эту проблему.
Джичао

16

Это довольно полезно, чтобы не допустить закрытия ?>.

Файл остается действительным для PHP (не является синтаксической ошибкой), и, как сказал @David Dorward, он позволяет избежать пробелов / переноса строки (всего, что может отправить заголовок в браузер) после ?>.

Например,

<?
    header("Content-type: image/png");
    $img = imagecreatetruecolor ( 10, 10);
    imagepng ( $img);
?>
[space here]
[break line here]

не будет действительным

Но

<?
    header("Content-type: image/png");
    $img = imagecreatetruecolor ( 10, 10 );
    imagepng ( $img );

буду.

На этот раз вы должны быть ленивы, чтобы быть в безопасности .


3
Вот почему я выделил курсивом. Он предотвращает ошибки, которые могут стоить вам много времени для нежелательного пространства после ?>. безопасность не может быть хорошим словом здесь. В любом случае, это ничего не исправляет (для меня это не плохой код, чтобы предотвратить вещи, echoздесь был бы плохой код), но / и он все еще действует. Докажите, что я не прав в этом.
Шикирю

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

1
Чученос, держу пари, ты имел в виду скорее безопасность, чем безопасность. ИМХО негу для этого было слишком много. Вернул тебя на круги своя. ;-) В конце концов, вы не сказали что-то не то. Даже рекомендации по разработке PHP поощряют вас делать это. Фактически, гораздо лучше полагаться на закрытие тегов, а не на буферизацию вывода, например. Последнее будет похоже на отключение display_errors. Чистый обман. И хороший шанс, что ваше приложение не будет портативным. Я действительно думаю, что, как правило, лучше вообще не полагаться на буферизацию вывода.
maraspin

1
Я не хочу задавать вопросы людям, которым нравится помещать ?>в конец файла только php. но вам когда-нибудь приходилось исправлять ошибки, вызванные конечными пробелами? Также не все серверы настроены одинаково, особенно когда вы переходите на другой хост, обнаружение этих ошибок занимает очень много времени. Если вы хотите положить, ?>просто сделайте это, если вы также добавите немного пробела и ваша команда должна отладить, чтобы быть готовым
обвинить в

16

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

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

Руководство по PHP> Справочник по языку> Основной синтаксис> Теги PHP


10

Ну, я знаю причину, но я не могу показать это:

Для файлов, которые содержат только код PHP, закрывающий тег ( ?>) никогда не разрешается. Это не требуется в PHP, и его пропуск предотвращает случайное внедрение конечного пробела в ответ.

Источник: http://framework.zend.com/manual/en/coding-standard.php-file-formatting.html


23
Этот тег «никогда не разрешается», вероятно, является стандартом кодирования Zend, но это не правило синтаксиса для форматирования файлов PHP.
Мэтт Хаггинс

9

Ну, есть два способа взглянуть на это.

  1. PHP-код - это не что иное, как набор инструкций по обработке XML , и поэтому любой файл с .phpрасширением - это не что иное, как XML-файл, который просто обрабатывается для PHP-кода.
  2. Так получилось, что PHP разделяет формат инструкций обработки XML для своих тегов open и close. Исходя из этого, файлы с .phpрасширениями МОГУТ быть действительными файлами XML, но они не должны быть такими.

Если вы верите первому маршруту, тогда все PHP-файлы требуют закрытия конечных тегов. Чтобы пропустить их, создаст недопустимый файл XML. Опять же, без вступительного <?xml version="1.0" charset="latin-1" ?>объявления у вас все равно не будет действительного XML-файла ... Так что это не главная проблема ...

Если вы верите второму маршруту, это открывает двери для двух типов .phpфайлов:

  • Файлы, содержащие только код (например, библиотечные файлы)
  • Файлы, которые содержат собственный XML, а также код (например, файлы шаблонов)

Исходя из этого, файлы только с кодом могут заканчиваться без закрывающего ?>тега. Но файлы XML-кода не могут заканчиваться без закрытия, ?>так как это сделает недействительным XML.

Но я знаю, о чем ты думаешь. Вы думаете, что это имеет значение, вы никогда не собираетесь визуализировать PHP-файл напрямую, поэтому кого волнует, является ли он действительным XML. Ну, это имеет значение, если вы разрабатываете шаблон. Если это допустимый XML / HTML, обычный браузер просто не будет отображать код PHP (он рассматривается как комментарий). Таким образом, вы можете макетировать шаблон без необходимости запуска кода PHP внутри ...

Я не говорю, что это важно. Это просто мнение, которое я не вижу выраженным слишком часто, так что может быть лучше, чтобы поделиться этим ...

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


1
Это совершенно неверно. PHP НЕ переводит эти теги в XML, и, следовательно, дисбаланс не генерируется.
Драченкаце

7
@Felicitus: Полагаю, вы пропустили ту часть, которая гласит: «Я не говорю, что это важно. Это просто мнение, которое я не вижу выраженным слишком часто, так что какое место лучше поделиться этим ...» Это не о PHP перевод тегов в XML. Речь идет о том, что происходит, когда файл интерпретируется в контексте XML (например, HTML или редакторы и т. Д.) ... Но момент упущен ...
ircmaxell

7

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

В Apache 2.4.6 с PHP 5.4 фактически возникают ошибки сегментации на наших производственных машинах, когда за закрывающим phpтегом есть свободное место . Я просто потратил впустую часы, пока, наконец, не сузил ошибку с помощью strace .

Вот ошибка, которую выдает Apache:

[core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11)

6

«Есть ли еще одна веская причина (кроме проблемы с заголовком) пропустить заключительный тег php?»

Вы не хотите непреднамеренно выводить посторонние символы пробела при генерации двоичного вывода, данных CSV или других выходных данных, отличных от HTML.


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

5

Pros

Cons

Вывод

Я бы сказал, что аргументы в пользу пропуска тега выглядят сильнее (помогает избежать большой головной боли с header () + это «рекомендация» PHP / Zend). Я признаю, что это не самое «красивое» решение, которое я когда-либо видел с точки зрения согласованности синтаксиса, но что может быть лучше?


2

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

  • С полной инструкцией по обработке синтаксиса ( <?php ... ?>) исходный код PHP является действительным документом SGML, который может быть проанализирован и обработан без проблем с синтаксическим анализатором SGML. С дополнительными ограничениями это может быть также действительный XML / XHTML.

Ничто не мешает вам писать действительный код XML / HTML / SGML. Документация PHP знает об этом. Выдержка:

Примечание. Также обратите внимание, что если вы встраиваете PHP в XML или XHTML, вам нужно будет использовать теги <? Php?>, Чтобы соответствовать стандартам.

Конечно, синтаксис PHP не является строгим SGML / XML / HTML, и вы создаете документ, который не является SGML / XML / HTML, точно так же, как вы можете превратить HTML в XHTML, чтобы он соответствовал XML или нет.

  • В какой-то момент вы можете захотеть объединить источники. Это будет не так просто, как просто сделать, cat source1.php source2.phpесли у вас есть несоответствие, введенное закрытием ?>тегов.

  • Без ?>него будет сложнее определить, был ли документ оставлен в режиме выхода из PHP или в режиме игнорирования PHP (тег PI <?phpможет быть открыт или нет). Жизнь становится проще, если вы постоянно оставляете свои документы в режиме игнорирования PHP. Это похоже на работу с хорошо отформатированными документами HTML по сравнению с документами с закрытыми, плохо вложенными тегами и т. Д.

  • Кажется, что некоторые редакторы, такие как Dreamweaver, могут иметь проблемы с открытым PI [1] .


0

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

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

И, возможно, именно поэтому большинство ответов вернулось к личному стилю и синтаксису.


0

Есть 2 варианта использования PHP-кода:

  1. PHP-код, такой как определение класса или определение функции
  2. Используйте PHP в качестве языка шаблонов (т.е. в представлениях)

в случае 1. закрывающий тег совершенно бесполезен, также я хотел бы видеть только 1 (один) открытый тег php и NO (нулевой) закрывающий тег в таком случае. Это хорошая практика, поскольку она делает код чистым и отделяет логику от представления. Для случая представления (2.) некоторые обнаружили, что естественно закрыть все теги (даже обработанные PHP), что приводит к путанице, поскольку на самом деле PHP имеет два отдельных варианта использования, которые не должны смешиваться: логика / исчисление и презентация

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.