Вариант, когда нужны взаимные ссылки, предложен в статье — «владеющая ссылка».
К сожалению в статье не упомянут другой недостаток Rc/Arc — при неправильном употреблении они могут привести к утечке памяти.
А куда будет указывать ссылка?
Ссылку можно сделать, если известно, что объект «ученик» будет жить меньше, чем объект «школа».
Односторонние ссылки в этом случае проблемы не составляют.
У индекса/id есть преимущество — он не прибивает объект, на который ссылается, гвоздями к определённому месту в памяти.
«по логике» — достаточно сомнительное обоснование наличия ссылки у ученика.
Как вариант, индекс или id вполне могут выполнять роль «ссылки». Всё зависит от задачи, а задачи могут со временем меняться.
Справедливости ради PHP6 не релизился, поскольку сами разработчики признали неудачной попытку реализовать эту версию, вместо чего продолжили эволюцию ветки 5.x. Perl6 же вышел, когда интерес к Perl5 как таковому уже угас, а сам язык в современных представлениях сильно устарел и его нишу постепенно занимает Python2.
Вполне ожидаемо, что с роботизацией и освоением микро- и наноуровней, операции станут сильно проще и эффективней.
Для простых случаев можно предположить, что органы будут выращиваться не целиком, а по частям, и эти части будут выращиваться в самом организме где-то неподалёку. Здесь много мест для потенциальной оптимизации.
Но всё это никак не решает другую проблему: когда организм внезапно и серьёзно повреждён механически и для выживания требуется срочная замена уничтоженных органов. Тут только печатать и иметь запас готовых.
Если тебя вынуждают идти на преступление с тяжёлыми последствиями, это редко когда бывает «просто». Но преступление от этого не перестаёт быть преступлением.
Об этом и речь, когда ты знаешь, что к тебе пришёл условный «террорист» и просит настроить систему, которая будет использована во вред, ты — соучастник.
В описанной в статье ситуации — «устанавливающим и настраивающим» оказался по совместительству программист-разработчик. Не создатели тех языков и прочих инструментов, с помощью которых это было сделано, не создатели железа, не авторы учебников по созданию сайтов, а тот, кто выполнял ТЗ, в котором была поставлена цель — мошенничество. Это — соучастие. Сознательное.
Разумеется, список соучастников не ограничивается одним программистом, вина на всей руководящей цепочке и поддерживающей периферии, кто знал суть ТЗ — от руководителя до уборщицы, случайно услышавшей случайный разговор о сути проекта в курилке :-) Вину порождает и действие, и бездействие.
«не обращаешь внимания» ≠ «не нужно»
Функция ровно в том же виде может объявляться локально рядом (перед, после) с простыми вызовами. И тут уже имеет значение, что имелось в виду — то ли функция объявляется, то ли она вызывается.
Машинный парсер можно под самые экзотические случаи придумать. Но человеку будет много легче опираться на ключевые слова с подсветкой синтаксиса.
Пустой кортеж не бессмысленен, а означает ровно то, что задумано — пустое значение. То, что на него сделали «сахар» в виде необязательности указания, так даже и хорошо, никто пока обязательного указания не требовал. Опасаться подобного ничем не лучше, чем ходить в шапочке из фольги «а вдруг инопланетяне нас зомбируют?»
Вопрос был в общем про ромб (diamond problem).
Компоновку — хорошо — можно предоставить и как наследование при соответствующих возможностях языка, однако как бы мы компоненты ни заворачивали — они должны быть изолированы друг от друга, иначе они друг друга «покрошат», поскольку у них есть похожие части, которые выглядят одинаково, но отвечают за разные состояния и переопределённые в наследнике эти части могут удивить родителя. В примере выше — кроме отдельной кнопки — есть ещё отдельные внутренности, например, сервопривод. Если же всё это изолировано и работает независимо — смысл склеивать всё в один класс, чтобы потом всё время писать «такая-то часть класса» — уже дискуссионен. Но «осуждать» не зная особенностей конкретного языка — воздержусь.
В данном случае пример — это сама задача. Копир должен наследовать и принтер, и сканер. А это чуточку разные вещи, выполняющие разные задачи. «Старт» принтера и «старт» сканера — это не одно и то же, нельзя выбрать что-то одно из этого, нельзя «стартануть» их просто «по-очереди». Нужно, чтобы отработал сканер, забрать его результат и отдать обработать принтеру. Что в принципе независимый третий метод «старт».
То есть архитектура уже должна приводить к компоновке, а не наследованию и разведению «состояний» «в разные углы». Копир состоит из принтера и сканера, связывая их дополнительными функциями, но не наследует их свойства, как может показаться на первый взгляд.
«Проблема ромба» может возникать и без множественного наследования — это проблема некоторого общего ресурса, имеющего состояние, и нескольких владельцев, желающих его использовать. Открытый файл, общая память, синхронный протокол связи, сеанс на веб-сервере. То есть, столкнуться с нею в ФП-языке так же возможно, как и в ООП-языке, не реализующем множественное наследование. Множественное наследование — лишь частный случай.
Помимо гугла есть и другие пауки, причём, не только поисковые.
Хотя насчёт изоморфности не могу не согласиться в том, что это протекающая абстракция.
Речь максимум может идти о частичной изоморфности — у клиента и сервера разные задачи и разные возможности.
Ещё один неочевидный аспект такого репоста — это «поднятие» качественных статей из прошлого. Мне периодически всплывают такие статьи от тех, на кого я подписан, кто сейчас решает какую-то задачу и статья ему решить помогает. Бывает интересно почитать ленту закладок — там самый качественный материал хабра.
На самом деле всё ещё сложнее — добавленное в избранное — это своеобразный «репост» для фолловеров, как и звёздочка на гитхабе. Кто помнит об этой фиче — те просто так в избранное не добавляют. Поэтому «избранное» несёт двойственную и противоречивую роль — одни ещё не оценили, другие — оценили высоко и рекомендовали.
Скорее наоборот — скоро выкатят WA, и множество языков хлынут в браузер — во многих сообществах держат руку на пульсе, готовят и тестируют соответствующий инструментарий.
Так и есть — это полное пересечение и современые DBMS его хорошо «понимают».
Я не знаю, возможно это отпечаток какой-то привычки, но не могу подтвердить описанного эффекта — моё сознание просто воспринимает «берём то, что нам нужно». Я в реальной жизни не «джойню» в уме сущности, чтобы осознать такие вещи как «все читатели, которые держат хоть одну книгу, которой в наличии больше среднего». Само описание на русском языке в данном случае строится через взятие полного множества всех читателей и последовательного исключения из него через перечисление правил — это, прямо скажем, легко и естественно. И это хорошо ложится на структуру FROM [источники данных] WHERE с перечислением вышеуказанных ограничений. По другому мне наверно нужно было бы думать «возьмём все комбинации книг, читателей и записей в формулярах, теперь начнём проверять, что id читателя указан в одной из записей о чтении и id книги указан в этой же записи, при этом в наличии этой книги больше среднего». Это слишком непривычно, чтобы читать подобным образом, хотя технически именно это и написано.
Секция FROM — техническая, в ней просто перечислены сущности, секция WHERE логическая — в ней перечислены правила, идущие из естественного языка и при их естественном чтении легко искать ошибки.
Вот так это выглядит для меня:
SELECT -- возьмём:
member.first_name || ' ' || member.last_name AS "full_name" -- имя и фамилию читателя, объединив их в одну строку
FROM -- будем смотреть источники:
member, book, borrowing -- «читатель», «книга», «задолженность»
WHERE -- ожидая получить:
member.id = borrowing.member_id AND -- «все читатели, которые держат ...»
book.id = borrowing.book_id AND -- «... хоть одну книгу, ...»
book.stock > (SELECT avg(stock) FROM book) -- «... которой в запасе больше среднего»
Подобная логическая интерпретация сразу позволяет обратить внимание на «странности», которые были бы неочевидны в разбросанных JOIN… ON — сравните исходный запрос и реорганизованный и обратите внимание на тезис, с которого начиналась статья — «SQL очень далёк от естественного языка». Получается, что он на самом деле не так уж и далёк, хотя тезис справедлив, поскольку речь шла немного о другом. Можно с помощью ORM нагенерировать ужас, понятный только машине и SQL это с радостью позволит. Но можно адаптировать для человека — у нас есть для этого достаточно свободы.
Одна проблема: человеки сразу займутся сравнением вкуса фломастеров и этого у нас не отнять :-)
Так все три одинаковы. Разная сложность чтения. Все три источника в любом случае нужно держать в уме, а визуально искать легче, когда искать нужно в одном месте, а не разбросанные по запросу. Перечисленные через запятую они «собираются» — «одним взглядом», растянутые на несколько строчек — пока найдёшь одно, можешь уже забыть другое (особенно в сложном запросе).
В монстро-запросе будет другая ситуация. Если планировщик базы хорошо оптимизирует подобное — возможно имеет смысл разбивать сложный запрос на более простые и оформлять их в виде функций или WITH выражений, хотя это не всегда полезно.
Я не претендую на истину в последней инстанции и всегда можно найти обратный пример. Просто привёл пример для сравнения, как можно упростить простой запрос и сделать его легко читаемым для человека. Фанатизм же до добра не доведёт.
Это кажется незначительным различием в простом запросе. Но когда запрос сложный и нужно посидеть, «распарсить» его и понять — каждая подобная мелочь сильно облегчает работу.
К сожалению в статье не упомянут другой недостаток Rc/Arc — при неправильном употреблении они могут привести к утечке памяти.
Ссылку можно сделать, если известно, что объект «ученик» будет жить меньше, чем объект «школа».
Односторонние ссылки в этом случае проблемы не составляют.
У индекса/id есть преимущество — он не прибивает объект, на который ссылается, гвоздями к определённому месту в памяти.
Как вариант, индекс или id вполне могут выполнять роль «ссылки». Всё зависит от задачи, а задачи могут со временем меняться.
Для простых случаев можно предположить, что органы будут выращиваться не целиком, а по частям, и эти части будут выращиваться в самом организме где-то неподалёку. Здесь много мест для потенциальной оптимизации.
Но всё это никак не решает другую проблему: когда организм внезапно и серьёзно повреждён механически и для выживания требуется срочная замена уничтоженных органов. Тут только печатать и иметь запас готовых.
В описанной в статье ситуации — «устанавливающим и настраивающим» оказался по совместительству программист-разработчик. Не создатели тех языков и прочих инструментов, с помощью которых это было сделано, не создатели железа, не авторы учебников по созданию сайтов, а тот, кто выполнял ТЗ, в котором была поставлена цель — мошенничество. Это — соучастие. Сознательное.
Разумеется, список соучастников не ограничивается одним программистом, вина на всей руководящей цепочке и поддерживающей периферии, кто знал суть ТЗ — от руководителя до уборщицы, случайно услышавшей случайный разговор о сути проекта в курилке :-) Вину порождает и действие, и бездействие.
Функция ровно в том же виде может объявляться локально рядом (перед, после) с простыми вызовами. И тут уже имеет значение, что имелось в виду — то ли функция объявляется, то ли она вызывается.
Машинный парсер можно под самые экзотические случаи придумать. Но человеку будет много легче опираться на ключевые слова с подсветкой синтаксиса.
Пустой кортеж не бессмысленен, а означает ровно то, что задумано — пустое значение. То, что на него сделали «сахар» в виде необязательности указания, так даже и хорошо, никто пока обязательного указания не требовал. Опасаться подобного ничем не лучше, чем ходить в шапочке из фольги «а вдруг инопланетяне нас зомбируют?»
Компоновку — хорошо — можно предоставить и как наследование при соответствующих возможностях языка, однако как бы мы компоненты ни заворачивали — они должны быть изолированы друг от друга, иначе они друг друга «покрошат», поскольку у них есть похожие части, которые выглядят одинаково, но отвечают за разные состояния и переопределённые в наследнике эти части могут удивить родителя. В примере выше — кроме отдельной кнопки — есть ещё отдельные внутренности, например, сервопривод. Если же всё это изолировано и работает независимо — смысл склеивать всё в один класс, чтобы потом всё время писать «такая-то часть класса» — уже дискуссионен. Но «осуждать» не зная особенностей конкретного языка — воздержусь.
То есть архитектура уже должна приводить к компоновке, а не наследованию и разведению «состояний» «в разные углы». Копир состоит из принтера и сканера, связывая их дополнительными функциями, но не наследует их свойства, как может показаться на первый взгляд.
«Проблема ромба» может возникать и без множественного наследования — это проблема некоторого общего ресурса, имеющего состояние, и нескольких владельцев, желающих его использовать. Открытый файл, общая память, синхронный протокол связи, сеанс на веб-сервере. То есть, столкнуться с нею в ФП-языке так же возможно, как и в ООП-языке, не реализующем множественное наследование. Множественное наследование — лишь частный случай.
Хотя насчёт изоморфности не могу не согласиться в том, что это протекающая абстракция.
Речь максимум может идти о частичной изоморфности — у клиента и сервера разные задачи и разные возможности.
Я не знаю, возможно это отпечаток какой-то привычки, но не могу подтвердить описанного эффекта — моё сознание просто воспринимает «берём то, что нам нужно». Я в реальной жизни не «джойню» в уме сущности, чтобы осознать такие вещи как «все читатели, которые держат хоть одну книгу, которой в наличии больше среднего». Само описание на русском языке в данном случае строится через взятие полного множества всех читателей и последовательного исключения из него через перечисление правил — это, прямо скажем, легко и естественно. И это хорошо ложится на структуру FROM [источники данных] WHERE с перечислением вышеуказанных ограничений. По другому мне наверно нужно было бы думать «возьмём все комбинации книг, читателей и записей в формулярах, теперь начнём проверять, что id читателя указан в одной из записей о чтении и id книги указан в этой же записи, при этом в наличии этой книги больше среднего». Это слишком непривычно, чтобы читать подобным образом, хотя технически именно это и написано.
Секция FROM — техническая, в ней просто перечислены сущности, секция WHERE логическая — в ней перечислены правила, идущие из естественного языка и при их естественном чтении легко искать ошибки.
Вот так это выглядит для меня:
Подобная логическая интерпретация сразу позволяет обратить внимание на «странности», которые были бы неочевидны в разбросанных JOIN… ON — сравните исходный запрос и реорганизованный и обратите внимание на тезис, с которого начиналась статья — «SQL очень далёк от естественного языка». Получается, что он на самом деле не так уж и далёк, хотя тезис справедлив, поскольку речь шла немного о другом. Можно с помощью ORM нагенерировать ужас, понятный только машине и SQL это с радостью позволит. Но можно адаптировать для человека — у нас есть для этого достаточно свободы.
Одна проблема: человеки сразу займутся сравнением вкуса фломастеров и этого у нас не отнять :-)
В монстро-запросе будет другая ситуация. Если планировщик базы хорошо оптимизирует подобное — возможно имеет смысл разбивать сложный запрос на более простые и оформлять их в виде функций или WITH выражений, хотя это не всегда полезно.
Я не претендую на истину в последней инстанции и всегда можно найти обратный пример. Просто привёл пример для сравнения, как можно упростить простой запрос и сделать его легко читаемым для человека. Фанатизм же до добра не доведёт.
читается легче, чем
Это кажется незначительным различием в простом запросе. Но когда запрос сложный и нужно посидеть, «распарсить» его и понять — каждая подобная мелочь сильно облегчает работу.