Bloomberg:

littleBits Founder Ayah Bdeir discusses her opensource library of electronic modules that snap together with tiny magnets for prototyping and play.

This is awesome.

Bram Cohen:

Management figures they’ll save money on salaries by leaving it up to the employees to negotiate for their own pay. So they don’t give raises until someone tries to negotiate for one.

Aaron Erickson:

In many companies, particularly consulting companies, salespeople call the shots, have most of the respect, and take home most of the rewards. Delivery – the "programmers", are the people who are to be managed, paid as little as possible, and controlled by management.

Aby skonwertować czas do liczby sekund w Excelu należy wartość komórki z czasem przemnożyć przez liczbę sekund w dobie (86400).

Times are stored internally by Excel as fractions of a 24-hour day, so that 12:00:00 would be stored as 0.5 and 18:00:00 as 0.75. Consequently, to convert a time to seconds, you must multiply by the number of seconds in a day - it is easier to remember this as *24*60*60 rather than the actual number (86400).

excelforum.com

Kontrolki wizualne w technologii Windows Forms pozwalają tworzyć powiązanie pomiędzy właściwością kontrolki a właściwością obiektu będącego źródłem danych dla tej kontrolki.

class MyTextBox : TextBox
{
  public void Bind(object obj, string dataMember)
  {
    DataBindings.Add(new Binding("Text", obj, dataMember));
  }
}

Takie rozwiązanie działa bez zarzutu jednak ma pewną wadę – nazwa właściwości źródła danych przekazywana jest jako łańcuch znaków. Powoduje to sytuację, w której poprawność tego powiązania zweryfikujemy dopiero po uruchomieniu programu chociaż chciałoby się aby było to już na etapie kompilacji. Aby osiągnąć mój cel postanowiłem skorzystać z możliwości jakie oferują wyrażenia lambda w ramach języka C#.

class MyTextBox1 : TextBox
{
  public void Bind<T>(T obj, Expression<Func<T, object>> dataMemberExpr)
  {
    string dataMember = GetDataMember(dataMemberExpr);
    DataBindings.Add(new Binding("Text", obj, dataMember));
  }

  private string GetDataMember(Expression<Func<T, object>> dataMemberExpr)
  {
    LambdaExpression expr = dataMemberExpr;
    Expression node = expr.Body;
    MemberExpression memberExpr = (MemberExpression)node;
    return memberExpr.Member.Name;
  }
}

Aby stworzyć powiązanie należy wywołać metodę Bind w następujący sposób:

class Person
{
  public string Name { get; set; }
}

Person p = new Person { Name = "Bob" };

MyTextBox1 myTextBox1 = new MyTextBox1();
myTextBox1.Bind(p, x => x.Name);

Chciałem wykorzystać Phusion Passenger podczas tworzenia aplikacji Ruby on Rails. Konieczne w tym celu było aktywowanie środowiska development. Niestety opcja RailsEnv nie skutkowała pożądanym zachowaniem. Ostatecznie należało ustawić opcję RackEnv (jak w przykładowej konfiguracji zamieszczonej poniżej).

<VirtualHost *:80>
  ServerName app.local
  DocumentRoot "/path/to/your/app/public"
  RackEnv "development"
  <Directory "/path/to/your/app/public">
    Allow from all
    Options -MultiViews
  </Directory>
</VirtualHost>

Ostatnimi czasy wzorzec Dekorator przydał nam się w sytuacji, w której nie chcieliśmy modyfikować widoku jednak chcieliśmy aby dane w pewnych przypadkach były inaczej prezentowane. Zaimplementowaliśmy ten wzorzec w najprostszy możliwy sposób:

class Coffee {
  private final String name;

  public Coffee(String name) {
    this.name = name;
  }

  public int price() {
    return 4;
  }

  public String name() {
    return name;
  }
}

class Milk extends Coffee {
  private final Coffee coffee;

  public Milk(Coffee coffee) {
    super("");
    this.coffee = coffee;
  }

  @Override
  public int price() {
    return coffee.price() + 2;
  }

  @Override
  public String name() {
    return coffee.name();
  }
}

class BasicTest {
  private Coffee decorated;

  @Test
  public void testPriceDecoration() {
    assertEquals(6, decorated.price());
  }

  @Test
  public void testNameDecoration() {
    assertEquals("coffee", decorated.name());
  }

  @Test
  public void testMultiLevelDecoration() {
    assertEquals(8, new Milk(decorated).price());
  }

