Metoda chaining-dlaczego jest to dobra praktyka, czy nie?

Metoda chaining jest praktyką metod obiektowych zwracających sam obiekt w celu wywołania wyniku dla innej metody. Tak:

participant.addSchedule(events[1]).addSchedule(events[2]).setStatus('attending').save()

Wydaje się to być uważane za dobrą praktykę, ponieważ tworzy czytelny kod lub "płynny interfejs". Jednak wydaje mi się, że zamiast tego łamie obiekt wywołujący notację implikowaną przez samą orientację obiektu - wynikowy kod nie reprezentuje wykonywania akcji do wyniku poprzedniego metoda, czyli jak zwykle oczekuje się, że kod zorientowany obiektowo będzie działał:

participant.getSchedule('monday').saveTo('monnday.file')

Ta różnica pozwala na tworzenie dwóch różnych znaczeń dla notacji kropkowej "wywołania wynikowego obiektu": w kontekście łączenia łańcuchów powyższy przykład odczytywałby jako zapisanie obiektu participant , mimo że w rzeczywistości przykład ma na celu zapisanie obiektu schedule otrzymanego przez getSchedule.

Rozumiem, że różnica polega na tym, czy wywołana metoda powinna być oczekiwana zwracać coś lub nie (w takim przypadku zwróci sam wywołany obiekt do łączenia). Jednak te dwa przypadki nie odróżniają się od samej notacji, a jedynie od semantyki wywoływanych metod. Kiedy metoda łańcuchowa nie jest używana, zawsze mogę wiedzieć, że wywołanie metody działa na czymś związanym z wynikiem poprzedniego wywołania - przy łańcuchowaniu to założenie łamie się i muszę semantycznie przetworzyć cały łańcuch, aby zrozumieć, co rzeczywisty obiekt bycie wezwanym naprawdę jest. Na przykład:

participant.attend(event).setNotifications('silent').getSocialStream('twitter').postStatus('Joining '+event.name).follow(event.getSocialId('twitter'))

Tam dwa ostatnie wywołania metody odnoszą się do wyniku getSocialStream, podczas gdy poprzednie odnoszą się do uczestnika. Może źle jest pisać łańcuchy, w których zmienia się kontekst (prawda?), ale nawet wtedy będziesz musiał stale sprawdzać, czy łańcuchy kropkowe, które wyglądają podobnie, w rzeczywistości trzymają się tego samego kontekstu, czy działają tylko na wynik.

Wydaje mi się, że podczas gdy metoda łańcuchowania powierzchownie produkuje czytelny kod, przeciążenie znaczenia notacji kropkowej powoduje tylko większe zamieszanie. Ponieważ nie uważam się za guru programowania, zakładam, że to moja wina. więc: co mi umyka? Czy ja rozumiem, że metoda łańcuchowania jest w jakiś sposób Niewłaściwa? Czy są przypadki, w których metoda łańcuchowania jest szczególnie dobra, lub w niektórych przypadkach jest szczególnie zła?

Sidenote: rozumiem, że to pytanie można odczytać jako stwierdzenie opinii zamaskowane jako pytanie. Jednak nie jest - naprawdę chcę zrozum, dlaczego łańcuchowanie jest uważane za dobrą praktykę i gdzie popełniam błąd, myśląc, że łamie nieodłączną notację zorientowaną na obiekt.

Author: Ilari Kajaste, 2009-07-09

15 answers

Zgadzam się, że jest to subiektywne. W większości przypadków unikam łączenia metod, ale ostatnio znalazłem również przypadek, w którym to było po prostu właściwe - miałem metodę, która akceptowała coś w rodzaju 10 parametrów i potrzebowała więcej, ale przez większość czasu trzeba było podać tylko kilka. Z nadpisami stało się to bardzo uciążliwe bardzo szybko. Zamiast tego zdecydowałem się na podejście łańcuchowe:

MyObject.Start()
    .SpecifySomeParameter(asdasd)
    .SpecifySomeOtherParameter(asdasd)
    .Execute();
To coś w rodzaju fabrycznego wzoru. Metoda ta była opcjonalna, ale sprawiła, że łatwiejsze pisanie kodu (szczególnie z IntelliSense). Pamiętaj jednak, że jest to jeden odosobniony przypadek i nie jest to ogólna praktyka w moim kodzie.

