Facebook z G+ zabijają RSS-y

Nigdy nie było zbyt różowo, jeśli chodzi o publiczny content dostarczany kanałami RSS na wielu stronach, mimo że implementacja (szczególnie RSS 1.0) sprowadza się do przekształcenia "newsów" (bo o nich głównie myślę) na listę elementów składających się z trzech pól: tytułu, opisu i adresu URL. Ale w czasach popularyzacji Facebooka oraz próbującego go dogonić Google+ mamy do czynienia z postępującym zanikiem dystrybucji informacji przez RSS.

Doliczyłem się trzech sposobów publikacji informacji na strumieniach portali społecznościowych: ręczny przez właściciela (wpisanie treści wiadomości na ścianie), ręczny przez innych na ścianie właściciela, automatyczny (integracja za pomocą FB API, najpierw post pisany jest na stronie właściciela i automatycznie postowany na FB). Za wyjątkiem postowania przez innych na ścianie właściciela pozostałe sposoby są podobnie pracochłonne, więc przyczyna postowania na FB musi być jednak inna i nie zależy od czasu przygotowania i wysłania informacji. Może to wynika z lepiej widocznej audiencji, a może po prostu z faktu, iż na FB ludzie są z reguły zalogowani stale i nie muszą logować się do nieprzyjemnego panelu CMS-a, mogą wpisać co myślą a co nie jest jednocześnie oficjalnym newsem, albo po prostu często współdzielą jednym kliknięciem treść pisaną przez kogoś innego. Sęk w tym, że Facebook i G+ zachowują te informacje wyłącznie dla siebie, mimo że właściciel publikuje publicznie.

Dobijanie RSS następuje dokładnie w tym momencie. Ani FB ani G+ nie udostępniają contentu na zewnątrz, choćby właśnie w omawianych kanałach RSS. Jakiś czas temu FB wyłączył feedy rss/atom. Zmuszają przez to do rejestracji i korzystania z ich nie-do-końca-darmowych usług. Na dowód tego Google zniszczyło jeden ze swoich lepszych produktów - Google Reader. Interfejs FB/G+ nie jest tym, jaki lubię, a do tego nie chcę rejestrować się i zgadzać na nieodpowiadające mi warunki tylko dlatego, że chcę czytać publiczne newsy, które mogą być emitowane przecież w tradycyjny sposób bez dodatkowego nakładu pracy. Niestety wina leży też po stronie odbiorców, którzy nie domagają się RSS, ale też uznają ten kanał za używany wyłącznie przez geeków (niektórzy mylą geeków z hipsterami, ale to przejaw ignorancji i drwin z ludzi używających wygodnego narzędzia). Znam osoby korzystające z RSS nie będące geekami.

Jak temu zaradzić? Mam dwa pomysły, obydwa mające jednak spore wady. Pierwszy to zgłaszanie próśb do administratorów/webmasterów stron o dodanie kanałów RSS, a drugi to utworzenie projektu "news4rss", który byłby wrapperem dla stron typu "aktualności" czy wpisów blogowych nie posiadających kanałów RSS. Wady to odpowiednio brak zainteresowania ze strony właścicieli stron (dodatkowe koszty, dodatkowa praca - mimo że relatywnie niewielka!), oraz w drugim przypadku dokładanie swoich "trzech groszy" do zabijania RSS (poprzez brak zainteresowania tym kanałem ze strony właścicieli). Może działanie na tych dwóch płaszczyznach przyniesie pozytywny efekt?

Czytaj więcej : komentarze (0) : Lis 14, 2013

Co boli MVC

Prowadziliśmy swego czasu dyskusje o logice biznesowej i szukaliśmy rozwiązania starając się znaleźć jej miejsce w MVC. Stosując bowiem ten paradygmat logika naturalnie "rozmywa się" po kontrolerach i modelach (ekstremiści wstawiają ją nawet do widoków). Typowy przykład złego podejścia to kiepskie implementacje ORM (Propel-PHP, DjangoORM - Python):

class User(Model):
   def save(..):
      ...

W tym przypadku Model jest jednocześnie persistance managerem i wykonuje operacje, których nie powinien. Prawidłowe podejście to

class UserManager:
   def save(self, user):
       ....

Który kod łatwiej przetestować? Gdzie znajduje się logika zapisu stanu encji?

Inny przykład:

class Product(Model):
    def calculate_tax(self, tax):
       ...

vs

class TaxCalculator:
    def calculate_tax(self, product):
       ...

Jak widać w drugim podejściu to TaxCalculator zawiera logikę obliczania podatku dla produktu. Możemy ją łatwiej przetestować (bez uruchamiania całego środowiska i persistance) oraz możemy ją wymieniać wprowadzając różne kalkulatory, np. USATaxCalculator, VATTaxCalculator, etc.

