Pull to refresh
4
0
Алексей @LastDragon

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

Send message
Там даже с обычным phpdoc проблемы, в IDE всё красное

Для Laravel-а практически обязателен https://github.com/barryvdh/laravel-ide-helper, который решает почти все проблемы с автокоплитом в PHPStorm-е :) (быстрее бы еще фабрики смержили...)

Спасибо. Правда судя по беглому взгляду в Windows 10 оно просто так не заведется (hosts как минимум обновлять оно, похоже, не умеет).

А что не так с вагрантом? Для разработки (под виндой по крайней мере) очень удобно — буквально за день сделал шаблон, и постепенно перетащил все проекты в отдельные виртуалки, при этом у каждой отдельный домен (на основе имени из composer/package.json). Как это сделать на докере сходу не нашел.

Так нету этой необходимости, php storm давным-давно умеет вот так:


image


vscode сразу из коробки так не умеет, но вон там https://github.com/microsoft/vscode/issues/16221 вроде есть плагин.


Для каких-нибудь gd функций оно возможно актуально (даже не вспомню где еще есть по 10 параметров?), но для обычного кода оно не нужно, а если нужно, то это скорее повод задуматься о том что пора что-то отрефакторить. Поэтому, кмк, недостатков гораздо больше чем достоинств (подробнее ниже написал https://habr.com/ru/post/511266/#comment_22276484)

Я профессионально программирую на PHP с 2004 года, то есть вот уже 16 лет на момент написания этой статьи, и продолжаю это делать каждый день

А я где-то с 2006-7, и не согласен — в целом всё радует (эх, дженерики бы еще...), за исключением именованных параметров:


  • Сама по себе проблема больше выдуманная, в нормальным коде функций где больше 4-5 параметров мало, да и IDE давным-давно умеют выводить названия параметров.
  • Названия теперь часть публичного API, а значит чтобы исправить опечатку придется выпускать новую мажорную версию, но
  • Проверка имен при наследовании есть только в рантайме — т.е. при обновлении зависимостей теперь гораздо больше работы ибо придется так же проверять и синхронизировать имена.
  • Ассоциативные массивы при распаковке будут использованы как именованные параметры, что может сломать существующий код
  • Привести код к единому стилю больше невозможно и у нас всегда будет каша из argName, argname и arg_name. Два последних варианта использует сам PHP, а т.к. теперь они часть публичного API то исправлены могут быть только в PHP 9 (т.е. в реальности надежд на согласованное std api всё меньше и меньше).
Можно конечно не делать ничего, но сама по себе фича очень удобная.

Это "удобная" фича сделала имена параметров частью публичного апи, теперь чтобы исправить опечатку в названии параметра нужно будет выпустить новую мажорную версию. Вариант с array_fill(50, default, 0); был, кмк, лучше.

Если вам нужно перерендерить дочерние компоненты, а при этом их входные данные не поменялись — вы делаете что-то не по канонам Angular

Это обычный очень распространенный кейс:


<страница которая с сервера объект с дочерними элементам>
    <заголовок, который используется на многих других страницах и вычисляет статус по дочерними элементам />

    <дочерний элемент №1>
        <редактировать />
        <удалить />
    </дочерний элемент №1>

    <дочерний элемент №2>
        <редактировать />
        <удалить />
    </дочерний элемент №2>
</страница которая с сервера объект с дочерними элементам>

Когда дочерний элемент удаляет/изменят сам себя надо
1) уведомить страницу
2) перерисовать всё компоненты


Когда объект действительно сложный гораздо проще было бы сказать "перерендерь меня полностью", но вместо этого приходится создавать глубокую копию*, ну или пробрасывать refresh$, но это как раз (очередной) костыль для решения проблемы, которую должен решать фреймфорк. Более того, refresh$, в отличии от клона, может не работать когда где-то внутри есть сторонние компоненты, который о нем не знают.


* — еще можно реализовать deep check (обычно оверкил), или фейковый @Input (ничем не лучше refresh$).


Ну а программное изменение инпутов компонента — это проделки Императора, смотрите совет №5 :)

Далеко не все можно написать декларативно. Ну а если вы не учитываете что ваш компонент может быть использовать программно, то вы сами роете себе яму чтобы попасть в неё в будущем.


См: https://github.com/angular/angular/issues/22567

А не будет ли проблем с отловом ошибок если прописали не тот интерфейс в фабрике или месте инжектирования

Будет, и еще какая, но это скорее проблема @Inject(), который не может проверить типы предоставленного значения и того что нужно.


const TT = new InjectionToken<number>("ddd");

@Component({
  providers: [
    {
      provide: TT,
      useValue: {}
    }
  ]
})
export class AppComponent {
  constructor(@Inject(TT) t: string) {
    console.log(t); 
  }
}

Как видим должен быть number, предоставили {}, а сам компонент ждет string — и ни одной ошибки. Поэтому @Inject() скорее антипатерн и вместо него почти всегда лучше использовать абстракный класс.


1) инжектируя работу роут как параметр ...

Для случая описанного в статье так-то есть https://angular.io/api/router/Resolve, который отложит рендеринг компонента до момента резолва всех резолверов (= пользователь не будет смотреть в пустую страницу) тем самым позволит выбросить *ngIf + можно вывести ошибку и опционально перенаправить пользователя на другую страницу если резолвинг провалился (= сервер вернул 404 например)


Правда с типами тут тоже не все идеально ибо data: Observable<{[name: string]: any;}>.