Chodzi o to, że w 99% przypadków można zrobić tak samo dobrze lub nawet lepiej bez metody chaining. Ale jest 1%, Gdzie jest to najlepsze podejście.

 69
Author: Vilx-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 14:00:05

Tylko moje 2 grosze;

Metoda łańcuchowania sprawia, że debugowanie jest trudne: - Nie możesz umieścić punktu przerwania w zwięzłym punkcie, aby można było wstrzymać program dokładnie tam, gdzie chcesz - Jeśli któraś z tych metod wyrzuci wyjątek, a otrzymasz numer linii, nie masz pojęcia, która metoda w" łańcuchu " spowodowała problem.

Myślę, że ogólnie dobrą praktyką jest zawsze pisać bardzo krótkie i zwięzłe teksty. Każda linia powinna wykonać tylko jedno wywołanie metodyczne. Preferuj więcej linii niż dłużej linie.

EDIT: komentarz wspomina, że łączenie metod i łamanie linii są oddzielne. To prawda. W zależności jednak od debugera, może być możliwe, ale nie może być możliwe umieszczenie punktu przerwania w środku instrukcji. Nawet jeśli możesz, użycie oddzielnych linii ze zmiennymi pośrednimi daje o wiele większą elastyczność i całą masę wartości, które możesz sprawdzić w oknie Watch, które pomaga w procesie debugowania.

 67
Author: RAY,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-03 02:46:12

Osobiście wolę metody łańcuchowe, które działają tylko na oryginalnym obiekcie, np. ustawiając wiele właściwości lub wywołując metody typu użytkowego.

foo.setHeight(100).setWidth(50).setColor('#ffffff');
foo.moveTo(100,100).highlight();

Nie używam go, gdy jedna lub więcej metod łańcuchowych zwróci jakikolwiek obiekt inny niż foo w moim przykładzie. Podczas gdy składniowo można łańcuch wszystko tak długo, jak używasz prawidłowego API dla tego obiektu w łańcuchu, zmiana obiektów IMHO sprawia, że rzeczy mniej czytelne i może być naprawdę mylące, jeśli API dla różnych obiekty mają jakiekolwiek podobieństwa. Jeśli na końcu wykonasz jakieś bardzo popularne wywołanie metody (.toString(), .print(), cokolwiek) na jakim przedmiocie ostatecznie działasz? Ktoś niechcący czytający kod może nie zauważyć, że byłby to niejawnie zwracany obiekt w łańcuchu, a nie oryginalny odnośnik.

Łączenie różnych obiektów może również prowadzić do nieoczekiwanych błędów null. W moich przykładach, zakładając, że foo jest poprawne, wszystkie wywołania metody są "bezpieczne" (np. ważne dla foo). W Przykład OP:

participant.getSchedule('monday').saveTo('monnday.file')

...nie ma gwarancji (jako zewnętrzny programista patrzący na kod), że getSchedule zwróci poprawny, inny niż null obiekt schedule. Ponadto, debugowanie tego stylu kodu jest często o wiele trudniejsze, ponieważ wiele IDE nie oceni wywołania metody w czasie debugowania jako obiektu, który można sprawdzić. IMO, za każdym razem, gdy możesz potrzebować obiektu do wglądu do celów debugowania, wolę mieć go w jawnej zmiennej.

 33
Author: Brian Moeskau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-05 08:40:49

Martin Fowler ma tu dobrą dyskusję:

Metoda Chaining

Kiedy go używać

Metoda Chaining może dodać wiele do czytelności wewnętrznej DSL i w rezultacie stał się prawie synonum dla wewnętrznych DSL w niektórych umysły. Metoda Chaining jest najlepsza, jednak, gdy jest używany w połączeniu z innymi kombinacjami funkcji.

Metoda Łańcuchowania jest szczególnie skuteczne z gramatykami takimi jak rodzic::= (to | tamto)*. Korzystanie z różnych metody zapewniają czytelny sposób sprawdzam, który argument będzie następny. Podobnie opcjonalne argumenty mogą być łatwo pominąć metodę Chaining. Lista klauzul obowiązkowych, takie jak parent:: = pierwsza sekunda nie praca tak dobrze z podstawową formą, chociaż może być dobrze wspierany przez korzystanie z interfejsów progresywnych. Większość czas, w którym wolałabym zagnieżdżoną funkcję do tej sprawy.

