All streams
Search
Write a publication
Pull to refresh
22
0
Алексей @pankraty

Разработчик

Send message
На метод удаления треков из плейлиста, помимо самого ID плейлиста и рамок с и по какой трек удалить, они зачем-то передают треки, которые будут удалены.


По-моему, тут явно удивление тому, зачем передавать треки, а не зачем передавать «с» и «по».

Касаемо удаления треков из плейлиста. Представим, что реализовано через указание ID плейлиста и номеров С и По. А дальше смоделируем следующие ситуации:


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

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

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

Выбирать место наибольшего скопления котиков по наименьшему треугольнику — неправильно. Представьте пустую поляну, где в одном краю 100 котиков на расстоянии, в среднем, 30 см между каждой парой, а в другом — в коробке 20*20 три котенка. Ваша мята достанется котятам.


Разумнее разделить поляну регулярной сеткой, например, гексагональной (тут триангуляция Делоне тоже пригодится), выбрав размер ребра сопоставимым с расстоянием, с которого котик чует мяту. Потом подсчитать количество котиков в каждой ячейке и уже из них выбирать максимум(ы). Это не гарантирует достижения теоретического максимума количества осчастливленных котиков, т.к. начальная точка для сетки выбирается произвольно, но даёт результат, достаточно хороший для большинства практических целей.

ОК, переименуем мы a и b в firstEdge и secondEdge. Splice — в AttachTwoEdgesTogetherOrBreakThemApart. Можем даже разбить на несколько методов. Только я сомневаюсь, что станет сильно понятнее.

А можно в комментарии дать ссылку на оригинал публикации, в которой не только разъясняются, для чего нужен QuadEgde, и что такое Splice, но и математически доказывается корректность алгоритма. И тому, кто будет разбираться с кодом намного удобнее будет видеть a, b, alpha, beta, Splice, Rot (1-в-1 соответствующие примерам в статье), а не наши искуственно выделенные функции и переименованные аргументы.
То есть, по вашему, краткий и лаконичный комментарий может быть длиннее по количеству символов чем непосредственная реализация?


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

public static void Splice(QuadEdge a, QuadEdge b)
{
	var alpha = a.ONext.Rot;
	var beta = b.ONext.Rot;

	var t1 = b.ONext;
	var t2 = a.ONext;
	var t3 = beta.ONext;
	var t4 = alpha.ONext;

	a.SetNext(t1);
	b.SetNext(t2);
	alpha.SetNext(t3);
	beta.SetNext(t4);
}

// Due to bug in version 2.5.345 we have to explicitly add [something] so that clients using that version would not crash


Что характерно, даже если этот кусок логики покрыт тестами, это не застрахует от того, что кто-то в угаре рефакторинга не выпилит этот кусок логики вместе с тестами, если там не будет объяснения, что это костыль добавленный с такой-то целью.
В идеальном мире код пишется без костылей. В реальном мире — костыли желательно хотя бы снабжать комментариями.

Вот статья, из которой я узнал про это https://m.habr.com/en/post/440576/
Отложилось в памяти, что это какая-то новая возможность, но не запомнил, это уже в релизе или в планах.
По работе с постгресом уже несколько лет не взаимодействовал, да и до этого не скажу чтобы прям глубоко погружался, так что многих тонкостей не знаю.

Возможно, вы путаете Postgres с MS SQL. В последнем действительно CTE — это поздзапрос, записанный в другой форме, а в Postgres оно материализуется (вроде бы в какой-то из последних версий добавили возможность не материализовывать CTE с помощью опции).


Что касается довода "SQL декларативный язык. То, что господин Manish с помощью переписывания текста запроса в другом формате получил более быстрое выполнение, это означает либо проблемы оптимизатора запросов у PostgreSQL..." — это так не работает. Да, оптимизатор не всесилен, и если переписывание запроса помогает ускорить его в десятки раз — надо переписывать. Ну или ждать, когда вендор научит СУБД правильно оптимизировать такой вариант запроса.

Недавно ревьювил код, и там было использовано слово forbid. У меня возникло ощущение, что ему тут не место, хотелось предложить заменить на prohibit, но чем обосновать — неясно. Переводчики оба слова переводят одинаково.
Проконсультировался с англоговорящим знакомым, тот подтвердил: смысл один, оттенки разные. Forbid более авторитарное, обычно имеется в виду, что кто-то персонально запрещает. А в случае организации или неопределённой группы лиц — скорее prohibit.

