Archive for Programming

Text Ellipsis with Gradient Fade in Pure CSS

2011-12-26 18:56

The other day I encountered a small but very interesting effect, visible in Bitbucket issues’ table. Some of the cells were slightly too narrow for the text they contained, and it had to be ellipsized. Usually this is done by cropping some of the text’s trailing chars and replacing them with dots – mostly because that’s what the text-ellipsis style is doing. Here, however, I saw something much more original: the text was fading out in gradient-like style, going from full black to full transparent/white over a distance of about 30 pixels. It made quite of an eye-catching effect.

So, I decided to bring up Firebug and find out how this nifty trick actually works. Taught by past experiences, I expected a tightly coupled mis-mash of DOM and CSS hacks, with lots of moving parts that need to be carefully adjusted in face of any changes. Alas, I was wrong: it turned out to only use CSS, in succinct and elegant manner. After simple reverse-engineering, I uncovered a clever solution involving gradients, opacity and :before/:after pseudo-elements. It definitely deserves some press, so let’s look into it.

Tags: , ,
Author: Xion, posted under Internet, Programming » 3 comments

About Java references

2011-12-17 19:22

There is somewhat common misconception about garbage collecting, that it totally frees the programmer from memory-related concerns. Granted, it makes the task easier in great many cases, but it does so at the expense of significant loss of control over objects’ lifetime. Normally, they are kept around for at least until they are not needed anymore – and usually that’s fine for the typical definitions of “need” and “at least”. Usually – but not always.

For those less typical use cases, garbage-collected environments provide mechanisms allowing to regain some of that lost control, to the extent necessary for particular task. Java, for example, offers a variety of different types of references, enabling to change the notion of what it means for an object to be eligible for garbage collecting. Choosing the right one for a problem at hand can be crucial, especially if we are concerned with the memory footprint of our application. Since – as the proverb goes – JVM expands to fill all available memory, it’s good to know about techniques which help maintain our heap size in check.

The default is strong

So today, I will discuss the SoftReference and WeakReference classes, which can be both found in the java.lang.ref package. They provide the so-called soft and weak references, which are both considerably less powerful when it comes to prolonging the lifetime of an object.

Tags: , , ,
Author: Xion, posted under Programming » 1 comment

Decorators with Optional Arguments in Python

2011-12-13 18:34

It is common that features dubbed ‘syntactic sugar’ are often fostering novel approaches to programming problems. Python’s decorators are no different here, and this was a topic I touched upon before. Today I’d like to discuss few quirks which are, unfortunately, adding to their complexity in a way that often doesn’t feel necessary.

Let’s start with something easy. Pretend that we have a simple decorator named @trace, which logs every call of the function it is applied to:

  1. @trace
  2. def some_function(*args):
  3.     pass

An implementation of such decorator is relatively trivial, as it wraps the decorated function directly. One of the possible variants can be seen below:

  1. def trace(func):
  2.     def wrapped(*args, **kwargs):
  3.         logging.debug("Calling %s with args=%s, kwargs=%s",
  4.                       func.__name__, args, kwargs)
  5.         return func(*args, **kwargs)
  6.     return wrapped

That’s pretty cool for starters, but let’s say we want some calls to stand out in the logging output. Perhaps there are functions that we are more interested in than the rest. In other words, we’d like to adjust the priority of log messages that are generated by @trace:

  1. @trace(level=logging.INFO)
  2. def important_func():
  3.     pass

This seemingly small change is actually mandating massive conceptual leap in what our decorator really does. It becomes apparent when we de-sugar the @decorator syntax and look at the plumbing underneath:

  1. important_func = trace(level=logging.INFO)(important_func)

Introduction of parameters requires adding a new level of indirection, because it’s the return value of trace(level=logging.INFO) that does the actual decorating (i.e. transforming given function into another). This might not be obvious at first glance and admittedly, a notion of function that returns a function which takes some other function in order to output a final function might be – ahem – slightly confusing ;-)

But wait! There is just one more thing… When we added the level argument, we not necessarily wanted to lose the ability to invoke @trace without it. Yes, it is still possible – but the syntax is rather awkward:

  1. @trace()
  2. def some_function(*args):
  3.     pass

That’s expected – trace only returns the actual decorator now – but at least slightly annoying. Can we get our pretty syntax back while maintaining the added flexibility of specifying custom arguments? Better yet: can we make @trace, @trace() and @trace(level) all work at the same time?…