Największy problem metody Chaining is problem z wykończeniem. Podczas gdy istnieją obejścia, Zwykle jeśli na to wpadniesz, lepiej Ci będzie. usng zagnieżdżoną funkcję. Zagnieżdżone Funkcja jest również lepszym wyborem, jeśli pakujesz się w bałagan z Zmienne Kontekstowe.

 22
Author: Dirk Vollmar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 14:09:03

Moim zdaniem metoda chaining jest trochę nowością. Jasne, wygląda fajnie, ale nie widzę w tym żadnych prawdziwych zalet.

Jak jest:

someList.addObject("str1").addObject("str2").addObject("str3")

Any better than:

someList.addObject("str1")
someList.addObject("str2")
someList.addObject("str3")

Wyjątkiem może być sytuacja, gdy addObject() zwróci nowy obiekt, w którym to przypadku niezabezpieczony kod może być nieco bardziej uciążliwy, jak:

someList = someList.addObject("str1")
someList = someList.addObject("str2")
someList = someList.addObject("str3")
 18
Author: Tom Dalling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 13:52:43

Jest to niebezpieczne, ponieważ może zależeć od większej liczby obiektów niż oczekiwano, np. wtedy twoje wywołanie zwraca instancję innej klasy:

Podam przykład:

FoodStore to obiekt, który składa się z wielu sklepów spożywczych, które posiadasz. / align = "left" / getLocalStore () zwraca obiekt, który przechowuje informacje o najbliższym store do parametru. getPriceforProduct (anything) jest metodą tego obiektu.

Więc kiedy dzwonisz / align = "left" / getLocalStore (parametry).getPriceforProduct (anything)

Jesteś zależny nie tylko od artykułów spożywczych, jak jednak, ale także od LocalStore.

Jeśli getPriceforProduct (cokolwiek) kiedykolwiek się zmieni, musisz zmienić nie tylko FoodStore, ale także klasę, która wywołała metodę łańcuchową.

Powinieneś zawsze dążyć do luźnego sprzężenia między klasami.

To powiedziawszy, osobiście lubię je łączyć podczas programowania Rubiego.

 7
Author: rprandi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 16:07:49

Korzyści z chain
ie, gdzie lubię go używać

Jedną z zalet łączenia, o której nie wspomniałem, była możliwość użycia go podczas inicjacji zmiennej lub przekazywania nowego obiektu do metody, Nie wiem, czy jest to zła praktyka, czy nie.

Wiem, że to wymyślony przykład, ale powiedzmy, że masz następujące klasy

Public Class Location
   Private _x As Integer = 15
   Private _y As Integer = 421513

   Public Function X() As Integer
      Return _x
   End Function
   Public Function X(ByVal value As Integer) As Location
      _x = value
      Return Me
   End Function

   Public Function Y() As Integer
      Return _y
   End Function
   Public Function Y(ByVal value As Integer) As Location
      _y = value
      Return Me
   End Function

   Public Overrides Function toString() As String
      Return String.Format("{0},{1}", _x, _y)
   End Function
End Class

Public Class HomeLocation
   Inherits Location

   Public Overrides Function toString() As String
      Return String.Format("Home Is at: {0},{1}", X(), Y())
   End Function
End Class

I powiedzieć, że nie masz dostępu do klasy bazowej, lub powiedzieć, że wartości domyślne są dynamiczne, oparte na czasie, itp. Yes you może wtedy utworzyć instancję, a następnie zmienić wartości, ale może to stać się kłopotliwe, zwłaszcza jeśli po prostu przekazujesz wartości do metody:

  Dim loc As New HomeLocation()
  loc.X(1337)
  PrintLocation(loc)

Ale czy to nie jest po prostu dużo łatwiejsze do odczytania:

  PrintLocation(New HomeLocation().X(1337))

Albo, co z członkiem klasy?

Public Class Dummy
   Private _locA As New Location()
   Public Sub New()
      _locA.X(1337)
   End Sub
End Class

Vs

Public Class Dummy
   Private _locC As Location = New Location().X(1337)
End Class

W ten sposób używam łańcucha i zazwyczaj moje metody są tylko do konfiguracji, więc mają tylko 2 linie, ustaw wartość, a następnie Return Me. Dla nas wyczyścił ogromne linie bardzo trudne do odczytania i zrozum kod w jednej linijce, która czyta się jak zdanie. coś jak

