Wysyłanie emaili - dobre praktyki

Odpowiedz Nowy wątek
2018-11-11 17:50
0

Ostatnio znalazłem taki kod. Nie rozumiem kilku rzeczy:
1) Po co jest tworzony interfejs IEmailConfiguration? Gdyby klasa EmailConfiguration sama sobie wczytywała wartości z jakiegoś źródła, to miałoby to sens, ale przecież ona te wartości otrzymuje "za darmo" - tzn. nic nie musi robić, aby je wczytać. I czy takie pchanie klasy konfiguracji do warstwy aplikacji jest w porządku? Jak dla mnie, powinno się jej używać jedynie przy rejestrowaniu zależności do skonfigurowania jakiegoś EmailClienta.
2) Dlaczego SmtpClient nie jest zarejestrowany w kontenerze i wstrzykiwany, tylko tworzony "dynamicznie" za pomocą using? Ma to związek z wydajnością? Czy wywołanie Dispose nie może poczekać? Jeśli użyjemy AddScoped, to przecież taDispose zostanie wywołana tuż po zakończeniu przetwarzania żądania.
3) Co w ogóle sądzicie o tym kodzie?

Pozostało 580 znaków

2018-11-11 17:59
0

1) sam nie wiem, interfejs do klasy konifugracyjnej, która przechowuje tylko proste właściwości to jak dla mnie jakiś WTF
A co do samego istnienia klasy to jakoś musisz skonfigurować ten EmailService, więc nie widze tutaj problemu. Co byś proponował zamiast tego?

2) a jaka byłaby zaleta gdyby był wstrzykiwany?

Pozostało 580 znaków

2018-11-11 18:00
0

@some_ONE: Nie trzeba by było go konfigurować za każdym razem, gdy jest potrzebny w kodzie. Ogólnie to po raz kolejny widzę takie podejście, ale nie wiem o co z tym chodzi ;(

edytowany 1x, ostatnio: nobody01, 2018-11-11 18:03

Pozostało 580 znaków

2018-11-11 18:10
0

Czyli jak by to miało wyglądać zamiast klasy konfiguracyjnej?

EDIT: W ogóle twoja odpowiedź dotyczy punktu 1 czy 2?

edytowany 1x, ostatnio: some_ONE, 2018-11-11 18:13

Pozostało 580 znaków

2018-11-11 18:12
0

Zamiast wstrzykiwać obiekt klasy konfiguracji wstrzykiwałoby się SmtpClienta, który wcześniej zostałby skonfigurowany w Startupie czy gdzieś indziej przy użyciu właśnie tego obiektu konfiguracji (chociaż przy takim podejściu istnienie EmailConfiguration chyba nie ma sensu, bo jest używana tylko w jednym miejscu).

edytowany 1x, ostatnio: nobody01, 2018-11-11 18:14

Pozostało 580 znaków

2018-11-13 18:35
2
nobody01 napisał(a):

Ostatnio znalazłem taki kod. Nie rozumiem kilku rzeczy:
1) Po co jest tworzony interfejs IEmailConfiguration?

No przecież jest napisane: Since we are good programmers we will use an interface too!. :P Osobiście przestałbym czytać po tym zdaniu, tak na wszelki wypadek.

Ogólnie interfejs do konfiguracji to nie jest zły pomysł, tylko jeśli chcemy iść tą drogą, to tam powinny być metody , a nie właściwości z publicznymi setterami. Publiczny setter w interfejsie to jakiś absurd.
Ja bym zrobił raczej interfejs IConfigurationProvider, który by mi zwracał EmailConfiguration jakąś metodą. Ale tylko gdybym musiał, bo tak ogólnie, to konfigurowalny w taki sposób serwis do obsługi emailów nie ma za bardzo dla mnie sensu.

I czy takie pchanie klasy konfiguracji do warstwy aplikacji jest w porządku? Jak dla mnie, powinno się jej używać jedynie przy rejestrowaniu zależności do skonfigurowania jakiegoś EmailClienta.

No właśnie nie. Taki interfejs daje tylko to, że można jednostkowo przetestować kod EmailSerwisu, ale testowanie takiej klasy jednostkowo nie ma przecież żadnego sensu.

2) Dlaczego SmtpClient nie jest zarejestrowany w kontenerze i wstrzykiwany, tylko tworzony "dynamicznie" za pomocą using?