Looks like tough call, but fortunately the answer is positive. Before we delve into details, though, let’s step back and try to somewhat improve the way we are writing our decorators.

Tags: , , , ,
Author: Xion, posted under Programming » 2 comments

Synchronization Through Memcache

2011-12-10 18:11

In web and server-side development, a memcache is a remote service that keeps transient data in temporary, in-memory store and allows for fast access. It is usually based on keys which identify values being stored and retrieved. Due to storing technique – RAM rather than actual disks – it offers great speed (often less than few milliseconds per operation) while introducing a possibility for values to be evicted (deleted) if memcache runs out of space. Should that happen, oldest values are usually disposed of first.

This functionality makes memcache a good secondary storage that complements the usual persistent database, increasing the efficiency of the system as a whole. The usual scenario is to poll memcache first, and resort to querying the database only if the result cannot be found in cache. Once the query is made, its results are memcached for some reasonable amount time (usually called TTL: time to live), depending on allowed trade-offs between speed and being up-to-date with our results.

While making applications more responsive is the primary use case for memcache, it turns out that we can also utilize it for something completely different. That’s because memcache implementations offer something more besides the obvious get/set commands. They also have operations which make it possible to use memcache as synchronization facility.

Odkrycie archeologiczne

2011-11-20 21:18

Sprzed prawie czterech lat pochodzi pewien niewielki (~2KLOC) projekt uczelniany, na który natknąłem się kilka dni temu w swoich przepastnych archiwach i postanowiłem upublicznić. Jest to implementacja prostego (acz zupełnie funkcjonalnego) serwera FTP, napisana w czystym C pod systemy POSIX-owe. Nie spodziewam się bynajmniej, aby mogła znaleźć rzeczywiste zastosowanie jako kawałek oprogramowania. Jest ona jednak całkiem interesująca jako kawałek kodu.

Wielu znany jest zapewne “syndrom następnego pół roku”. Polega on na tym, że gdy po pół roku (plus/minus kilka miesięcy) spoglądamy na stworzony przez siebie kod, widzimy go tak, jakby napisał go ktoś zupełnie inny. Zazwyczaj wręcz trudno nam się w nim połapać i szybko dochodzimy do wniosku, że teraz napisalibyśmy go zdecydowanie lepiej. Nasz twór traktujemy więc jako bezwarto… ekhm… legacy code (;]), i uważamy to za naturalną kolej rzeczy.

Jednak moje niedawne znalezisku okazało się pod tym względem sporym zaskoczeniem. Nietypowe jest bowiem to, jak przetrwało ono próbę czasu. Na jego podstawie muszę dojść do lekko szokującego wniosku, iż Xion2007 potrafił – o zgrozo – pisać dobry kod. Robił to wprawdzie ostrożnie i raczej niepewnie (czego dowodem była przesadna ilość komentarzy), ale koniec końców udawało mu się to całkiem nieźle. Wysyłając mu wiadomość z przyszłości, mógłbym wprawdzie wspomnieć o zaletach podziału kodu na pliki krótsze niż 800-linijkowe, lecz poza tym do niewielu rzeczy mógłbym się przyczepić. To zupełnie akceptowalny, czytelny i przejrzysty kod w C

Madness!

Tags: , ,
Author: Xion, posted under Programming, Studies » Comments Off on Odkrycie archeologiczne

Biedny, biedny JavaScript

2011-11-15 21:16

Przyznam, iż jestem trochę zaskoczony. Okazuje się bowiem, że niekiedy zupełnie nie udaje mi się skomunikować tego, co mam w rzeczywistości na myśli. A wydawać by się mogło, że przynajmniej te 500+ notek na blogu powinno dość skutecznie nauczyć mnie, jak klarownie formułować swoje stwierdzenia i opinie. Teoretycznie niby też wiem, że zrozumienie jest często podwójną iluzją, więc z dwóch wyjaśnień należy zawsze wybierać te łatwiejsze i bardziej bezpośrednie – także wtedy, gdy trzeba je dopiero znaleźć. To wszystko wydaje się oczywiste, dopóki – jak się przekonałem – nie okaże się trudne w praktycznym stosowaniu.