New Dealer.CarPicker().Subaru.WRX.SixSpeed.TurboCharged.BlueExterior.GrayInterior.Leather.HeatedSeats

Vs coś jak

New Dealer.CarPicker(Dealer.CarPicker.Makes.Subaru
                   , Dealer.CarPicker.Models.WRX
                   , Dealer.CarPicker.Transmissions.SixSpeed
                   , Dealer.CarPicker.Engine.Options.TurboCharged
                   , Dealer.CarPicker.Exterior.Color.Blue
                   , Dealer.CarPicker.Interior.Color.Gray
                   , Dealer.CarPicker.Interior.Options.Leather
                   , Dealer.CarPicker.Interior.Seats.Heated)


ie, gdzie nie lubię go używać

Nie używam funkcji łańcuchowych, gdy jest wiele parametrów do przekazania do funkcji, głównie dlatego, że linie są bardzo długie, a jak wspomniał OP, może to być mylące, gdy wywołujesz funkcje do innych klas, aby przekazać je do jednej z metod łańcuchowania.

Istnieje również obawa, że procedura zwróci nieprawidłowe dane, więc do tej pory używałem tylko łańcucha, gdy zwracam tę samą wywołaną instancję. Jak zaznaczono, jeśli łączysz się między klasami, utrudniasz debugowanie (która z nich zwracała null?) i może zwiększyć sprzężenie zależności między klasami.

Wniosek

Jak wszystko w życiu i programowaniu, Łańcuchowanie nie jest ani dobre, ani złe, jeśli można uniknąć złego, to łańcuchowanie może być wielką korzyścią.

Staram się przestrzegaj tych zasad.

  1. staraj się nie łączyć klas
  2. wykonaj procedury specjalnie dla chaining
  3. zrób tylko jedną rzecz w łańcuchu rutyna
  4. użyj go, gdy poprawia czytelność
  5. użyj go, gdy uprości kod
 6
Author: Apeiron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-20 18:59:21

Metoda chaining pozwala na projektowanie zaawansowanych DSLs bezpośrednio w Javie. W zasadzie można modelować przynajmniej te typy reguł DSL:

1. SINGLE-WORD
2. PARAMETERISED-WORD parameter
3. WORD1 [ OPTIONAL-WORD]
4. WORD2 { WORD-CHOICE-A | WORD-CHOICE-B }
5. WORD3 [ , WORD3 ... ]

Reguły te mogą być zaimplementowane przy użyciu tych interfejsów

// Initial interface, entry point of the DSL
interface Start {
  End singleWord();
  End parameterisedWord(String parameter);
  Intermediate1 word1();
  Intermediate2 word2();
  Intermediate3 word3();
}

// Terminating interface, might also contain methods like execute();
interface End {}

// Intermediate DSL "step" extending the interface that is returned
// by optionalWord(), to make that method "optional"
interface Intermediate1 extends End {
  End optionalWord();
}

// Intermediate DSL "step" providing several choices (similar to Start)
interface Intermediate2 {
  End wordChoiceA();
  End wordChoiceB();
}

// Intermediate interface returning itself on word3(), in order to allow for
// repetitions. Repetitions can be ended any time because this interface
// extends End
interface Intermediate3 extends End {
  Intermediate3 word3();
}

Dzięki tym prostym zasadom możesz zaimplementować złożone DSL ' y, takie jak SQL bezpośrednio w Javie, tak jak robi to jOOQ , biblioteka, którą stworzyłem. Zobacz dość złożony przykład SQL zaczerpnięty z mojego bloga tutaj:

create().select(
    r1.ROUTINE_NAME,
    r1.SPECIFIC_NAME,
    decode()
        .when(exists(create()
            .selectOne()
            .from(PARAMETERS)
            .where(PARAMETERS.SPECIFIC_SCHEMA.equal(r1.SPECIFIC_SCHEMA))
            .and(PARAMETERS.SPECIFIC_NAME.equal(r1.SPECIFIC_NAME))
            .and(upper(PARAMETERS.PARAMETER_MODE).notEqual("IN"))),
                val("void"))
        .otherwise(r1.DATA_TYPE).as("data_type"),
    r1.NUMERIC_PRECISION,
    r1.NUMERIC_SCALE,
    r1.TYPE_UDT_NAME,
    decode().when(
    exists(
        create().selectOne()
            .from(r2)
            .where(r2.ROUTINE_SCHEMA.equal(getSchemaName()))
            .and(r2.ROUTINE_NAME.equal(r1.ROUTINE_NAME))
            .and(r2.SPECIFIC_NAME.notEqual(r1.SPECIFIC_NAME))),
        create().select(count())
            .from(r2)
            .where(r2.ROUTINE_SCHEMA.equal(getSchemaName()))
            .and(r2.ROUTINE_NAME.equal(r1.ROUTINE_NAME))
            .and(r2.SPECIFIC_NAME.lessOrEqual(r1.SPECIFIC_NAME)).asField())
    .as("overload"))
