Płynne API (Fluent Interface) ============================= Wprowadzenie ------------ Płynne API (ang. *fluent interface*) to sposób projektowania interfejsów programistycznych (API), który umożliwia łańcuchowe wywoływanie metod (*method chaining*). Celem jest zwiększenie czytelności kodu oraz nadanie mu formy przypominającej zdania w języku naturalnym. :contentReference[oaicite:0]{index=0} Wzorzec ten został spopularyzowany przez Erica Evansa i Martina Fowlera (ok. 2005) i jest szeroko stosowany m.in. w bibliotekach LINQ czy ORM. :contentReference[oaicite:1]{index=1} Podstawowa idea ---------------- Każda metoda: - modyfikuje stan obiektu **lub** - ustawia parametr konfiguracji i **zwraca ten sam obiekt (`self`)**, co pozwala kontynuować wywołania. Przykład (bez Fluent API): .. code-block:: python ax = Axes(0, 0, 100, 100) ax.set_xrange(0, 10) ax.set_yrange(-1, 1) Z Fluent API: .. code-block:: python ax = Axes(0, 0, 100, 100) \ .bottom(0, 10) \ .left(-1, 1) Kod staje się krótszy i bardziej deklaratywny. Kluczowe zasady projektowe --------------------------- 1. Metody zwracają ``self`` .. code-block:: python def bottom(self, xmin, xmax): self.xmin = xmin self.xmax = xmax return self 2. Zachowanie kontekstu Każde kolejne wywołanie operuje na tym samym obiekcie (tym samym stanie). 3. Czytelność jako DSL (Domain-Specific Language) Kod powinien przypominać „zdanie”: .. code-block:: python Axes(...).bottom(0, 10).left(-1, 1).with_grid(True) 4. Opcjonalne zakończenie łańcucha Czasem stosuje się metodę ``end()`` jako sygnał końca konfiguracji: .. code-block:: python ax = Axes(...).bottom(...).left(...).end() Zastosowanie w klasie Axes --------------------------- W zadaniu projektowym klasa ``Axes`` pełni rolę konfiguratora układu współrzędnych. Fluent API pozwala oddzielić: - konstrukcję obiektu (geometria) - konfigurację (zakresy, styl, siatka) Przykład docelowy: .. code-block:: python axes = ( Axes(80, 40, 580, 260) .bottom(0.0, 6.28) .left(-1.0, 1.0) .with_xticks(6) .with_yticks(4) .with_grid(True) .end() ) Warto zwrócić uwagę: - metody nie tworzą nowych obiektów → modyfikują istniejący - kolejność wywołań ma znaczenie semantyczne - API powinno być spójne (np. ``bottom/top``, ``left/right``) Typowe błędy ------------ 1. Brak ``return self`` .. code-block:: python def bottom(self, xmin, xmax): self.xmin = xmin self.xmax = xmax # brak return → łańcuch się psuje 2. Niespójne nazewnictwo Złe: .. code-block:: python .set_xrange(...).grid_on(True) Dobre: .. code-block:: python .bottom(...).with_grid(True) 3. Zbyt długa logika w metodach Metody fluent powinny być **proste i jednofunkcyjne**. Uwagi projektowe ---------------- - Fluent API poprawia czytelność, ale może utrudniać debugowanie (łańcuch wielu wywołań w jednej linii). - Dobrą praktyką jest łamanie łańcucha na wiele linii. - W Pythonie implementacja jest naturalna dzięki zwracaniu ``self``.