Wtedy byś wypychał szczegóły implementacji do warstwy aplikacji. Jest to w porządku? ;)
Osobiście bym tak nie robił. Żadnego zysku z tego nie ma, to jakiś szczegół implementacji EmailService. Inne klasy powinny po prostu korzystać z tej klasy, która konfiguruje bibliotekę do obsługi emaili na swoje potrzeby.

Ma to związek z wydajnością? Czy wywołanie Dispose nie może poczekać? Jeśli użyjemy AddScoped, to przecież taDispose zostanie wywołana tuż po zakończeniu przetwarzania żądania.

A jeśli poleci wyjątek, to też zostanie dispose zawołane?


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2018-11-13 19:03
0

Ale mogę wypychać szczegóły implementacji, jeśli korzystam z biblioteki, której prawdopodobieństwo zamiany na inną jest bliskie zeru? Np. jakiś ORM albo Identity (oczywiście przy założeniu, że z Identity korzysta jakaś SecurityService i tylko ona, bo pozostałe klasy korzystają właśnie z tej SecurityService)?

Co do tego wywoływania Dispose po rzuceniu wyjątku, to nie wiem, ale zgaduję, że nie. ;) Tak z ciekawości: co zrobić, jeśli poleci wyjątek, a w kontenerze są zarejestrowane klasy kontekstu/sesji ORMa? Jak wtedy wywołać Dispose?

Pokaż pozostałe 9 komentarzy
@some_ONE: Layer to taki żarcik, ale według mnie podciąganie logowania/rejestracji pod security to taki overkill :P już prędzej bym tam wrzucił jakieś customowe rozwiązania związane z security lub krypto-podobne rzeczy, a nie :) - WeiXiao 2018-11-13 19:34
Może jakąś warstwę dostępu do aplikacji na poziomie middleware nazwałbym SecurityMiddleware :> - WeiXiao 2018-11-13 19:36
To może słabo znam sie na twoich żartach :P - some_ONE 2018-11-13 19:40
@some_ONE: Zawsze można dostosować się do tego, jak nazywają to inii :P Google: c# security service c# security provider c# authentication service c# authentication manager - WeiXiao 2018-11-13 19:44
Albo UserManager, w asp.net identity chyba tak to się nazywało - some_ONE 2018-11-13 21:09

Pozostało 580 znaków

2018-11-16 00:24
2
nobody01 napisał(a):

Ale mogę wypychać szczegóły implementacji, jeśli korzystam z biblioteki, której prawdopodobieństwo zamiany na inną jest bliskie zeru? Np. jakiś ORM albo Identity (oczywiście przy założeniu, że z Identity korzysta jakaś SecurityService i tylko ona, bo pozostałe klasy korzystają właśnie z tej SecurityService)?

Możesz, ja Ci przecież nie zabronię. Ale moim zdaniem nie powinno się tak robić. Ja między warstwami przekazuję tylko typy zdefiniowane w aplikacji, nie z zewnętrznych bibliotek.

Tak z ciekawości: co zrobić, jeśli poleci wyjątek, a w kontenerze są zarejestrowane klasy kontekstu/sesji ORMa? Jak wtedy wywołać Dispose?

Ja rejestruję w IoC interceptor, który opakowuje wszystkie klasy operujące na DB i tam w razie wyjątku robię rollback transakcji i sprzątam ORMa.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2018-11-16 16:40
0
somekind napisał(a):

Możesz, ja Ci przecież nie zabronię. Ale moim zdaniem nie powinno się tak robić. Ja między warstwami przekazuję tylko typy zdefiniowane w aplikacji, nie z zewnętrznych bibliotek.

Oczywiście masz rację. Chodziło mi o to, że niektóre biblioteki zachęcają do rejestrowania ich w IoC, aby można ich było łatwo używać, bez stosowania using i wywoływania "ręcznie" konstruktorów z dużymi liczbami argumentów, i nawet jeśli okrywamy taką bibliotekę abstrakcją, to zarejestrowanie jej w IoC ułatwia życie.

Ja rejestruję w IoC interceptor, który opakowuje wszystkie klasy operujące na DB i tam w razie wyjątku robię rollback transakcji i sprzątam ORMa.

Na to to ja chyba jestem za głupi. Byłaby szansa na jakiś pseudokod w wolnej chwili? ;)

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0