Обновить
-3
0
mjr27 @mjr27

Пользователь

Отправить сообщение

Не-не-не.


Мы, даже с нашими достаточно небольшими потребностями, со вздохом сползли с aws на арендованное железо. Причина, если разобраться, простая: пока всё работает, все работает. Как только что-то не работает, концов не найдешь.


Сейчас опенсорс облака уже вышли на уровень, при котором кластер из арендованного baremetal хлама вполне жизнеспособен.

В качестве дисклаймера: я, на самом деле, django orm не люблю. Автокомплит в разных редакторах от плохого до омерзительного, паршивая расширяемость, куча магии плюс сильная заточка под OLTP, так что при малейших поползновениях в сторону аггрегации/аналитики удобней откатиться в сторону raw sql.


Но вашей проблемы я не прочувствовал :)


Если миграцией базы управляет django, то есть https://github.com/rapilabs/django-db-constraints, ну или на худой конец sql прямо в миграциях.
Если база управляется извне, то в чем проблема c unmanaged моделями-то?
Если же и так и так, то в проекте есть проблемы посерьезней, чем выбор орм =)

И согласен, и нет.


Django is a quite opinionated framework. Со временем просто привыкаешь не писать поперек линованной бумаги, и количество палок резко снижается.


А вот с legacy database это полный ад, да.

Про ОРМ — настолько феерический бред, что не могу не отметиться.


Все звучит красиво, пока твои потребности умещаются в select * from table. В реальности же… ну, давайте на примере DSL Django ORM (первое, что в голову пришло).


queryset  = User.objects.all()
if len(statuses) > 0:
  queryset = queryset.filter(status__in=statuses)
if last_comment:
  queryset = queryset.filter(user__post__comment__сreated_at__gt=last_comment)
if signed_in_from:
  queryset = queryset.filter(signed_in__gte=signed_in_from)
if signed_in_to:
  queryset = queryset.filter(signed_in__lte=signed_in_to)

cnt = queryset.count()
admins = queryset.filter(is_admin=True)
data = admins[:100]

Знакомая ситуация? Думаю, да. Неужели кому-то по кайфу каждый такой запрос обписывать этим всем ворохом " AND ".join(chunks) и прочей бесполезной белибердой????

if (...) { 
   return true;
} else {
   return false;
}

Во мне каждый раз что-то умирает

Я просто оставлю это здесь:


https://ru.aliexpress.com/item/XCY-2016-fanless-Mini-Desktop-PC-Core-i3-4010Y-Core-i5-4210Y-1-5GHZ-Dual-core/32747926428.html?spm=a2g0s.9042311.0.0.nIPnc5


Плюсы по сравнению с малиной:


  • i7, да ладно, пусть i3, по производительности ну прямо совсем не арм. Пересобрать ядро? не вопрос. Plex, транскодящий видео для тупого телевизора? запросто
  • нагрева выше чем 55C так и не добился
  • аппаратные ethernet, wifi, и sata. В мира *pi это как розовый единорог.
  • Wifi ловит дальше, чем на 5 метров.
  • возможность при желании поставить windows.

Сравнимо с малиной:


  • потребление. В конфигурации i5, ssd + hdd)-- 7 Вт в простое, 12 в пике
  • Герметичный безвентиляторный корпус

Минусы по сравнению с малиной:


  • цена
  • отсутствие GPIO

Взял такого зверя в конфигурации i5 + 4G RAM + 30G mSATA SSD, докинул старый ноутбучный винт, поставил минимальную убунту. Внешний ip, Nginx, сертификаты от letsencrypt, radarr, качалка, Plex, файлопомойка/owncloud, облако. Занято 350мб оперы, 8gb диска, loadavg стремится к нулю.


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

Считать так считать ))


# v1
from operator import is_
from itertools import filterfalse
from functools import partial

is_none = partial(is_, None)
filter_none = partial(filterfalse, is_none) 
filtered = filter_none(seq)
filtered2 = filter_none(seq2)
all_filtered = filter_none(chain(seq, seq2))

# v2
filtered = (x for x in seq if x is not None)
filtered2 = (x for x in seq2 if x is not None)
all_filtered = (y for x in (seq, seq2) for y in x if y is not None)

# v3
from itertools import chain