  @Before
  public void setUp() throws Exception {
    decorated = new Milk(new Coffee("coffee"));
  }
}

Powyższy test potwierdza, że implementacja jest prosta i skuteczna jednak posiada kilka wad:

  • klasa dekorowana musi nadpisywać wszystkie metody klasy dekorowanej,
  • dodanie metody do klasy dekorowanej nie wymusza na nas implementacji tej metody w klasie dekorującej.

Chcąc znaleźć rozwiązanie tych problemów postanowiłem użyć klasy Proxy.

interface Coffee {

  int price();

  String name();
}

class CoffeeImpl implements Coffee {
  private final String name;

  public CoffeeImpl(String name) {
    this.name = name;
  }

  public int price() {
    return 4;
  }

  public String name() {
    return name;
  }
}

class Milk extends CoffeeImpl {

  public static Coffee add(final Coffee coffee) {
    return Decorators.decorate(coffee, new Milk(coffee));
  }

  private final Coffee coffee;

  private Milk(Coffee coffee) {
    super("");
    this.coffee = coffee;
  }

  public int price() {
    return coffee.price() + 2;
  }
}

class Decorators {

  public static Coffee decorate(final Coffee coffee, final Coffee decorator) {
    InvocationHandler handler = new InvocationHandler() {
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Class decoratorClass = decorator.getClass();
        Method m = decoratorClass.getMethod(method.getName(), method.getParameterTypes());
        Coffee target = m.getDeclaringClass() == decoratorClass ? decorator : coffee;
        return method.invoke(target, args);
      }
    };
   return (Coffee) Proxy.newProxyInstance(
     Coffee.class.getClassLoader(),
     new Class[] { Coffee.class },
     handler);
 }
}

class ProxyTest {
  private Coffee decorated;

  @Test
  public void testPriceDecoration() {
    assertEquals(6, decorated.price());
  }

  @Test
  public void testNameDecoration() {
    assertEquals("coffee", decorated.name());
  }

  @Test
  public void testMultiLevelDecoration() {
    assertEquals(8, Milk.add(decorated).price());
  }

  @Before
  public void setUp() throws Exception {
    decorated = Milk.add(new CoffeeImpl("coffee"));
  }
}

Implementacja z użyciem klasy Proxy także działa bez zarzutu oraz rozwiązuje problemy wersji podstawowej jednak nie podoba mi się konieczność zastosowania interfejsu wymuszana przez klasę Proxy. Postanowiłem bardziej zagłębić się w ten temat i natrafiłem na bibliotekę cglib, która pomogła w rozwiązaniu ostatniego problemu.

class Coffee {
  private final String name;

  public Coffee(String name) {
    this.name = name;
  }

  public int price() {
    return 4;
  }

  public String name() {
    return name;
  }
}

class Milk extends Coffee {

  public static Coffee add(final Coffee coffee) {
    return Enhancers.enhance(coffee, new Milk(coffee));
  }

  private final Coffee coffee;

  public Milk(Coffee coffee) {
    super("");
    this.coffee = coffee;
  }

  @Override
  public int price() {
    return coffee.price() + 2;
  }
}

public class Enhancers {

  public static Coffee enhance(final Coffee coffee, final Coffee enhancer) {
    MethodInterceptor interceptor = new MethodInterceptor() {
      public Object intercept(Object obj, Method method, Object[] objects,
          MethodProxy methodProxy) throws Throwable {
        Class enhancerClass = enhancer.getClass();
        Method m = enhancerClass.getMethod(method.getName(), method.getParameterTypes());
        Object target = m.getDeclaringClass() == enhancerClass ? enhancer : coffee;
        return method.invoke(target, objects);
      }
    };

    Enhancer e = new Enhancer();
    e.setSuperclass(Coffee.class);
    e.setCallback(interceptor);

    return (Coffee) e.create(new Class[] { String.class }, new Object[] { "" });
  }
}

class CglibTest {
  private Coffee decorated;

  @Test
  public void testPriceDecoration() {
   assertEquals(6, decorated.price());
  }

  @Test
  public void testNameDecoration() {
    assertEquals("coffee", decorated.name());
  }

  @Test
  public void testMultiLevelDecoration() {
    assertEquals(8, Milk.add(decorated).price());
  }

  @Before
  public void setUp() throws Exception {
    decorated = Milk.add(new Coffee("coffee"));
  }
}