Если я правильно понимаю, раньше было 2 проприетарных платформы, работающих по сходим правилам: .net и java. Microsoft, чтобы "подтолкнуть развитие платформы и экосистемы", вывела .net в опенсорс; Oracle с той же целью сделала java платной. Очень интересно будет посмотреть в перспективе, чья стратегия к чему привела.

theCreature.Health = (theCreature.Health - damage).ButNotLess(than: 0).However().IfAndOnlyIf(theCreature is (Terribly)Lucky).Then(theCreature.Health + 2 * damage);

Fluent-подход отлично заходит, когда видишь одну строчку кода, и по ней понятно, что тут происходит. Например, создание маппинга в автомаппере:

configuration.CreateMap<OneThing, OtherThing>()
.ForMember(d => d.StatusId, ctx => ctx.MapFrom(s => s.Status))

(у меня тут правда большой вопрос к авторам, почему в CreateMap сначала Source, потом Destination, а в маппинге полей — наоборот. Ну да ладно, это к делу не относится)

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

configuration.CreateMap<OneThing, OtherThing>()
{
Status => StatusId,
Price => Cost,
Amount => Quantity,
Count => Number
};


Конечно, учитывая ограничения и синтаксис языка, это писалось бы, скорее так:
{ s => s.Price, d => d.Cost },. И тут, не зная контекста, сложнее понять что происходит, чем в случае fleunt-подхода. Но при многогратном повторении смотрится чище.
Если вызывать его на чём-то целом, да. Но когда у вас уже есть нечто разделённое, Separated(with: ", ")...

… как мне кажется, вызывает ступор и InvalidOperationException в мозгу.

SQL шел (идет?) по пути приближения к человеческому языку. Результат, как минимум, спорный, но и там не стали для объединения строк использовать ключевое слово SEPARATED BY. Назвать функцию STRING_AGG, думаю, тоже не было идеальным решением, но она хотя бы образована от AGGREGATE, не SEPARATE.
Join — это глагол, Separated — это прилагательное, первое — это действие, второе — это результат.

Даже если оба слова сделать активными (join, separate) или пассивными глаголами (joined, separated), суть не изменяется. Первый про объединение, второй про разделение, и действия эти направлены противоположно. Увидеть separated там, где ожидаешь увидеть joined, не ложится в прицнип наименьшего удивления.
Когда на входе — коллекция, а на выходе — строка, то это-таки «элементы, соединенные запятыми». Если же наоборот — то можно получить, допустим, список слов, разделенных [в исходной строке] пробелами.

Вот хоть убейте, Separate должен возвращать нечто разделенное (аналог string.Split). А у вас возвращается строка, склеенная из частей. Если бы я разбирался в АПИ незнакомой библиотеки, я искал бы concat, combine, join, glue, aggregate или что-то в этом роде. И когда, не найдя, я полез бы в справку и нашел там, что мне надо использовать separate, я подумал бы, что кто-то сошел с ума — или я, или автор библиотеки.
Особенно выразительно смотрится с пустым разделителем. chars.separate(""). Awesome

И ведь не GitUtils, а IRepository, ICommit, IBranch; не ExcelHelper, а ExcelDocument, ExcelSheet; не GoogleDocsService, а GoogleDocs.


С другой стороны, «Система контроля версий», а не «Коммиты». «Текстовый редактор», а не «Тексты». «Веб-браузер», а не «Веб-страницы».

«Кофемолка», «Холодильник», «Калькулятор», «Эскалатор», «Эвакуатор» — а не «Кофе», «Продукты», «Вычисления», «Ступеньки», «Беспредельщики»

Это еще и флотское приветствие. В Как я встретил вашу маму был персонаж, который со всеми здоровался только так.

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


Модификаторы доступа — это не более чем контракт. Если вы объявили член публичным, то потребители вашей библиотеки вправе рассчитывать, что этот член не будет слишком уж часто меняться. А вот если они через рефлексию доставали internal классы, и после обновления библиотеки все перестало работать — так они ССЗБ.


Еще, модификатор класса "перекрывает" модификаторы его членов. Например, если класс (вложенный) объявлен как private, у него вполне легально может быть public конструктор, но использовать его можно будет только в пределах внешнего класса (опять же, не беря в расчет рефлексию).

Information

Rating
Does not participate
Location
Саратов, Саратовская обл., Россия
Date of birth
Registered
Activity