Nazwa dla lekkich i ciężkich operacji

0
TomRiddle napisał(a):

Napisałem to w poście wyżej, bo korzysta z IO i z socketów.

Tu nie chodzi o microbenchmark, tylko o działanie aplikacji. Ile razy wywołujesz tę funkcję i jak? Z każdym żądaniem HTTP? Co sekundę? Na wątku w tle? Na wątku UI? To, że unikniesz kilku cykli procesora w tym miejscu nie oznacza, że trzymanie hashmapy ma jakikolwiek sens.

Idealnie by było gdyby nazwa była wymowna i nie musiałbyś szukać nigdzie indziej informacji o tym.

Jeżeli piszesz cache, to napisz go poprawnie i nazwij metodę isYadaYadaCached. Jeżeli zaczniesz wymyślać coś innego, to tylko spowodujesz pytania.

Nie mierzyłem, ale mam mózg i wiem bez sprawdzania że implementacja oparta na mapie jest szybsza niż fetchowanie czegoś z IO/socket'ów.

Ponownie: GC? Czy to jest na wątku w tle? Czy na wątku UI? Czy to jest ścieżka krytyczna? Kto wypełnia słownik? Kto go czyści? Jak często?

Nie jest pomijalna.

O, to cenna informacja. To dlaczego nie jest pomijalna? Czy to jest ścieżka krytyczna? Co jeżeli ktoś za tydzień postanowi usunąć sprawdzanie w tej hashmapie, co się wywali?

Nie mogę pozbyć się całkowicie hash'mapy bo ten szybki pre-test nie jest jej jedynym zadaniem, jest istotnym elementem innej części aplikacji (głównie UI).

Czyli masz jakiś stan używany w innych miejscach aplikacji? Czy da się tego uniknąć? Czy da się te dwa słowniki rozdzielić? Ponownie: co jeżeli ktoś usunie sprawdzanie przy pomocy hashmapy, co się zepsuje?

Jeśli ktoś przebuduję część aplikacji, to faktycznie implementację fast/slow check'a trzeba będzie zmienić. Teraz to jest zupełnie nie potrzebne.

No i ponownie, skąd wiadomo, że trzeba będzie to zmienić? Jeżeli teraz masz jakieś argumenty na poparcie swojej implementacji, to dlaczego nie udokumentować ich?

Właśnie dokładnie dlatego chcę poświęcić czas i dobrze nazwać tę funkcję - żeby dokładnie mówiła czym jest i co robi.

Ponownie podtrzymuję swoją opinię, że nazwą nie przekażesz tego, co przekażesz dobrą dokumentacją.

A jakie to ma w ogóle znaczenie? Nawet gdyby to był 1%, to i tak warto zrobić pre-test, bo a nuż się okaże że pre-test dał true i wykonywanie ciężkiej operacji nie ma sensu.

Ma znaczenie, bo hashmapa zajmuje miejsce w pamięci, więc obciąża GC i serwer. Ponadto w słowniku mogą być niepoprawne dane i tym nieznaczącym kawałkiem kodu wprowadzisz buga.

"około" znaczy 70-90%. Mniej więcej 8/10 case'ów - widzę po reakcji programu że trochę krócej mieli.

Czy da się to zapisać jako test jednostkowy/wydajnościowy/jakikolwiek? Za tydzień ktoś będzie chciał to zmienić i nie będzie musiał myśleć, czy używanie dodatkowej ścieżki ma sens.

BO WYCIĄGANIE Z MAPY PO KLUCZU JEST JEDNĄ SZYBSZYCH OPERACJI W JAVIE. Szybsze chyba może być tylko dostęp do array'a po indexie.

Takie stwierdzenie jest bardzo ryzykowne, bo implementacji map jest mnóstwo, a nawet przy używaniu hashmap nie jest to oczywiste (chociażby kwestie wyliczania hasha dla stringa lub obiektu). No i znowu: co z GC?

No nie. Teraz to muszę pisać w assemblerze, skoro mapa jest taka nieoptymalna :/

Jeżeli usuniesz mapę, to nie będziesz musiał nic pisać.

Chwila... próbujesz mi teraz powiedzieć że moja implementacja ma milion dziur? Czy twierdzisz że korzystanie z szybki pre-optymalizacji z możliwymi false-negative'ami jest niebezpieczne?

Chcę się upewnić, że jeżeli w hashmapie będzie wartość, to będzie ona poprawna. Ponadto po Twoim opisie wyżej odnoszę wrażenie, że optymalizujesz tylko ścieżkę pozytywną (hashmapa zwraca true), a co z negatywną? Dlaczego wartości false nie trzymasz w hashmapie? Czy to efekt przeoczenia, czy ja źle zrozumiałem Twój kod, czy może wartość false w ogóle nie występuje?