filter_none = lambda seq: (x for x in seq if x is not None)
filtered = filter_none(seq)
filtered2 = filter_none(seq2)
all_filtered1 = filter_none(chain(seq, seq2))

# v4 -- для полных лентяев типа меня
def filter_none(seq):
  return (x for x in seq if x is not None)

filtered = filter_none(seq)
filtered2 = filter_none(seq2)
all_filtered2 =  filter_none(seq + seq2)

Какой вариант вызывает минимум WTF в минуту?

Дык все равно filter_none = lambda seq: (x for x in seq if x is not None) строчки на три короче и во сколько-то раз читаемей получается


Опять же, повторюсь, посыл понятен. Просто на таких масштабах пример выходит сомнительный. В сложных случаях тоже зачастую обычный for ... in ... получается куда более… readable


Очень уж в python LINQ-style filtered = seq.where(r=> r is not None) на борту на хватает.


P.S: спасибо за controlcenter :)

Буквально пара придирок по примерам… Ну или мыслей вслух, кому как нравится.


  1. @post_processing(list)
    Вообще правила хорошего тона очень уж не рекомендуют декораторам менять тип возвращаемого значения.


  2. List comprehansion VS functools

У list comprehension есть одна потрясающая особенность: они не прерывают контекст чтения. Одним взглядом сразу становится понятно, что здесь происходит и какой тип у нас на выходе.


Вы пытаететесь утвержать, что


filtered = [x for x in seq if x is not None]

это "куча ненужной фигни" по сравнению с


from operator import is_
from itertools import filterfalse
from functools import partial

is_none = partial(is_, None)
filter_none = partial(filterfalse, is_none) 
filtered = filter_none(seq)

Серьезно что ли? Посыл понятен, но пример-то свидетельствует о совершенно противоположном

Когда я уходил, тимлид (точнее, Ведущий Специалист) что-то начинал разбираться с SVN. Но это уже без меня было.

— Мужики, я работаю в oic/lib/
— Хорошо


....


— Мужики, никто oic/lib/bibl_stroki.c не трогал последние два дня?
— Я!
— И я!
— Мля!


Как-то так.

Но тем не менее, в том коллективе, где я был молодым специалистом, было принято именно так. Видимо, хипстеры и тогда были.


С ужасом представляю, что они использовали в 97

Когда-то, на рубеже веков, мы так и работали — rsync на машины остальных разрабов.


Читал и ностальгировал.

Мне казалось, первое апреля далеко.


Если по пунктам:


  1. А чем собственно плоха система "1 задача — 1 ветка"? Проблема с merge conflicts в случае единой ветки разработки никуда не исчезает же, просто тонким слоем размазывается по всей истории коммитов. Ну и плюс правило "последний коммит в фичаветке — это мердж из мастера" это уже давно хороший тон.
  2. Код ревью каждого отдельного коммита — это то, с чем справится pyflakes / статический анализатор. Без общего контекста задачи ревьюер на большее не способен.
  3. Точечный перенос коммитов из ветки develop в master не работает. Нарушение хронологии приводит к тому, что ответственный за это будет 40 часов в неделю пытаться разрулить какие-то конфликты. Оно ему надо?
  4. if(FEATURE_ENABLED) работает только в вакууме. Пример — практически любое изменение структуры БД.
  5. Один поломанный коммит ленивого разраба внезапно убивает тесты / CI для всех последующих. За день до релиза вероятность этого увеличивается до 100%.
  6. И наконец, где при такой схеме бедному разработчику хранить коммиты с шикарными описаниями "test" и "dummy", особенно если он работает из более чем одного места?

В качестве бонуса: могу ошибаться, но изменившаяся индентация вокруг if(FEATURE_ENABLED) делает бесполезным git blame.


P.S: CVS в 2017? Не-не-не, Дэвид Блейн

Рискну не согласиться. В подавляющем большинстве случаев (если только это не очередной вордпресс), зафиксировать окружение не только можно, но и необходимо.


А в нынешний контейнерный век это еще и удобно.

В тайпскрипте? От navigate<IItemParams>(route, <any>anyObject)? Никто не помешает, ясен перец. Но в первом же кодревью за это накажут.