O co mi w tym miejscu chodzi? Ano o to, iż niesłusznie zostałem uznany przez kilka osób za – nieco wyolbrzymiając – hejtera JavaScriptu. Tak została przez niektórych odebrana moja niedawna publikacja slajdów z prezentacji pod tytułem The Beauty and the JavaScript; tytułem, który rzeczywiście może dawać co nieco do myślenia ;) I chociaż mógłbym uznać, że wchodzi tu w grę głównie kwestia oceny wykładu po samych slajdach, to jakoś wydaje mi się, że wypadałoby tu dokonać małego sprostowania. Dzięki temu mógłbym też napisać, jak to właściwie jest z tą moją opinią o JavaScripcie, który przecież już od dłuższego czasu jest sam w sobie bardzo nośnym tematem.

Spieszę więc z wyjaśnieniem, że w kwestii JavaScriptu mam raczej osobliwą opinię. Otóż przede wszystkim jest mi go… żal.

Klasy bardziej meta

2011-11-08 21:57

W językach ze skrzywieniem obiektowym klas używa się często i gęsto. Nieco inaczej jest z innym, o wiele mniej znanym pojęciem: metaklasami. Przedrostek meta- sugeruje tu od razu nieco wyższy poziom abstrakcji, co jest generalnie słusznym podejrzeniem. Dokładne znaczenie kryjące się za tym terminem w pewnym stopniu zależy od języka programowania, lecz w każdym przypadku chodzi o narzędzie związane z manipulowaniem samymi klasami. Zupełnie intuicyjnie jest to więc “jeden poziom meta więcej” :)
Jako nieco bardziej zaawansowana funkcjonalność, metaklas nie wykorzystuje się codziennie. Tym bardziej jednak warto wiedzieć przynajmniej z grubsza, jak działają, aby poprawnie rozpoznawać sytuacje, w których są one użyteczne. I dlatego właśnie dzisiaj przyjrzymy się metaklasom w trzech wariantach, specyficznych dla popularnych języków programowania.

Pierwszy z nich dotyczy systemów refleksji, czyli przydatnego mechanizmu językowego, pozwalającego programowi na wgląd w swoją wewnętrzną strukturę. W językach obiektowych oznacza to przede wszystkim możliwość posługiwania się klasami na bardziej dynamicznym poziomie. Są one wtedy reprezentowane przez obiekty, i właśnie te reprezentacje – używane poprzez moduły refleksji – nazywa się czasem metaklasami.
W wielu językach wyglądają one podobnie. Java ma na przykład klasę java.lang.Class, zaś C# – System.Type. Zyskując dostęp do instancji tychże klas (np. poprzez Class.forName albo Type.GetType) otrzymujemy możliwość wykonywania operacji na klasach, które one reprezentują. I tak możliwe jest chociażby tworzenie ich obiektów, wywoływanie metod, dostęp do pól. Dzięki temu możemy na przykład w (miarę) łatwy sposób zaimplementować proste rozwiązania wspierające pluginy, tj. dynamicznie ładowane wtyczki do naszych aplikacji.

Drugie znaczenie pojęcia metaklasy opisuje referencje do klas. Ideą jest tu traktowanie klas jako wartości pierwszego rodzaju (first-class value), które można przypisywać do zmiennych i w uogólniony sposób przekazywać między różnymi miejscami w kodzie. Specjalne zmienne, do których możemy “przypisywać” klasy są w co najmniej jednym języku nazywane właśnie metaklasami.
Przydatność tego typu rozwiązania zależy głównie od tego, jak wielkimi jesteśmy fanami wzorców typu fabryka abstrakcyjna :) Być może podstawową funkcjonalnością takich metaklas jest bowiem abstrakcja procesu tworzenia (lub ogólniej: pozyskiwania z zewnątrz) nowych obiektów. Pozostałe przypadki użycia metaklas są pokrywane zwykle przez szablony (C++), typy generyczne (C#, Java, itp.) lub podobne mechanizmy tworzenia kodu, który w pewien określony sposób jest niezależny od dokładnego typu obiektów, którymi operuje.

Czas wreszcie na trzeci wariant metaklas. Jest on zdecydowanie najciekawszy, ale też najbardziej skomplikowany i w pewien sposób wysublimowany – mimo swojej niewątpliwej użyteczności. Mam tutaj na myśli metaklasy w Pythonie.

Tags: , , , , ,
Author: Xion, posted under Programming » 1 comment
 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.