No to na prawdę nie wiem czemu twierdzisz że nie warto poświęcać czasu na dobre nazwy.

Nigdzie tak nie powiedziałem.

Mój tok myślenia można byłoby uprościć do:

  • Jeżeli piszesz cache, to napisz go poprawnie (albo użyj gotowca z Guavy czy czegoś) i nazwij metodę blablaCached. Najlepiej też umieść w dokumentacji jakieś uzasadnienie, dlaczego postanowiłeś go użyć.
  • Jeżeli nie piszesz cache'a per se, to napisz w dokumentacji przesłanki do użycia tej szybkiej ścieżki. Nawet proste stwierdzenie w stylu fast check to avoid I/O operations as this seems to speed up things też jest wartościowe, inny programista zrozumie, że niespecjalnie cokolwiek mierzyłeś i kierowałeś się intuicją, więc jak trzeba będzie to zmieniać, to nie będzie godziny myślenia „a może to zepsuje rzeczy gdzieś indziej / a może muszę robić benchmarki, czy to się wyrobi na produkcji”. Możesz też nazwać funkcję checkYadaYadaFastWithoutIOWithFalseNegativesjeżeli tak bardzo chcesz.
0

niech shallowCheck zwraca strukture shallowResult w ktorej bedziesz miec

ShallowResult {
  bool FalsePositive;
  bool FalseNegative;
}

I wtedy zmieniasz odpowiednio warunek i wynik operacji shallowCheck mowi Ci o tym ze moze to byc FalsePositive czy FalseNegative

PS nie wiem dokladnie o co chodzi, nie czytalem calego tematu, jedynie odnosze sie stwierdzenia o ktorym napisales o moim pomysle ;)

0
fasadin napisał(a):

niech shallowCheck zwraca strukture shallowResult w ktorej bedziesz miec

ShallowResult {
  bool FalsePositive;
  bool FalseNegative;
}

I wtedy zmieniasz odpowiednio warunek i wynik operacji shallowCheck mowi Ci o tym ze moze to byc FalsePositive czy FalseNegative

Nie chcę nic refactorować :| Warunek fast(a) && slow(a) jest ok! Chcę tylko lepszą nazwę.

0

Chcę tylko lepszą nazwę

no jak widzisz, nie mozesz ogarnac lepszej nazwy bo:

  1. Chcesz opisac to co funkcja robi
  2. Chcesz opisac to co funkcja zwraca

i to w samej nazwie funkcji

Przeciez to nie moze zadzialac tak by bylo czytelne i zrozumiale

ShallowCopyThatIsFastAndReturnsFalsePositiveOrNegativeSoYouCannotBeSure(a)
DeepCopyThatIsSlowAndReturnsBooleanBecauseResultIsGuaranteed(a)

to jest mniej wiecej co chcesz osiagnac poprzez nazwy (powiedzmy... zamiast shallowcopy czy deepCopy mozesz uzyc co tma chcesz)

0
fasadin napisał(a):

Chcę tylko lepszą nazwę

no jak widzisz, nie mozesz ogarnac lepszej nazwy bo:

  1. Chcesz opisac to co funkcja robi
  2. Chcesz opisac to co funkcja zwraca

i to w samej nazwie funkcji

Przeciez to nie moze zadzialac tak by bylo czytelne i zrozumiale

ShallowCopyThatIsFastAndReturnsFalsePositiveOrNegativeSoYouCannotBeSure(a)
DeepCopyThatIsSlowAndReturnsBooleanBecauseResultIsGuaranteed(a)

to jest mniej wiecej co chcesz osiagnac poprzez nazwy (powiedzmy... zamiast shallowcopy czy deepCopy mozesz uzyc co tma chcesz)

W sumie to nie, chcę zawrzeć w nazwie cechy algorytmu:

  • optymalny/wymagający
  • optymistyczny/pewny

Jest dużo takich metod które mają takie nazwy.

0
Afish napisał(a):

Mój tok myślenia można byłoby uprościć do:

  • Jeżeli nie piszesz cache'a per se, to napisz w dokumentacji przesłanki do użycia tej szybkiej ścieżki. Nawet proste stwierdzenie w stylu fast check to avoid I/O operations as this seems to speed up things też jest wartościowe, inny programista zrozumie, że niespecjalnie cokolwiek mierzyłeś i kierowałeś się intuicją, więc jak trzeba będzie to zmieniać, to nie będzie godziny myślenia „a może to zepsuje rzeczy gdzieś indziej / a może muszę robić benchmarki, czy to się wyrobi na produkcji”.