В каком вам удобно, в таком и описывайте.
Отличный ответ. Лично мне ни в каком не удобно.

Честно, не понимаю о чем разговор. Вас устраивает — пользуйтесь на здоровье. Меня нет, по длинному списку озвученных выше причин. От продолжения спора для меня ничего не изменится, так что удаляюсь.

кто помешает мне вызывать

navigate<T>(route, anyObject), парсер лох


Там, где вы описываете роут, очевидно.

А где я описываю роут, например, в случае lazyLoad? В каком из двух файлов?

как его выразить в рамках системы типов ТС
да хоть public navigate<T>(route: string, params: T, options: RequestOptions>. Довести до абсолюта public navigate<T>(params: T, options: RequestOptions> по очевидным причинам не получится.

У вас есть ф-я, которая генерит роуты, в чем проблема проверять роут в ней?

Два контраргумента:


  1. Зачем бить "туда" и "обратно" на два разных куска, если это всё можно задать 1 раз декларативно?
  2. А где должна быть эта функция? Вижу 4 варианта:
    • Отправляющий компонент (где создается URL): привет, копипаста; структурно неверно
    • Принимающий компонент (куда ведет URL): как достучаться? что если компонент по нескольким схемам URL доступен? Что с использованием в других проектах?
    • функция: привет от DI и тестов
    • сервис/injectable: ну вроде сильных контраргументов нет

А теперь вопрос — зачем мне сервис маршрутизации, когда у меня уже есть сервис маршрутизации?


UPD: изменил, парсер съел угловые скобки

Вообще не понял аргумента. Строку нельзя превратить в типизированную структуру? JSON.parse негодует.


RouterTypeService.register("int", /\d+/, (val) => typeof val === "number", parseInt, x=>x.toString());
RouterTypeService.register("uuid", /[a-f0-9]{32}/, parseUuid, x=>x.toString());
{path: "/category-{id:int}{aux:/item-{itemId:uuid}", name: 'test'}


this.router.navigate('test, {id: 10, aux: {itemId: 'aa...00'}});


Кто мешает

Вообще не понял вопроса, если честно.


(new UrlBuilderService()).makeCategoryUrl(id, itemId)?


А чем вас, собственно, не устраивает /category;id={id}? тем, что ";" вместо "-"?

Если коротко — да хотя бы тем, что я хочу именно так а не иначе. Достаточная причина? Система маршрутизации, под которую приходится подстраиваться, веет 2001м годом а-ля category.php?id[]=12&id[]=13


Конкретно в текущем проекте у нас полу-статический контентный сайт с давней историей и кучей трафика по прямым ссылкам и букмаркам (да, такое еще существует). И этот сайт по нажатию кнопки "сделать п… то" превращается в современное spa.


И я хочу чтобы у ангулара были точно такие же ссылки, какие были уже второй десяток лет.


Я много фреймворков перевидал, но пока что это первый в котором, когда настолько примитивная функция сделана настолько "для галочки".

редко нужного функционала

Если навигация это "редко используемый функционал", то я даже не знаю, что такое часто используемый.


canActivate гварды

К сожалению, не панацея. Я хочу проверку ссылки в момент ее генерации (о проверке в compile-time я уже не говорю).


Или хоть что-либо отличное от каши any[] в [routerLink]


роут foo/:id при несуществующем в базе айдишнике столь же невалиден, сколь и роут с неправильным синтаксисом

Сильное утверждение. Навскидку


https://twitter.com/hashtag/++++++++++
https://twitter.com/hashtag/llllllllll3llllllll


Ваш «общий случай» не учитывает синтаксиса аргументов и именованных аутлетов

На то, что структура URL для именованных аутлетов прибита девятидюймовыми гвоздями, я предпочел не жаловаться, в Router и без этого проблем хватает.


Данный способ как раз расширяем (e.g "/category-{id}{aux:/item-{id}}"), в отличии от встроенного "вот вам url.split('/'), радуйтесь"


P.S: Вообще, думаю, спор на самом деле ни о чем. Вам стандартной схемы хватает, мне однозначно нет. Так что буду плакаться, колоться, и делать велосипед. Спасибо за интересную дискуссию.


/off

Информация

В рейтинге
Не участвует
Откуда
Украина
Дата рождения
Зарегистрирован
Активность