Frameworki narzucają konwencje, ale nie ograniczają aż tak naszych działań. Dlatego w moich projektach, ostatnio opartych o Django, stosuję minimalny kod kontrolerów, operacje zamykam w formularzach (mimo, że nie są renderowane) lub funkcjach/metodach wykonujących proces na rzecz jakiegoś obiektu. W ten sposób modele są pozbawione metod będących operacjami na ich samych. Taki kod jest przede wszystkim łatwiej testowalny (mowa o unit tests), oraz nie wymaga uruchamiania i konfigurowania całego środowiska, co czasem bywa problematyczne i jest wolniejsze.

Jeśli już mowa o Django, to wyraźnie widać, gdzie popełniono błędy projektowe. Model już na wstępie posiada dwie operacje, których nie powinien mieć - model.save() i model.delete(). Zapis i odczyt stanu oraz usuwanie modelu powinny być wykonywane przez obiekt zewnętrzny (konkretnie persistence manager). Z kolei formularze są ściśle związane z widgetami HTML, co przy stosowaniu ich jako obiektów utility (np. do walidacji danych) pociąga za sobą niechciane zależności.

Warto zastosować się do kilku reguł:

Ciekawe artykuły:

Czytaj więcej : komentarze (0) : Wrz 6, 2013

Brak wyjątku przy błędach Django compilemessages [v1.4]

Zauważyłem, że compilemessages nie rzuca wyjątków przy błędach msgfmt. Jest to typowe wyciszenie błędu przez brak sprawdzania returncode. To praktyka naruszająca Zen of Python, tj. regułę "Errors should never pass silently".

Przed zgłoszeniem ticketa warto sprawdzić, czy ktoś już tego nie raportował. Okazuje się, że zgłoszenie już jest od dwóch miesięcy, ale uwaga! Jest już poprawka zamieniającą os.system() na subprocess.Popen()!

W przeciwieństwie do ticketów otwartych od wielu lat to na prawdę szybka reakcja. Jestem mile zaskoczony!

https://code.djangoproject.com/ticket/19584

Czytaj więcej : komentarze (0) : Mar 6, 2013

jQuery Tools DateInput - nie używać, grozi utratą zdrowia

Ostatnio walczę z jQuery Tools DateInput, i to dosłownie. Początkowo sprawia dobre wrażenie, ale jest to kawał skopanego i źle prowadzonego softu:

Straciłem cały dzień na łataniu i dorabianiu brakujących funkcji (to jest dosyć proste, jeśli wiemy co należy zrobić), ale co trochę wychodzą nowe błędy.

Zatem jeśli planujesz użyć kalendarza w sposób bardziej zaawansowany niż tylko podpięcie go pod input, to stanowczo odradzam ten pakiet.

Czytaj więcej : komentarze (0) : Lut 20, 2013

Django NoDB Test Runner - czyli czuję zapach świeżej mogiły

A tak se wstawiłem, a co...

Developerzy Django swego czasu nie potrafili wyobrazić sobie, że może istnieć w naszym niemałym programistycznym świecie potrzeba odpalania testów bez bazy (baz) danych. Minęły trzy lata i zaserwowali nam w końcu (1.2) możliwość zdefiniowania własnego test runnera w prosty sposób (class based).

Prymitywny test runner bez bazy danych:

class NoDbTestRunner(DjangoTestSuiteRunner):
  """ A test runner to test without database creation """

  def setup_databases(self, **kwargs):
    """ Override the database creation defined in parent class """
    pass

  def teardown_databases(self, old_config, **kwargs):
    """ Override the database teardown defined in parent class """
    pass

który podpina się w settings równie trywialnie:

TEST_RUNNER = 'testrunner.NoDbTestRunner'

Pal sześć, że potrzebuję suite do testów z bazą równocześnie z suite bez niej, i żeby to osiągnąć będę musiał się jeszcze sporo napocić dorabiając najlepiej wykrywanie potrzeby użycia testowych baz. Najgorsze jednak w tym wszystkim jest to, że połączenia testowe tworzone są przez defaultowy test runner, który właśnie wywaliliśmy w kosmos. Jeśli myślicie, że brak jego odpalenia będzie skutkował brakiem zdefiniowanych połączeń i wyjątkami, to jesteście w błędzie. Oryginalny test runner ZAMIENIA parametry definicji ISTNIEJĄCYCH połączeń.

Skutkiem tego jest uruchamianie testów na ustawieniach defaultowych. A czy wiecie co robi Django przy wczytwaniu fixturek do testów? Flush DB. Dziękuję Ci, Django. Mam nadzieję, że teraz nie odpalicie NoDbTests na swoich serwerach live.

Fatalny ORM i, jak się okazuje, fatalne rozwiązanie frameworka testowego w Django zaczynają przekonywać mnie do skierowania się w stronę innego produktu, szczególnie gdy realizuje się systemy większe niż "przeciętny blogasek".

Czytaj więcej : komentarze (0) : Lut 13, 2013