Alex Gusev@flancer
Я кодирую, потому что я кодирую…
Information
- Rating
- Does not participate
- Location
- Рига, Латвия, Латвия
- Date of birth
- Registered
- Activity
Specialization
Фулстек разработчик
Ведущий
From 3,000 €
JavaScript
HTML
CSS
Node.js
Vue.js
Веб-разработка
Progressive Web Apps
PostgreSQL
MySQL
GitHub
2. Если это невозможно сделать на PHP, то попробуйте изложить ваши мысли на Java/C/JavaScript/Python. У меня есть кое-какой опыт в этих языках и, надеюсь, я смогу понять, что вы хотите донести.
3.Т.е., вы утверждаете, что название «функциональная парадигма» не отражает сути?
4. Согласен, разница есть. Считайте, что я привел пример для случая, когда разработчик базового функционала ничего не знает о разработчиках плагинов, а разработчики плагинов знают только базовый функционал и не могут никаким образом повлиять ни на него, ни друг на друга.
5. Спешу вас расстроить а) PHP вполне позволяет строго использовать типизацию, б) вы все еще не поняли, что даже самая расстрогая типизация не дает возможности создавать изолированным командам разработчиков общее приложение, даже наоборот — мешает.
6. В самом общем случае вообще ничего нет — есть и такая теория.
2. Я сделал вывод о том, что «функциональная парадигма делает акцент на вычислениях» на основании названия этой самой парадигмы, вы в свою очередь сказали, что «название обманчиво» и привели в качестве примера LISP. Я обратил ваше внимание на то, что мы говорим не про LISP, а именно про «функциональную парадигму» и в данном конкретном случае название вполне соответствует сути:
А теперь вы предлагаете мне показать функциональный язык (из мейнстрима), в котором нет обширной поддержки структур данных.. Похоже, вы просто потеряли нить обсуждения.
3. Потому что при распределенной разработке вполне возможен вариант, когда разработчики не могут договориться друг с другом просто в силу того, что они не знакомы друг с другом. Более того, я спорадически интегрирую такие решения друг с другом. Это Magento.
4. Но это и не означает обратного.
5. Если вы не видите выигрыша, то вам не и стоит этого делать. Если вдруг увидите выигрыш — тогда и применяйте.
Вот в этом месте лишние атрибуты. Разработчик базового функционала заложил только $id. Атрибут $ref заложил разработчик плагина 1, атрибут $email — разработчик плагина 2. Разработчики друг с другом не знакомы. Поэтому базовый класс выглядит по идее как-то так:
После чего у интегратора и начинается свистопляска с различными переопределениями. Акцентирую еще раз — весь фокус в том, что разработчики плагинов ничего не знают друг про друга, каждый из них знает только структуру базового объекта и свои собственные дополнения.
По поводу сохранения. В Magento при обращении к БД считывается структура таблиц со всеми атрибутами и при сохранении фильтруются «лишние» из $data. Это дело кэшируется, поэтому иногда получается весьма забавно, когда поля в таблице есть, а сохранить в них ничего нельзя. Но все лечится путем удаления кэша.
и создает свои собственные расширения базового объекта CustomerRef & CustomerEmail:
допустим, есть внешний класс для выполнения операций с БД (разделение инструкций и данных, детали его реализации на данный момент не важны). В этом случае в базовой имплементации подгружается объект со всеми своими атрибутами и используется в таком виде в базовом workflow. В местах, где включаются обработчики плагинов (допустим, по событию), они преобразовывают базовые данные в понятный для себя вид и работают со «знакомыми» атрибутами, игноря атрибуты незнакомые. В конце базового workflow происходит сохранение объекта в БД:
По сути дела производный от DataObject класс в некотором роде и является для среды выполнения адаптером к данным, хранимым в ассоциативном массиве. Все то же самое, при желании, можно изобразить и просто на ассоциативном массиве, только без autocomplete'а в IDE и без возможности поиска Find Usages.
2. Я имел в виду не LISP, я имел в виду именно «функциональное программирование».
3. «Строго типизированный» DTO не удовлетворяет условию «распределенной разработки» — там по определению не может быть строгой типизации.
4. Практика «игнорирую то, чего не знаю» весьма хорошо сочетается с «универсальным контейнером».
5. То, что это ассоциативный массив никак не отменяет того, что он может использоваться в качестве «универсального контейнера данных».
а) типизируемым;
б) дополняемым;
Меня в Magento весьма сильно напрягало, что в таких структурах никогда точно не знаешь, что лежит, и сильно радовало, что в них всегда можно положить все, что угодно. Проблема в том, что в некоторых случаях множественное наследование не работает. Например, когда два-три расширения переопределяют один и тот же класс основного функционала. Разработчик каждого плагина не знает о существовании других плагинов, да и не должен. А я, как интегратор, должен сам решать в каком порядке мне выстроить иерархию наследования в конечном приложении. И иногда это бывает довольно забавной задачей, если учесть, что порой приходится совмещать в одном приложении по 15-20 сторонних плагинов.
В подобной ситуации вот такой DataObject + «гарвардский» подход (отделение данных от инструкций, функциональное программирование, если кому удобнее) может дать весьма ощутимые бонусы в виде конвейеризации обработчиков некоей «структуры данных».
Во втором случае адрес элемента в массиве данных напоминает привычные пути (файловые, XPath, JSONPath), что позволяет использовать уже существующие методы работы с подобной информацией. При помощи аннотаций его можно слегка «дотипизировть», оставляя тем не менее дополняемым на уровне исполнения.
Вы правы в том, что все данные одной не очень большой базы можно воткнуть в обычный ассоциативный массив. И да, это будет универсальный контейнер. А если его использовать без добавления инструкций по обработке, то это и будет универсальный контейнер данных. Вот только не будет отражена структура «известных данных», что изрядно усложнит разработку. Хотя можно сделать «типизатор» данных, который для любого произвольного массива будет извлекать данные нужной структуры. Это тоже путь.
вместо
Даже визуально видно, что сложность уменьшилась минимум в 2 раза.
2. На основании названия.
3. Если DTO полностью удовлетворяет условиям, значит его можно использовать в качестве «универсального контейнера данных».
4. Если есть расширяемость на уровне данных, то значит в SOA уже используется концепция «универсального контейнера данных». Да, я знаю, как расшифровывается XML.
5. Нет, это вы не поняли. Если вы используете любой способ структурирования данных для формирования «посылки» с произвольным содержимым, то вы таким образом создаете «универсальный контейнер данных». Даже если сами об это не подозреваете. А я просто обращаю ваше внимание на этот аспект «обработки структурированных данных». Вы могли всю жизнь программировать в определенном стиле, не подозревая об этом, а потом я пришел и сообщил, что для вашего стиля характерны определенные черты, и дал ему название «функциональное программирование».
6. Если он полностью удовлетворяет, то является.
2. Функциональная парадигма делает акцент на вычислениях, я же делаю ацент на данных. В обоих случаях рассматривается один и тот же посыл — «отделение данных от инструкций», который был предложен еще 70-80 лет назад Говардом Эйкеном.
3. В таком случае DTO нельзя использовать как «универсальный контейнер данных».
4. Не отличается, но дополняет — вводит расширяемость на уровне данных в «чётко определённые интерфейсы» SOA.
5. «Универсальный контейнер данных» — это более узкий термин, чем «любой способ обработки структурированных данных». «Контейнер» подразумевает краткосрочное хранение при передаче, «универсальный» подразумевает независимость от содержимого, «данные» подразумевают данные. Это все равно спросить «Зачем вводить понятие 'функционального программирования', когда уже есть всем понятный термин 'программирование'».
6. В таком случае, типизируемый объект не может являться универсальным контейнером данных.
7. См. п.2
2. В некотором смысле этот подход является следствием функциональной парадигмы.
3. В таком случае «DTO — как паттерн» можно использовать в качестве универсального контейнера данных;
4. Знаю.
5. Чтобы не смешивать данные и обрабатывающий их код — как в DTO.
6. Если типизируемый объект позволит добавлять к себе любую структуру данных и выдавать ее — то он и будет являться универсальным контейнером. Именно это и позволяют делать объекты, наследующие от DataObject.
2. Слышал.
3. Если DTO не зависит от типа переносимых данных — да, это он и есть.
4. Buzzword SOA — не понимаю, о чем это.
5. Самое главное в этой концепции: мухи (код обработчиков) отдельно, а котлеты (обрабатываемые данные) — отдельно. А если «мухи» и/или «котлеты» будут в виде типизируемых объектов — так оно даже и лучше.
2. Можно при сериализации использовать и внешнюю функцию — это не принципиально. Принципиально, что сериализуются любые данные — и те, которые уложил в контейнер разработчик основного функционала, и те, которые в этот же контейнер уложил разработчики плагинов для основного функционала.
3. Один входной объект для функции и один выходной — это принципиальный вопрос для конвейеризации. Если вы посмотрите на web-сервисы, то увидите, что именно так и есть — на вход подается одна структура данных (request), на выходе получается другая, но тоже одна (response). В request'е объединены воедино все данные, необходимые для выполнения операции сервисом (как и в запросе) — сервис сам может выбрать из запроса нужные ему данные (а плагин к сервису может выбрать из этого же запроса нужные ему).
2. Любая DBMS является довольно-таки универсальным контейнером данных.
3. Я использую подход с акцессорами только лишь из-за привычки ожидать подсказки от IDE после набора префикса get/set. Мне так удобнее. Чтобы не путать с другими методами при использовании автодополнения. Но если мы работаем с контейнером данных, то там не должно быть других методов, кроме акцессоров, так что можно обойтись и самими свойствами.
4. В моем примере A, B и C — это представители различных уровней приложения, разных «вселенных». Это как запросить данные из программы на JavaScript у сервиса, написанного на Java. Java-сервис может изменять запрос сколько угодно — он работает с копией, созданной на основании транскода (XML в случае с SOAP).
5. Менять входные данные — не очень хорошая практика, даже если ты создаешь весь код сам, а уж если ты работаешь в команде, то надо много раз подумать, чтобы решится на это.
6. Если все-таки приходится сталкиваться с тем, что моя или чья-то еще функция/метод изменяет входные данные, то — да, меня это напрягает.
Для себя я решил задачу экстрагирования в статье небольшого размера сути подхода по отделению обрабатываемых данных от обработчиков, что, на мой взгляд, является одним из краеугольных камней при распределенной разработке (слабосвязанными командами разработчиков) гетерогенных программных систем (типичный пример — web-приложение), интегрированных с внешними сервисами посредством SOAP/REST и адаптируемых конечным пользователем под изменяющиеся условия применения.
Да, это довольно узкоспециализированное направление, достаточно сильно отличающееся, например, от «программирования игр под андроид», но, к сожалению, на habr'е нет отдельной категории для подобных направлений, поэтому я и запостился в общий хаб «Программирование». Прошу прощения у всех, кого отвлек этим своим постом от забот насущных.
IMHO, в наше стремительно летящее время приложения должны разрабатываться в том виде, в каком девелоперу удобно их создавать и изменять (второе даже важнее первого). И если девелоперу удобнее создавать и изменять (второе важнее) приложение с использованием JS — он будет это делать с использованием JS. Более того, этого будет требовать сам заказчик разработки. Ну а пользователи… 80% пользователей приложения проапргрейдятся, 20% будут выкинуты на обочину курить бамбук.
Я не имею в виду, что JS «захватит мир», я имею в виду, что «одноядерный 32-битный Pentium 4 Northwood» это если и не 20%, то уже очень близко к нему.