Całe te Twoje dwa ogromne posty nie specjalnie niosą jakąś wartość dla mnie, ponieważ:

  • po pierwsze, zadając pytanie nie szukałem pomocy w implementacji/optymalizacji, dlatego że...
  • po drugie, to czy funkcja się wykona 1ms czy 100ms z biznesowego punktu widzenia jest to żadna różnica
  • po trzecie, mam inne priorytety co do pracy nad aplikacją, niż performance'owe optymalizacje
  • po czwarte, całkowicie odbiegłeś od tematu (czyli dobrej nazwy) w stronę hiper-optymalizacji
  • po piąte, nie specjalnie chce mi się pokazywać dlatego akurat taką strategię wybrałem, dlatego że...
  • po szóste, gdybyś zobaczył ten kod, to sam sobie odpowiedziałbyś na 80% pytań i sądzę że doszlibyśmy do podobnego wniosku - że lepiej jest zrobić szybkiego check'a z mapy która już istnieje (nawet jeśli jej implementacja jest nieoptymalna), niż od razu walić do IO/Socket'ów, bo implementacja raczej nie będzie tak fatalna żeby była wolniejsza niż io/socket (jasne, możesz się nie zgadzać, ale nie tego dotyczyło pytanie).

Nawet proste stwierdzenie w stylu fast check to avoid I/O operations as this seems to speed up things też jest wartościowe, inny programista zrozumie, że niespecjalnie cokolwiek mierzyłeś i kierowałeś się intuicją

Wolałbym to zawrzeć w nazwie, niż w dokumentacji. W aplikacji są dziesiątki tysięcy funkcji, jasne że większość z nich nie będzie benchmarkowana osobno/razem, etc.

Poza tym, zauważ że to co napisałbyś w dokumentacji, dokładnie zawiera się w nazwach które próbuję znaleźć:

   fast check to avoid I/O operations as this seems to speed up things
// ↑ pierwsza nazwa
              // ↑ else
                   // ↑ druga nazwa, odnośnie "ciężkości" 
                                                  // ↑ pierwsza nazwa z "fast"

np:

if (fastCheckAvoidingIO(a)) {
  return true;
} else {
  return ioSocketTest(a);
}

i tada, dokumentacja nie jest potrzebna. Myślę że każdy kto uważnie przeczytał Clean Code'a doszedłby do podobnych wniosków.

Możesz też nazwać funkcję checkYadaYadaFastWithoutIOWithFalseNegativesjeżeli tak bardzo chcesz.

Też nie bardzo, bo nie chciałbym funkcji z 9 słowami w nazwie.

Może podkreślę - nie chcę w tym wątku się wypowiadać o optymalizacji, jeśli chcesz kontrybutować - proszę dopisz PR'a na githubie - ten wątek jest stworzony tylko z myślą o nazwach dla dwóch metod.

2

Czyli chcesz mieć w nazwie informację, że jest szybko, że omija IO, że może dać false negative, ale nie chcesz długiej nazwy, nie chcesz zmiany typów, no i zakładasz, że czytelnik kodu nie będzie zadawał pytań, które zadawałem ja (bo będzie wiadomo od kopa). Zgadza się? Powiedziałeś też

Jest dużo takich metod które mają takie nazwy.

To może podaj jakieś przykłady, bo trochę to wygląda tak, jakbyś szukał jakiegoś ładnego angielskiego słowa, które zawrze wszystkie informacje, a nie będzie miało dużo znaków.

0
Afish napisał(a):

Czyli chcesz mieć w nazwie informację, że jest szybko, że omija IO, że może dać false negative, ale nie chcesz długiej nazwy, nie chcesz zmiany typów,

Nie muszę mieć informacji o IO, wystarczy tylko że fast i że false negative. Noi to jest oczywiste że nie chcę zbyt długiej nazwy. Zmiana typu jest niepotrzebna.

no i zakładasz, że czytelnik kodu nie będzie zadawał pytań, które zadawałem ja

Nawet gdyby zadał, co mnie to? W aplikacji jest 10000 funkcji które mają nazwy na 2-4 słowa i jakoś nikt pytań nie zadaje.

To może podaj jakieś przykłady, bo trochę to wygląda tak, jakbyś szukał jakiegoś ładnego angielskiego słowa, które zawrze wszystkie informacje, a nie będzie miało dużo znaków.

Jedno angielskie słówko było by miodzio (jak np memoize() zamiast np getFromStoreOrEvaluate() czy coś).

I nie koniecznie musi mieć mało znaków. Mówiłem że chcę mało słów - nie krótkie słowa.

0
  1. existsNonExactFast
  2. existsExactSlow

Nieprecyzyjna często jest szybka i na odwrót, to samo z dokładnością i powolnością. Osobiście wybrałbym shallow i deep.

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