ЭКСКЛЮЗИВ ВЕБ-ТЕХНОЛОГИИ
Ларионов Андрей Николаевич
Введение
Информационные технологии стремительно развиваются, и чтобы поспеть за данным прогрессом необходимо всегда быть в тренде. Для того чтобы актуализировать свои знания, следует искать информацию из разных источников в интернете, а также следить за новинками печатных изданий. Некоторые западные и отечественные авторы публикуют действительно крутые материалы, которые достойны изучения и вполне могут повысить свой профессиональный уровень.
Программирование сейчас развивается в разных направлениях. Одно из которых является также изучение и работа с Искусственным Интеллектом. Этот раздел кибернетики является прогрессивным и перспективным, так как он помогает программистам решать многие задачи, автоматизируя рутину и сокращая трудозатраты на решение типовых задач.
В этой книге я не будут рассматривать стандартные материалы и азы программирования. Вместо этого я напишу о том, что крайне мало пишут в сети и в книгах. Мы рассмотрим интересные примеры и пройдёмся по шагам реализации тех или иных задач, возникающих у веб-программиста. Меня зовут Ларионов Андрей, я являюсь автором многих фантастических и художественных книг. Также я являюсь весьма опытным Backend-разработчиком, который работал в Москве и крупных региональных компаниях, занимающихся разработкой информационных технологий. Я тот, кто старается идти в ногу со временем, занимаясь самообучением и познанием чего-то нового. Свой опыт и некоторые наработки хотел бы передать младшим поколениям, чтобы они что-то взяли для себя из данных материалов книги.
Данная книга подходит для школьников, студентов, которые решили связать судьбу с ИТ-сферой. Потому такие материалы будут полезны для их развития и становления, как профессионалов в своей деятельности. Но главное помнить всегда, что прогресс неизбежен, и данная книга, возможно, устареет буквально через пару годов с момента её выпуска. Хотя парадигмы программирования будут актуальны ещё долгое время. Потому эта книга — лишь промежуточное звено для изучения, один из шагов на пути к профессионализму, а также неплохой способ прокачать свои навыки. Ведь в любом случае информация, даже неактуальная, может быть полезна, как историческая концепция того, как развивалась информационная отрасль в веб-технологиях.
Итак, меньше пустых слов, и больше дел. Начнём с разных задач, в частности типовые вопросы на собеседованиях, парадигмы ООП, или как настроить Docker у себя на компьютере, какие нюансы существуют в новых версиях Laravel 10—11 и т. д.
Парадигмы программирования
Итак, все мы знаем, что каждый уважающий себя программист должен знать принципы ООП. Однако это только основа того, что предполагает высокоуровневое программирование. Кроме того существует ещё свод правил, которые рекомендовано использовать в процессе программирования. Итак рассмотрим их:
Рассмотрим каждую из парадигм программирования по отдельности.
— SOLID
SOLID — это акроним, который представляет собой пять принципов объектно-ориентированного программирования, направленных на улучшение проектирования и упрощение поддержки кода.
S — Single Responsibility Principle (SRP): Принцип единственной ответственности. Каждый класс должен иметь только одну причину своего существования, то есть он должен выполнять только одну задачу, а не представлять собой многофункциональный винегрет кода.
O — Open/Closed Principle (OCP): Принцип открытости/закрытости. Программные сущности (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для модификации. Это означает, что Вы можете добавлять новое поведение, не изменяя существующий код. Для этого, например, можно воспользоваться интерфейсами и трейтами.
L — Liskov Substitution Principle (LSP): Принцип подстановки Барбары Лисков. Объекты в программе должны быть заменяемыми экземплярами их подтипов без изменения правильности программы. Это означает, что подклассы должны быть взаимозаменяемыми с базовыми классами.
I — Interface Segregation Principle (ISP): Принцип разделения интерфейса. Клиенты не должны зависеть от интерфейсов, которые они не используют. Это означает, что лучше иметь несколько специализированных интерфейсов, чем один универсальный.
D — Dependency Inversion Principle (DIP): Принцип инверсии зависимостей. Высокоуровневые модули не должны зависеть от низкоуровневых; оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей; детали должны зависеть от абстракций.
— KISS
KISS — Keep It Simple, Stupid: Принцип «Делай это просто, глупо». Он подразумевает, что системы должны быть как можно проще. Сложные решения могут привести к ошибкам и трудностям в поддержке. Простота должна быть приоритетом в проектировании.
— DRY
DRY — Don’t Repeat Yourself: Принцип «Не повторяй себя». Он утверждает, что информация не должна дублироваться в коде. Если Вы видите повторяющийся код, это может быть признаком того, что его следует вынести в отдельную функцию или класс. Это помогает уменьшить количество ошибок и упрощает поддержку. Проблема избыточности кода решается посредством создания родительской абстракции, которая будет содержать в себе основные методы и свойства, которые будут присущи дочерним классам.
— YAGNI
YAGNI — You Aren’t Gonna Need It: Принцип «Вам это не понадобится». Он говорит о том, что не следует добавлять функциональность, пока она не станет необходимой. Это помогает избежать избыточности и усложнения кода, что делает его более управляемым и легким для понимания.
— DDD
DDD — Domain Driven Design: Что означает «Дизайн ориентированный на предметную область». DDD — это подход к разработке программного обеспечения, который акцентирует внимание на глубоком понимании предметной области (domain) и использовании этого понимания для создания модели, отражающей бизнес-логику. Основные принципы DDD включают:
— Унифицированный язык (Ubiquitous Language): Создание общего языка для общения между разработчиками и бизнес-экспертами, чтобы избежать недопонимания и обеспечить чёткость требований.
— Моделирование предметной области: Разработка моделей, которые точно отражают бизнес-логику, включая сущности, агрегаты, значения объектов и границы контекста (Bounded Contexts).
— DDD помогает строить более гибкие и поддерживаемые приложения, соответствующие реальным потребностям бизнеса.
Итак мы рассмотрели основные правила, помимо ООП, которые нам непременно понадобятся в процессе разработки. Эти принципы помогают разработчикам создавать более чистый, поддерживаемый и эффективный код.
Нюансы абстракции в ООП
Как известно любому сколь опытному программисту, что ООП представляет собой четыре основных принципа (наследование, полиморфизм, инкапсуляция и абстракция). Об абстракции иногда не говорят в официальных источниках по программированию. Однако это тоже является неотъемлемой частью процесса программирования. Итак в двух словах об этом.
Принцип абстракции ООП реализуются через создание абстрактных классов, либо через интерфейсы. Некоторые программисты не улавливают разницы между двумя этими возможностями и путаются в ответах на собеседованиях, судя по опубликованным данным в сети. Потому в данной главе мы разберём подробно разницу между двумя этими подходами.
Итак интерфейс и абстрактный класс — это два способа реализации абстракции в объектно-ориентированном программировании, но у них есть ключевые отличия:
Основные отличия:
— Интерфейс: Это контракт, который определяет набор методов, которые класс должен реализовать. Интерфейсы не могут содержать реализацию методов (в некоторых языках, таких как Java, начиная с версии 8, интерфейсы могут содержать методы по умолчанию).
— Абстрактный класс: Это класс, который не может быть инстанцирован и может содержать как абстрактные методы (без реализации), так и методы с реализацией.
Наследование:
— Интерфейс: Класс может реализовать несколько интерфейсов, что позволяет создавать более гибкие и модульные структуры.
— Абстрактный класс: Класс может наследовать только один абстрактный класс, что ограничивает гибкость.
Члены:
— Интерфейс: Все методы по умолчанию являются публичными и абстрактными. Поля интерфейса являются статическими и финальными.
— Абстрактный класс: Может содержать как публичные, так и защищённые методы и поля.
В PHP интерфейсы и абстрактные классы используются для определения структуры классов, но они имеют разные цели и ограничения.
Основные отличия:
Интерфейс:
— Не может содержать реализацию методов (до PHP 8.0, где появились методы с реализацией по умолчанию).
— Класс может реализовать несколько интерфейсов.
— Все методы в интерфейсе являются абстрактными и публичными по умолчанию.
Абстрактный класс:
— Может содержать как абстрактные методы (без реализации), так и методы с реализацией.
— Класс может наследовать только один абстрактный класс.
— Может содержать свойства и конструкторы.
Код на PHP типовой вариант реализации интерфейса и абстрактного класса (пример взят из интернета):
// Интерфейс
interface Shape {
public function area ();
}
// Абстрактный класс
abstract class Polygon {
protected $sides;
public function __construct ($sides) {
$this-> sides = $sides;
}
abstract public function perimeter ();
}
// Класс, реализующий интерфейс и наследующий абстрактный класс
class Rectangle extends Polygon implements Shape {
private $width;
private $height;
public function __construct ($width, $height) {
parent::__construct (4); // У прямоугольника 4 стороны
$this-> width = $width;
$this-> height = $height;
}
public function area () {
return $this-> width * $this-> height;
}
public function perimeter () {
return 2 * ($this-> width + $this-> height);
}
}
// Использование
$rectangle = new Rectangle (5, 10);
echo «Area:». $rectangle-> area (). "\n»; // Area: 50
echo «Perimeter:». $rectangle-> perimeter (). "\n»; // Perimeter: 30
?>
Этот вопрос часто встречается на собеседованиях при трудоустройстве, потому постарайтесь ответить на него правильно.
Инстанс и INSTANCEOF в PHP
Как вы заметили в предыдущем вопросе слово «инстанс», потому я поясню что это значит для тех, кто только изучает ООП и не знаком с такими терминами.
Инстанс в программировании (от англ. «instance» — «экземпляр», «пример») — это конкретный экземпляр объекта, созданный на основе определённого класса или шаблона.
Другими словами, это копия объекта, класса или системы, которая создаётся под конкретные задачи и запускается отдельно от других копий. В PHP инстанс (или экземпляр) — это конкретный объект, созданный на основе класса. Когда Вы создаёте объект, Вы фактически создаёте инстанс класса. Давайте рассмотрим пример.
<?
class Car {
// Свойства класса
public $color;
public $model;
// Конструктор класса
public function __construct ($color, $model) {
$this-> color = $color;
$this-> model = $model;
}
// Метод класса
public function displayInfo () {
return «Модель:». $this-> model.», Цвет:». $this-> color;
}
}
// Создание инстанса класса Car
$myCar = new Car («красный», «Toyota»);
// Вызов метода для отображения информации об автомобиле
echo $myCar-> displayInfo (); // Вывод: Модель: Toyota, Цвет: красный
?>
В данном примере мы написали класс Car с методами и свойствами. А также создали экземляр (инстанс) данного класса сохраненного в переменной $myCar. После чего вызываем метод dislpayInfo () и выводим на экран.
Таким образом, резюмируя вышесказанное, можно сказать, что инстанс — это конкретный объект, созданный на основе класса, который может иметь свои уникальные значения свойств и методы для работы с этими значениями.
Однако нам также необходимо иногда различать является созданный объект экземпляром класса. Для этого и существует оператор INSTANCEOF. В PHP оператор INSTANCEOF используется для проверки, является ли объект экземпляром определённого класса или его подкласса. Это полезно для реализации полиморфизма и для проверки типов объектов во время выполнения.
Рассмотрим пример (типовой вариант взятый из открытых источников):
<?
// Определяем базовый класс Animal
class Animal {
public function makeSound () {
return «Some sound»;
}
}
// Определяем подкласс Dog
class Dog extends Animal {
public function makeSound () {
return «Bark»;
}
}
// Определяем подкласс Cat
class Cat extends Animal {
public function makeSound () {
return «Meow»;
}
}
// Создаем экземпляры классов
$dog = new Dog ();
$cat = new Cat ();
// Проверяем типы объектов с помощью instanceof
if ($dog instanceof Dog) {
echo «This is a dog:». $dog-> makeSound ();
// Вывод: This is a dog: Bark
}
if ($cat instanceof Cat) {
echo «This is a cat:». $cat-> makeSound ();
// Вывод: This is a cat: Meow
}
if ($dog instanceof Animal) {
echo «A dog is an animal:». $dog-> makeSound ();
// Вывод: A dog is an animal: Bark
}
if ($cat instanceof Animal) {
echo «A cat is an animal:». $cat-> makeSound ();
// Вывод: A cat is an animal: Meow
}
?>
В данном примере мы создали два класса Dog и Cat, унаследованных от класса Animal. Далее мы проверяем через оператор instanceof принадлежность экземпляров к тому или иному классу.
Генераторы и итераторы
Ещё одним частым вопросом на собеседованиях бывает вопрос про генераторы и итераторы. Итак рассмотрим подробнее в чем разница между этими двумя понятиями, и что они означают в практическом программировании.
Генераторы и итераторы в PHP оба используются для создания последовательностей данных, но они имеют некоторые ключевые отличия:
Итератор: Это объект, который реализует интерфейс Iterator и предоставляет методы для обхода коллекции данных (например, current (), key (), next (), rewind (), valid ()).
Генератор: Это специальная функция, которая использует ключевое слово yield для возврата значений по одному за раз, не требуя создания отдельного класса.
Синтаксис: Генераторы имеют более простой и лаконичный синтаксис по сравнению с итераторами, так как не требуют реализации всех методов интерфейса.
Память: Генераторы более эффективны по памяти, так как они создают значения по мере необходимости, а не хранят их все в памяти, как это делает итератор.
Пример итератора на PHP
class MyIterator implements Iterator {
private $items = [];
private $position = 0;
public function __construct ($items) {
$this-> items = $items;
}
public function current () {
return $this-> items [$this-> position];
}
public function key () {
return $this-> position;
}
public function next () {
++$this-> position;
}
public function rewind () {
$this-> position = 0;
}
public function valid () {
return isset ($this-> items [$this-> position]);
}
}
$items = [1, 2, 3, 4, 5];
$iterator = new MyIterator ($items);
foreach ($iterator as $key => $value) {
echo «Key: $key, Value: $value\n»;
}
Вот же пример генератора на PHP:
function myGenerator ($items) {
foreach ($items as $item) {
yield $item;
}
}
$items = [1, 2, 3, 4, 5];
$generator = myGenerator ($items);
foreach ($generator as $key => $value) {
echo «Key: $key, Value: $value\n»;
}
Итак мы рассмотрели альтернативы генераций последовательностей данных. Этот практический опыт может быть использован при решении разных задач в программировании.
Класс для работы с БД на PHP
В данной главе я приведу пример класса для работы с БД. Здесь будет осуществлена реализация основных операций осуществляющихся при обмене данных (select, insert, update, delete).
Итак для начала создадим класс конфигурации, в который запишем только доступы от MySQL. Вот текст класса Class_Config.php:
class Class_Config {
public $ipBD = «localhost»;
public $NameBD = «my_bd»;
public $LoginBD = «root»;
public $PwdBD = «123»;
}
А класс Class_BD.php представлен также в этом же каталоге:
require_once('Class_Config.php’);
Class Class_BD
{
private $report_error1;
private $Config1;
public $current_date;
public $mysqli;
public $ModeEdit;
public $Current_code;
public function TestClass () {
return «Ответ от класса БД получен!»;
}
//////////////////////////////////////////////////////////////////
// Constructor. Create exemplar.
//////////////////////////////////////////////////////////////////
function __construct ()
{// Инициализация класса репорта ошибок
//print «Конструктор класса BaseClass\n»;
//$this-> report_error1 = new Report_error ();
$this-> Config1 = new Class_Config ();
$ModeEdit = false;
// Инициализация класса конфигуратора и подключение к бд
$this-> mysqli = new mysqli ($this-> Config1-> ipBD,
$this-> Config1-> LoginBD,
$this-> Config1-> PwdBD,
$this-> Config1-> NameBD);
if ($this-> mysqli-> connect_errno)
{
printf («No connect with BD: %s\n», $this-> mysqli-> connect_error);
exit ();
}
else {
$ModeEdit = true;
}
$CodeWeb = «RU»;
$this-> mysqli-> query («SET lc_time_names = ’ru_RU»»);
$this-> mysqli-> query («SET NAMES ’utf8»»);
$this-> current_date = date (’d.m.y’);
}
////////////////////////////////////////////////////////////////
// Private function execute sql
////////////////////////////////////////////////////////////////
public function external_query ($sql)
{
$result = $this-> mysqli-> query ($sql);
return $result;
}
///////////////////////////////////////////////////////////////
// public function — Simple table
///////////////////////////////////////////////////////////////
public function simple_select ($sql, $debug = false)
{
if ($debug == true) {
return $sql;
} else {
$result_set = $this-> mysqli-> query ($sql);
if (!$result_set) return false;
$i = 1;
$data = array ();
while ($row = $result_set-> fetch_assoc ()) {
$data [$i] = $row;
$i++;
}
$result_set-> close ();
return $data;
}
}
///////////////////////////////////////////////////////////////
// Function Annulate specsimbol
// хакинк против sql-иньекций
///////////////////////////////////////////////////////////////
public function _strip ($data)
{
$lit = array (»\\t», "\\n», "\\n\\r», "\\r\\n», «»,» (»,»)»);
$sp = array (»», «», «», «», «»,» [»,»]»);
return str_replace ($lit, $sp, $data);
}
///////////////////////////////////////////////////////////////
// Function _desrtip
// обращение символов
///////////////////////////////////////////////////////////////
public function _destrip ($data)
{
$lit = array (»& [&», '&] &»);
$sp = array (» (»,»)»);
return str_replace ($lit, $sp, $data);
}
///////////////////////////////////////////////////////////////
// Function xss blocking
// Хакинг против xss-атак
///////////////////////////////////////////////////////////////
public function xss ($data)
{
if (is_array ($data)) {
$escaped = array ();
foreach ($data as $key => $value)
{$escaped [$key] = $this-> xss ($value);}
return $escaped;
}
return htmlspecialchars ($data, ENT_QUOTES);
}
///////////////////////////////////////////////////////////////
// Function Insert of data
// $table_name — Name Table
// $fields — list of field’s
// $values — list of field’s
//
///////////////////////////////////////////////////////////////
public function insert ($table_name, $fields, $values, $debug = false)
{
if ((count ($fields)) == (count ($values)))
{
// Защита от xss-атаки
$esc_ = Array ();
foreach ($values as $key_ => $value_)
{
$esc_ [$key_] = $this-> _strip ($value_);
}
// Защита от ошибок экранирования
$values = $esc_;
$values = $this-> xss ($values);
$return_where =» (»;
//
for ($i = 0; $i <count ($fields); $i++)
{
if ((strpos ($fields [$i],» (») === false) && ($fields [$i]!= «*»))
$fields [$i] = "`». $fields [$i].»`»;
if ((strpos ($values [$i],» (») === false) && ($values [$i]!= «*»))
$values [$i] = «'». $values [$i].»'»;
$return_where.=» (`». $fields [$i].»` = «». $values [$i].»»)»;
if ($i <count ($fields) -1) $return_where.= " and»;
}
$return_where =»)»;
$fields = implode (»,», $fields);
$values = implode (»,», $values);
$table_name = $this-> Config1-> pref.$table_name;
$query = «Insert into `$table_name` ($fields) Values ($values)»;
if ($debug)
return $query;
else
{
$dt = $this-> mysqli-> query ($query);
return true;
}
}
else return false;
}
///////////////////////////////////////////////////////////////
//
// Function Delete of data — deleteRecord
// $table_name — Name Table
// $id — number delete record
// $debug — отладчик кода
//
///////////////////////////////////////////////////////////////
public function deleteRecord ($table_name, $id = «», $debug = false)
{
$table_name = $this-> Config1-> pref.$table_name;
if (empty ($id))
$query = «Delete from `$table_name`»;
else
$query = «Delete from `$table_name` Where (`id` =». $id.»)»;
$value = $this-> mysqli-> query ($query);
if (!$debug)
return $value;
else
return $query;
}
///////////////////////////////////////////////////////////////
//
// Function Delete of data — deleteRecordWhere
// $table_name — Name Table
// $id — number delete record
// $debug — отладчик кода
//
///////////////////////////////////////////////////////////////
public function deleteRecordWhere ($table_name, $where, $debug = false) {
$table_name = $this-> Config1-> pref.$table_name;
if (empty ($where))
$query = «Delete from `$table_name`»;
else
Бесплатный фрагмент закончился.
Купите книгу, чтобы продолжить чтение.