<project>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

W systemie istnieją dwie klasy (FooImpl i BarImpl), które zależą od siebie poprzez pole konstruktora.

interface Foo {
  void execute(boolean forward);
}

class FooImpl implements Foo {
  private final Bar bar;

  public FooImpl(Bar bar) {
    this.bar = bar;
  }

  public void execute(boolean forward) {
    System.out.print("Foo");
    if (forward) {
      System.out.print(" -&gt; ");
      bar.execute(!forward);
    }
  }
}

interface Bar {
  void execute(boolean forward);
}

class BarImpl implements Bar {
  private final Foo foo;

  public BarImpl(Foo foo) {
    this.foo = foo;
  }

  public void execute(boolean forward) {
    System.out.print("Bar");
    if (forward) {
      System.out.print(" -&gt; ");
      foo.execute(!forward);
    }
  }
}

Taki stan nie pozwala stworzyć obiektów tychże klas bez konieczności wprowadzenia dodatkowego obiektu pośredniczącego wywołania do poprawnie stworzonego obiektu. W javie funkcjonalność tą realizuje klasa java.lang.reflect.Proxy. Aby stworzyć takie proxy potrzebna będzie jeszcze implementacja interfejsu java.lang.reflect.InvocationHandler, do której przekazane będą wszystkie wywołania metod obiektu proxy.

class DelegateInvocationHandler implements InvocationHandler {
  private Object delegate;

  public void setDelegate(Object delegate) {
    this.delegate = delegate;
  }

  public Object invoke(Object target, Method method, Object[] args)
      throws Throwable {
    return method.invoke(delegate, args);
  }
}

Aby zbudować obiektu obu klas najpierw przygotujemy proxy FooImpl. Korzystając z obiektu fooProxy możemy stworzyć obiekty klas FooImpl i BarImpl za pomocą operatora new. Ostatnim etapem wymaganym do poprawnego działania proxy potrzebne jest ustawienia obiektu delegata. Po wykonaniu tych wszystkich operacji wywołania metod execute zostaną przekazane do odpowiednich obiektów.

DelegateInvocationHandler handler = new DelegateInvocationHandler();

Foo fooProxy = (Foo) Proxy.newProxyInstance(
  Foo.class.getClassLoader(),
  new Class[]{Foo.class},
  handler);

Bar bar = new BarImpl(fooProxy);
Foo foo = new FooImpl(bar);

handler.setDelegate(foo);

foo.execute(true); // na wyjsciu Foo -> Bar
bar.execute(true); // na wyjsciu Bar -> Foo

Java w wersji 6 dostarcza klasę java.util.ServiceLoader, z użyciem której można zaimplementować mechanizm wtyczek. Za przykład posłuży nam aplikacja generująca raporty wspierająca różne formaty danych wyjściowych.

Każdy generator raportów musi implementować odpowiedni interfejs:

package com.mbialon.rg;

public interface ReportGenerator {
  String format();
  void generate();
}

W podstawowej wersji aplikacji możemy dostarczyć tylko raport generujący wyjście w formacie HTML.

package com.mbialon.rg;

public class HtmlReportGenerator implements ReportGenerator {
  public String format() {
    return "html";
  }

  public void generate() {
    // Html report generation
  }
}

Aby skorzystać z możliwości dostarczanych przez java.util.ServiceLoader musimy w katalogu META-INF/services archiwum jar umieścić plik o nazwie odpowiadającej ładowanej usłudze (w moim przypadku to pełna ścieżka do interfejsu generatora raportów), który zawierał będzie ścieżki do klas implementujących ładowane usługi (w moim przypadku będzie to ścieżka do generatora HTML). Treść pliku META-INF/services/com.mbialon.rg.ReportGenerator to tylko jedna linia:

com.mbialon.rg.HtmlReportGenerator

Z przygotowanej zgodnie z powyższym opisem implementacji możemy skorzystać w aplikacji klienckiej.

package com.mbialon.rg;

import java.util.*;

public class Client {
  public static void main(String[] args) {
    ServiceLoader<ReportGenerator> providers = ServiceLoader.load(ReportGenerator.class);

    List<String> availableFormats = new ArrayList<String>();
    for (ReportGenerator generator : providers) {
      availableFormats.add(generator.format());
    }

    // user can select format from available options
    String selectedFormat;

    ReportGenerator selectedGenerator;
    for (ReportGenerator generator : providers) {
      if (selectedFormat.equals(generator.format()))
        selectedGenerator = generator;
    }
  }
}

