1. Чем отличаются PHP и javascript?
Между PHP и JavaScript существует несколько ключевых отличий - PHP в основном используется в качестве скриптового языка для разработки бэкендов, причём исторически предполагалось что он именно скриптовый язык, который отдаёт целиком страницы. JavaScript в свою очередь разрабатывался как язык для интерактивности в браузерах, что со временем сильно изменилось, и сегодня JavaScript позволяет не только разработку в браузере, но и предлагает разработку бэкендов с его использованием.
В оригинальном JavaScript, как такового практически нет ООП, впрочем в ранних версиях PHP его тоже не было, но сегодня существуют диалекты JavaScript, как например TypeScript и т.д. PHP исторически создан для того чтобы "умирать" - т.е., пришёл запрос по FCGI (например через Nginx) приложение отработало, вернуло ответ и умерло. JavaScript на бэкенде работает иначе (в основном) - существует реализации веб-серверов на Event Loop (что очень хорошо подходит для асинхронной модели, поскольку задача по большей части I/O bound, а не CPU - если всё сделано правильно), которые способны прослушивать порт и без использования внешнего веб-сервера отдавать запросы, но в продакшене всё равно используют внешний веб сервер, поскольку в данном случае можно обработать намного больше запросов, имплементировать горизонтальное масштабирование и т.д.
С точки зрения типизации оба довольно похожи, оба являются интерпретируемыми (впрочем существует и реализации с использованием JIT, трансляции и т.д., например kPHP).
2. Когда стоит делать классу приставку final и почему? А abstract?
Ключевое слово final в PHP позволяет ограничить дальнейшее наследование класса, т.е. мы не сможем наследовать текущий класс в другом классе. Это помогает избавиться от дальнейших проблем с деревом наследования, так же поощрает использование композиции, поскольку в случае с наследованием бывает тяжело проводить тестирование. Большое дерево наследования считается плохим тоном.
abstract - означает абстрактный класс, в PHP его активно используют для базовых объектов, от которых в дальнейшем наследуются другие классы. По сути это интерфейс с возможностью задать некоторые общие методы для классов имплементирующих данный интерфейс. Пример - хранение данных, это может быть SQLite, MySQL, S3 и т.д. мы можем поместить в базовый абстрактный класс задание и получение конфига (что лучше на самом деле реализовать через отдельный интерфейс).
3. Для чего может быть уместно использовать git rebase?
Из того что сразу приходит в голову:
Мы находимся в ветке, в которой разрабатываем новую фичу, в это время параллельно ведётся работа в других ветках, например ветке dev (где ведётся разработка), мы хотим смерджить новые коммиты, поскольку мы отбранчевались раньше, но не хотим иметь коммиты Merged into..
- в этом случае мы можем сделать ребейз - в случае конфликтов мы можем в дальнейшем их разрезолвить средствами Git (в случае с rebase покомитно для каждого где есть конфликт).
5. С какой целью стоит деактивировать кнопку отправки данных HTML-формы (если данные отправляются асинхронно через AJAX, без перезагрузки страницы), до получения ответа от сервера?
Это было необходимо, чтобы не допустить дублирования данных, поскольку пользователь интерфейсно не понимает что происходит. Хорошее решение в этом случае показать что происходит какая-то обработка (крутилки, loading и т.д.). В целом не вижу никаких проблем если не деактивировать, поскольку к любому пользовательскому вводу мы должны относиться как к условно-зловредному. В случае с получением каких-то данных, нет смысла делать тоже самое получение дважды - лишняя нагрузка.
6. Вопрос-задачка
Ваша библиотека работает с объектами классов, имплементирующих интерфейс, в котором есть метод getFormName()
. На данный момент в проекте имеется несколько классов, имплементирующих этот интерфейс, у которых есть публичное свойство $formName
, а также метод getFormName()
, возвращающий это свойство.
<?php
interface FormInterface
{
public function getFormName(): string;
}
class ClassOne implements FormInterface
{
public $formName = 'ClassOneForm';
public function getFormName(): string
{
return $this->formName;
}
}
class ClassTwo implements FormInterface
{
public $formName = 'ClassTwoForm';
public function getFormName(): string
{
return $this->formName;
}
}
function workWithForm(FormInterface $formClass): string
{
if ($formClass->formName) {
return 'Form Name: '.$formClass->formName;
}
return '';
}
echo workWithForm(new ClassTwo());
?>
Вопросы:
- Что будет выведено на экран при выполнении данного скрипта?
- Почему можно сказать, что тело функции workWithForm() написано некорректно?
Ответы
- PHP - динамический язык программирования, поэтому будет выведено '...: ClassTwoForm', мы воспользовались свойством языка, что иногда может быть полезно, но это не является правильным решением.
- Мы используем интерфейс, в котором содержится метод получающий
formName
, но вместо использования этого метода, мы используем особенности реализации нескольких классов, что может в определенный момент быть не так (может не быть этого свойства, или оно будет иметь другой уровень защиты) и такую проблему может быть не легко обнаружить. Так же, тестирование в этом случае осложнено.
Вопросы:
- Если в проект будет подключена библиотека, в которой есть класс ClassHundred, что будет выведено на экран в следующем скрипте?
<?php
class ClassHundred implements FormInterface
{
public $formNameSimple = 'ClassHF';
public $formNameFull = 'ClassHundredForm';
public $simple = false;
public function __construct($simple = false)
{
$this->simple = $simple;
}
public function getFormName(): string
{
if ($this->simple) {
return $this->formNameSimple;
}
return $this->formNameFull;
}
}
echo workWithForm(new ClassHundred(true));
?>
- Почему можно сказать, что тело функции workWithForm() написано некорректно?
- Если в проект будет подключена библиотека, в которой есть класс ClassHundred, что будет выведено на экран в следующем скрипте?
Ответы
- До исправления - функция
workWithForm
вернёт пустую строку, а так же если мне не изменяет память warning о том, что свойства formName не существует - Необходимо заменить проверку свойства и return на
return ...$formClass->getFormName()
- Интерфейсы уместно использовать когда нам необходим соотвествующий уровень абстракции, например получение данных из разных источников. Или различные API для каких-либо задач, например использование нескольких СМС гейтов. Про уместность использования проще говорить предметно, но моё личное мнение, что излишняя абстракция зачастую только вредит, когда наступит момент, что действительно необходимо добавить слой, я считаю имено тогда необходимо это делать. Интерфейсы сильно помогают с уменьшением связанности кода и с следованием всяким хорошим вещам как Паттерны, DRY, KISS, SOLID и т.д.
7. В чём разница между интерфейсом и трейтом в PHP? Для чего их уместно использовать в проекте?
Трейт - примесь, грубо говоря там где используется трейт происходит помещение кода трейта в этом месте, что-то вроде #include
в C. Я считаю использование трейтов чаще вредит и лучше прибегнуть к композиции, но для простых вещей, которые не связывают между собой критические элементы их можно использовать.