.from(r1)
.where(r1.ROUTINE_SCHEMA.equal(getSchemaName()))
.orderBy(r1.ROUTINE_NAME.asc())
.fetch()

Kolejny ładny przykład jest jRTF, małą DSL przeznaczoną do cerowania dokumentów RTF bezpośrednio w Javie. Przykład:

rtf()
  .header(
    color( 0xff, 0, 0 ).at( 0 ),
    color( 0, 0xff, 0 ).at( 1 ),
    color( 0, 0, 0xff ).at( 2 ),
    font( "Calibri" ).at( 0 ) )
  .section(
        p( font( 1, "Second paragraph" ) ),
        p( color( 1, "green" ) )
  )
).out( out );
 6
Author: Lukas Eder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-05 15:40:37

To wydaje się trochę subiektywne.

Metoda łańcuchowa nie jest czymś, co jest z natury złe lub dobre imo.

Czytelność jest najważniejsza.

(rozważ również, że posiadanie dużej liczby metod przykutych łańcuchami sprawi, że rzeczy będą bardzo kruche, jeśli coś się zmieni)

 5
Author: John Nicholas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-09 13:51:22

Wielu używa metody łańcuchowania jako formy wygody, a nie mając na uwadze jakiekolwiek problemy z czytelnością. Łańcuchowanie metod jest dopuszczalne, jeśli wiąże się z wykonaniem tej samej akcji na tym samym obiekcie - ale tylko wtedy, gdy faktycznie zwiększa czytelność, a nie tylko dla pisania mniejszego kodu.

Niestety wielu używa metody łańcuchowania zgodnie z przykładami podanymi w pytaniu. Mimo że mogą być nadal czytelne, to niestety powodują wysokie sprzężenie między wieloma klasami, więc to nie jest pożądane.

 5
Author: aberrant80,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-10 03:31:25

Metoda łańcuchowania może być po prostu nowością w większości przypadków, ale myślę, że ma swoje miejsce. Jeden przykład można znaleźć w Użycie Active Record CodeIgniter :

$this->db->select('something')->from('table')->where('id', $id);

To wygląda dużo czystsze (i ma więcej sensu, moim zdaniem) niż:

$this->db->select('something');
$this->db->from('table');
$this->db->where('id', $id);
To naprawdę jest subiektywne; każdy ma swoje zdanie.
 3
Author: Nathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-10 12:58:55

Całkowicie pominięty punkt tutaj, jest to, że metoda łańcuchowania pozwala na sucha. Jest to skuteczny stand-in Dla " Z " (który jest słabo zaimplementowany w niektórych językach).

A.method1().method2().method3(); // one A

A.method1();
A.method2();
A.method3(); // repeating A 3 times

Ma to znaczenie z tego samego powodu, dla którego DRY zawsze ma znaczenie; jeśli A okaże się błędem, a te operacje muszą być wykonywane na B, wystarczy zaktualizować tylko w 1 miejscu, a nie w 3.

Pragmatycznie, korzyść jest niewielka w tym przypadku. Jeszcze trochę mniej pisania, litle bardziej wytrzymały (suchy), wezmę go.

 3
Author: Anfurny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-01 14:13:02

Zgadzam się, zmieniłem sposób implementacji interfejsu fluent w mojej bibliotece.

Przed:

collection.orderBy("column").limit(10);

Po:

collection = collection.orderBy("column").limit(10);

W implementacji "before" funkcje zmodyfikowały obiekt i zakończyły się return this. Zmieniłem implementację na return a new object of the same type .