Po załadowaniu dostępnych generatorów raportów w aplikacji klienckiej możemy odczytać listę dostępnych formatów oraz możemy wybrać odpowiedni generator zgodnie z wybranym przez użytkownika formatem raportu. Stworzoną w ten sposób aplikację kliencką możemy rozszerzać o nowe formaty raportów dostarczając kolejne biblioteki bez konieczności rekompilacji aplikacji klienckiej. Każda z tych bibliotek musi zawierać implementacje generatorów oraz plik META-INF/services/com.mbialon.rg.ReportGenerator zawierający ścieżki do tych klas.

W weekend trafiłem na całkiem dobry opis użycia tagów z JSP 2.0. Tagi w tej wersji pozwalają w łatwy i przyjemny sposób upraszczać kod źródłowy widoku.

Próbowałem uruchomić jeden z pierwszych przykładów, operujący na danych zawartych wewnątrz taga:

<jsp:doBody var="theBody" />
<% String bc = (String) pageContext.getAttribute("theBody"); %>
<%= bc.toUpperCase() %>

Niestety próba kompilacji strony używającej taga się nie powiodła.

SEVERE: Servlet.service() for servlet jsp threw exception
org.apache.jasper.JasperException: Unable to compile class for JSP:

An error occurred at line: 3 in the jsp file: /WEB-INF/tags/bar.tag
pageContext cannot be resolved
1: <jsp:doBody var="theBody" scope="page" />
2:
3: <% String theBody = (String) pageContext.getAttribute("theBody"); %>
4: <%= theBody %>

Szukałem pomocy w internecie jednak nie znalazlem żadnej interesującej wskazówki. Zajrzałem więc do implementacji taga wygenerowanej przez serwer aplikacji i coś przykuło moją uwagę.

public void doTag() throws JspException, IOException {
  PageContext _jspx_page_context = (PageContext) jspContext;
  // ...
  _jspx_page_context.setAttribute("theBody", _jspx_sout.toString(), PageContext.PAGE_SCOPE);
  // ...
  String theBody = (String) pageContext.getAttribute("theBody");
  // ...
}

Zgodnie z komunikatem błędu nie ma tam dostępu do zmiennej pageContext jednak istnieje jspContext, która jest rzutowana do typu PageContext. Podmiana zmiennej w kodzie źródłowym taga spowodowała, że tag się skompilował i wszystko zadziałało. Ostatecznie znalazłem potwierdzenie mojego domysłu w tym artykule jednak nadal nie wiem skąd ta róźnica w nazewnictwie wynika. W związku z tym, poprawna implementacja taga powinna wyglądać następująco:

<jsp:doBody var="theBody" scope="page" />
<% String theBody = (String) jspContext.getAttribute("theBody"); %>
<%= theBody %>

Tydzień temu w piątek poprowadziłem pierwsze w moim zespole (ale także w mojej karierze) Coding Dojo, którego tematem było Bowling Kata. Spotkaliśmy się w 4 osoby na ostatnie 2,5h piątkowego popołudnia.

Stanowisko, zorganizowane w sali konferencyjnej, składało się z: * laptopa, * projektora, * zewnętrznej klawiatury i myszki.

Spotkanie miało na celu zapoznanie kolegów z samą ideą Coding Dojo oraz praktyczne wykorzystanie TDD. W związku z faktem, że jesteśmy bardzo początkujący w tym temacie, nie udało nam się osiągnąć głównego zamysłu tego rodzaju spotkań - wykorzystania zasad projektowania obiektowego do rozwiązania postawionego problemu. Mam jednak nadzieję, że w miarę kolejnych spotkań uda nam się ten element układanki poprawić.

Pierwsze wrażenia były bardzo pozytywne w związku z czym spotkania zostaną także zorganizowane dla pozostałych kolegów z mojej jednostki organizacyjnej (2 grupy po 4 osoby). Przeprowadzę z nimi spotkania na ten sam temat, co powinno dać mi nowe doświadczenia na przyszłość.