прийдёт с опытом

На самом деле чем больше опыта, тем больше осознание что DI тут какой-то ущербный :( В статье например не сказано что все зависимости по сути синглтоны (пусть и в пределах модуля), даже фабрика и та создает синглтоны (кмк несколько неочевидно), хотя это по-моему упоминается в документации. Если синглтон не нужен приходиться явно добавлять сервис в компонент и писать @Self() — очень раздражает и легко ошибиться (особенно когда компоненты наследуются). Надеюсь что когда-нибудь они добавят providedIn: 'component' или что-то подобное ...


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

Просто пишите код так, как задумано принципами фреймворка, и вы не попадете в неприятности с OnPush

Ровно до тех пор не заходите уведомить другие дочерние компоненты родительского компонента о том что "надо бы перерендерится". Проблема в том что при onpush компонент обновиться только если изменятся @Input() (см ниже) или если он сам вызовет markForCheck(), способа сказать angular-у "перерендерь меня полностью со всеми подкомпонентами" до сих пор не существует :( Самый простой и очевидный способ решить проблему через @Input(), но, как указано в статье, надо помнить о том что нельзя просто взять изменить свойство, надо создавать новый объект, в некоторых случаях это неудобно.


Кроме этого в статье упущен еще один важный момент: если вы изменяете @Input() программно, вы обязаны вызвать markForCheck()иначе angular не поймет что надо обновить компонент. На практике это значит что если вы хотите чтобы ваш компонент работал во всех случаях, то в каждый сеттер каждого @Input() надо пихать проверку действительно ли значение изменилось и вызывать markForCheck() когда это произошло (ну или проверять в ngDoCheck()).

Самый полезный, по моему мнению, способ использования фабрики в tree shakable сервисах выглядит так:

Пример кмк не очень удачный (как и плюсы), если нужен app-wide синглтон, то есть рекомендованный providedIn: 'root'.


Это работает точно так же, как и следующий пример:@NgModule({providers: [SomeService]})

Вот только в этом случае tree shakable невозможен (из статьи это немного неочевидно, да и вообще оно deprecated). И работает кстати тоже не совсем так как ожидаешь, при @Injectable({providedIn: SomeModule}) SomeModule не сможет использовать этот сервис внутри себя из-за cyclic dependency))) Приходится создавать отдельный пустой модуль для сервисов и импортировать его в SomeModule. Неудобно :(


@Injectable({providedIn: SomeModule})

И тут мы еще получаем одну неочевидную проблему с приоритетом (кто последний тот и папа), что затрудняет переопределение провайдеров определенных в импортируемых модулях (иногда оно нужно).


Поэтому в 99% providedIn: 'root' предпочтительнее.

Это очень мощный инструмент для создания гибких и переиспользуемых компонентов.

Всё-таки правильнее будет сказать "ущербный" или, если более политкорректно, "подходящий для совсем простых случаев", самый большой косяк в нем это что он наследует контекст того места где определен (т.е. AppComponent), что например не позволяет сделать вот так:


// app.html
<my-select>
    <option>...</option>
</my-select>

// my-select.html
<select>
   <ng-content><ng-content>
</select>

Прикол тут в том что визуально все как бы нормально, но на самом деле если посмотреть внутрь angular-а то можно заметить что optionы регистрируются вselecte, но тут этого не происходит по очевидной причине (другой контекст) и рождаются всякие баги https://github.com/angular/angular/issues/26273 (впрочем <select> сам по себе тоже довольно сильно баганый...).


А еще нет никакого способа задать содержимое по умолчанию, что довольно часто нужно (см https://github.com/angular/angular/issues/12530).


Поэтому по сути годится только для иконок :(

Я решил указать экспортный, потому что предельная сумма до постановки на учет валютного контроля по такому типу контракта выше остальных типов (до 6 млн ₽ вы можете быть спокойны).

Зарегистрировать можно и раньше не дожидаясь 3/6млн, единственное на что влияет регистрация это на коммисию при переносе контракта в другой банк, а вот если не сделать это вовремя то можно попасть на штраф (40к вроде был).


Ну и еще не все банки требуют дополнительных сумм в CoS из пункта (2). Модулю например достаточно только суммы.

Оно скорее аналог JsonSerializable

Наверное, но кмк в этом случае было бы лучше писать не 1 + 2 * 2 = 6 как сейчас, а 1 + 2 = 3 * 2 = 6

Последний раз инженерный калькулятор у меня был лет 20 назад наверное, поэтому не помню было ли оно так, ну а сейчас весьма неожиданно что контрол который выглядит как обычная кнопка на самом деле чекбокс… Тем более в прошлой версии корень был отдельной кнопкой без всякого переключения. Мне кажется лучше бы они сделали если не чекбокс, то хотя бы селект, но лучше конечно просто еще один ряд кнопок.

Нашел :) Фиг догадаешься… для тех кто тоже ищет он под "2nd"

Т.е. его надо каждый раз переключать в обычный режим?

В "обычном" режиме у него весьма забавный приоритет операторов (1 + 2 *2 = 6), а в "инженерном", где он нормальный, больше нет квадратного корня. Так что куда не переключайся он всё равно будет унылым :(

@Optional() @Self() public control: NgControl

Oно не работает c NG_VALIDATORS...

Делиться смысла нет, каждая налоговая может трактовать всё по своему и на мнение другой налоговой им побоку, так что придется самому спрашивать :)

Information

Rating
Does not participate
Location
Россия
Registered
Activity