Legos for the iPad Generation
2012-02-08
littleBits Founder Ayah Bdeir discusses her opensource library of electronic modules that snap together with tiny magnets for prototyping and play.
Bloomberg
This is awesome.
Why the Mythbusters won't do RFID
2012-02-06
Never Make Counter-Offers
2012-02-06
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.
Bram Cohen
Why would you want to work at ThoughtWorks
2012-01-04
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.
Aaron Erickson
The Innovators
2011-11-17
Zabawę czas zacząć
2011-03-08
Konwersja czasu do liczby sekund w Excelu
2011-01-25
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
Weryfikacja na etapie kompilacji nazw właściwości wykorzystywanych w Windows Forms Data Binding
2010-12-23
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);
Tworzenie aplikacji Ruby on Rails z użyciem Passenger
2010-10-18
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>
Implementacja wzorca Dekorator w Javie
2009-12-06
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"));
}
}