Wnioski

  • musimy zwracać większą uwagę na sposób rozwiązania problemu, najważniejsza jest jakość rozwiązania a nie jego kompleksowość,
  • po pewnym czasie spotkanie stało się troszkę chaotyczne, każdy kto miał jakiś pomysł tworzył test zaś inna osoba starała się go spełnić; podczas kolejnych spotkań muszę położyć większy nacisk na kolejność oraz długość okienek czasowych,
  • piątkowe popołudnie to nie jest najlepsza pora, zmęczenie po całym tygodniu pracy negatywnie wpływa na wydajność,
  • 2,5h w zupełności nam wystarczyło, będę się jednak zastanawiał nad zmianą długości spotkania (do 2h lub 1,5h) w zależności od tematu spotkania,
  • klawiatura laptopa może być niewygodna, dlatego następnym razem muszę przygotować dwa stanowiska z normalną klawiaturą i myszką.

Funkcja extend rozszerza lub nadpisuje domyślne opcje wtyczki.

jQuery.fn.foo = function(options) {
  var defaults = {
    length: 300,
    index: 2,
    text: "more"
  };
  var options = $.extend(defaults, options);
  var txt = "length: " + options['length'] + "\n";
  txt += "index: " + options['index'] + "\n";
  txt += "text: " + options['text'] + "\n";
  txt += "other: " + options['other'];
  alert(txt);
};

http://blog.jeremymartin.name/2008/02/building-your-first-jquery-plugin-that.html

Często spotykam się z kodem źródłowym, w którym klasy służą tylko do opakowania wielu zmiennych w celu zwrócenia wyniku funkcji. Typy nie powinny być kubełkami wartości tylko odzwierciedleniem idei i zamysłów programisty. Jakiś czas temu nie łatwo było mi przekonać znajomego dlaczego stworzyłem osobny typ reprezentujący język aplikacji zamiast wykorzystania zmiennej typu znakowego.

class Language {
  private String languageCode;
}

Ostatnio jednak wpadłem na jeszcze lepszy przykład wprost z aplikacji, nad którą aktualnie pracujemy. Główna ideą aplikacji CMS jest zarządzanie stronami i sekcjami, w których strony są umieszczane. Każda strona posiada swój unikalny adres.

class Page {
  String getUrl() {}
}

Powiedzmy, że nie jest to takie tragiczne rozwiązanie ale tylko do momentu kiedy zechcemy dodawać i usuwać wersję językową do adresu. W takim wypadku musielibyśmy dodać dodatkowe metody do klasy strony.

class Page {
  String getUrl() {}
  String getUrlWithoutLangVersion() {}
  String getUrlWithLangVersion(UserSession session) {}
}

Co jednak jeżeli chcielibyśmy wykonać jaką operację na samym tylko adresie np. pobranie nazwy strony albo wersji językowej? Zawsze możemy zastosować klasy pomocnicze.

class Page {
  String getUrl() {}
}

class PageUrlHelpers {
  static String getUrlWithoutLangVersion(String url) {}
  static String getUrlWithLangVersion(String url, UserSession session) {}
}

O ile taka implementacja pozwoli nam osiągnąć zamierzony cel, o tyle nie ma ona prawie nic wspólnego z programowaniem zorientowanym obiektowo. Dobry rozwiązaniem byłoby stworzenie osobnego typu reprezentującego adres strony. Przeniesienie logiki operacji na adresie do osobnej klasy pozwala nam używać tego typu w klasie strony ale także niezależnie jeżeli potrzebujemy operować na samym tylko adresie.

class PageUrl {
  PageUrl(String pageUrl) {}
  String toString() {}
  String getUrlWithoutLangVersion() {}
  String getUrlWithLangVersion(UserSession session) {}
}

class Page {
  PageUrl getUrl() {}
}

Co z tych rozważań wynika? Oczywiście nic nie stoi na przeszkodzie aby stosować styl proceduralny w języku zorientowanym obiektowo. Jednak tracimy wtedy wszystkie zalety naszego narzędzia, płynąć pod prąd wyrządzamy sobie sami szkodę. Problemy nie pojawią się na początku projektu kiedy złożoność jest niska. Dadzą się we znaki kiedy entropia odpowiednio wzrośnie. Dlatego trzeba złożoność systemu rozbijać na małe moduły, które wstydliwie ukrywają przed światem szczegóły ze swojej prywatności.

Okay, here’s what you do to get tab completion working in Windows. Download this. A zip with two files inside. These get copied into your Ruby installation. Place readline.dll in the bin folder. The readline.so goes in lib/ruby/1.8/i386-mswin32 folder.

Then, run in your command shell: irb --readline -r irb/completion.

http://poignantguide.net/ruby/expansion-pak-1.html