Moje rozumowanie dla tej zmiany :

  1. Wartość zwracana nie miała nic wspólnego z funkcją, była tylko po to, aby wspierać część łańcuchowa, powinna być funkcją pustą zgodnie z OOP.

  2. Metoda łańcuchowania w bibliotekach systemowych również implementuje ją w ten sposób (jak linq lub string):

    myText = myText.trim().toUpperCase();
    
  3. Oryginalny obiekt pozostaje nienaruszony, co pozwala użytkownikowi API zdecydować, co z nim zrobić. Pozwala na:

    page1 = collection.limit(10);
    page2 = collection.offset(10).limit(10);
    
  4. A implementacja kopii może być również używana do budowania obiektów:

    painting = canvas.withBackground('white').withPenSize(10);
    

    Gdzie funkcja setBackground(color) zmienia instancję i zwraca nic (jak powinno).

  5. Zachowanie funkcji jest bardziej przewidywalne (patrz punkt 1 i 2).

  6. Użycie krótkiej nazwy zmiennej może również zmniejszyć bałagan w kodzie, bez wymuszania api na modelu.

    var p = participant; // create a reference
    p.addSchedule(events[1]);p.addSchedule(events[2]);p.setStatus('attending');p.save()
    

Wniosek:
Moim zdaniem płynny interfejs wykorzystujący implementację return this jest po prostu błędny.

 2
Author: Bob Fanger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-10 12:21:54

Dobry:

  1. jest zwięzły, ale pozwala elegancko umieścić więcej w jednej linii.
  2. czasami można uniknąć użycia zmiennej, która czasami może być przydatna.
  3. Może działać lepiej.

Zły:

  1. implementujesz zwroty, zasadniczo dodając funkcjonalność do metod na obiektach, które tak naprawdę nie są częścią tego, co te metody mają robić. To zwrócenie czegoś, co już masz, aby uratować kilka bajtów.
  2. ukrywa przełączniki kontekstowe, gdy jeden łańcuch prowadzi do drugiego. Możesz to uzyskać za pomocą getterów, z wyjątkiem tego, że jest to dość jasne, gdy kontekst się przełącza.
  3. łączenie wielu linii wygląda brzydko, nie gra dobrze z wcięciami i może powodować pewne zamieszanie w obsłudze operatorów (szczególnie w językach z ASI).
  4. Jeśli chcesz zacząć zwracać coś innego, co jest przydatne w metodzie łańcuchowej, potencjalnie będziesz miał trudniejszy czas na naprawienie tego lub napotkanie większej liczby problemów z nim.
  5. przenosisz kontrolę na byt, do którego normalnie byś nie ściągnął tylko dla wygody, nawet w ściśle wpisywanych językach błędy spowodowane tym nie zawsze mogą być wykryte.
  6. Może działać gorzej.

Ogólne:

Dobrym podejściem jest nie używać łańcucha w ogóle, dopóki nie pojawią się sytuacje lub konkretne moduły będą szczególnie odpowiednie do niego.

Łańcuchy mogą bardzo poważnie zaszkodzić czytelności w niektórych przypadkach, szczególnie podczas ważenia w pkt 1 i 2.

Przy akasacji może być ona niewłaściwie użyta, na przykład zamiast innego podejścia (na przykład przekazanie tablicy) lub mieszania metod w dziwaczny sposób (parent.setSomething ().getChild ().setSomething ().getParent ().setSomething ()).

 1
Author: jgmjgm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-29 14:22:49

Myślę, że głównym błędem jest myślenie, że jest to podejście zorientowane obiektowo w ogóle, podczas gdy w rzeczywistości jest to bardziej podejście do programowania funkcyjnego niż cokolwiek innego.

Główne powody, dla których go używam, to zarówno czytelność, jak i zapobieganie zalewaniu mojego kodu przez zmienne.

Nie bardzo rozumiem, o czym mówią inni, gdy mówią, że to szkodzi czytelności. Jest to jedna z najbardziej zwięzłych i spójnych form programowania, z jakich korzystałem.

Także to:

ConvertTextToVoice.LoadText ("źródło.txt").Convertovoice ("destination.wav");

To sposób, w jaki zwykle go używam. Używanie go do łańcucha x liczba parametrów nie jest jak zwykle go używać. Jeśli chciałbym umieścić w wywołaniu metody liczbę x parametrów, użyłbym params składnia:

Public void foo (params object [] items)

I rzucać obiekty na podstawie typu lub po prostu użyć tablicy datatype lub kolekcji w zależności od zastosowania case.

 0
Author: Shane Thorndike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-05 18:38:24