Sunday, December 20, 2009

TDD Test Driven Development

Firmy szaleją na punkcie AGILE. W mojej firmie na przykład wprowadzono SCRUMa. Jestem DBA i widzę skutki działania programistów i czas jaki poświęcają na daną funkcjonalność oraz UTRZYMANIE.

  1. Fundamenty projektu. Początkowy etap rozwoju jest "najprostszy". Wszyscy są podekscytowani, programista ma coś nowego i 80% projektu powstaje bardzo szybko.
  2. Dopieszczanie projektu. Mamy fundamenty, wstawione okna i podłączony prąd (nie ma zamontowanych włączników tylko gołe druty), w łazience czeka najlepsze jacuzzi na świecie. Wykończeniowcy mozolnie dopieszczają nowy dom.
  3. Wejście mieszkańców. Horror, w jednym miejscu ktoś zapomniał wstawić włącznika i lokator dotknął dłonią przewodów pod napięciem, część włączników w ogóle nie działa. Okazało się, że rury są nieszczelne i woda wycieka ze ściany a nie leci do jacuzzi. Jesienią i zimą podwórze zamienia się w bagno bo studzienki nie są w stanie odprowadzić wody.
  4. Poprawki. Zrobiliśmy brakujący włącznik skuliśmy ściany i wymieniliśmy nie działającą część instalacji elektrycznej , poszerzyliśmy studzienki kanalizacyjne, nawet uszczelniliśmy rury. Okazało się jednak, że po uszczelnieniu rurociągu trzeba zmienić rury kanalizacyjne bo nie dają rady z odprowadzaniem zużytej wody. Podczas kucia uszkodziliśmy kable ethernetowe i przestał działać internet oraz system alarmowy oraz działająca do tej pory część instalacji elektrycznej. Zleceniodawca zerwał umowę i musimy płacić karę umowną.

Tak dokładnie wyglądają projekty informatyczne w dziewięćdziesięciu procentach wypadków. Na ratunek przyszły zwinne metody prowadzenia projektów. Niestety to nie jest panaceum na problemy. Scrum wymaga dobrych i doświadczonych programistów w projekcie. Programistów umiejących pisać testy.

Bez pisania testów nie da się wykorzystywać Scruma. Na dobrą sprawę młyn bez testów spowalnia tworzenie oprogramowania ponieważ iteracje często wymagają gwałtownych przeróbek i ręczne wyszukiwanie implikacji zmian ( nowych błędów ) to mordęga.

Dobry programista projektuje przed startem implementacji. Implementacje zaczyna od pisania testów. Nie da się przewidzieć wszystkich przypadków ale unika się kompromitujących wpadek.

Scrum jest prosty ale dla doświadczonych programistów.

http://en.wikipedia.org/wiki/Test-driven_development

Friday, December 4, 2009

Django Pisa (polskie czcionki)

I use Pisa to generate reports. I had problem with polish lettersm solution is to replace included fonts (arial, helvetica) with own.
Copy fonts to /project/directory/site_media/font.

#-*- coding: utf-8 -*- 
import cStringIO as StringIO

import ho.pisa as pisa

from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.template import Context
from django.template.loader import get_template
from django.utils.translation import ugettext_lazy as _

from arap.report.models import Review
from arap.report.models import Type
from arap.settings import  MEDIA_ROOT

@login_required
def print_report(request, id):
    """
    Generuje raport z przeglądu.
    """
    template = get_template('report/print.html')
    review = get_object_or_404(Review, id=id)
    context = Context({'pagesize':'A4', 'review':review, 'MEDIA_ROOT':MEDIA_ROOT})
    html  = template.render(context)
    result = StringIO.StringIO()
    pdf = pisa.pisaDocument(StringIO.StringIO(html.encode('UTF-8')), result)
    if not pdf.err:
        response = HttpResponse( result.getvalue() )
        
        response['Content-Type'] = 'application/pdf'
        response['Content-Disposition'] = 'attachment; filename="%s-%s-%s.pdf";' \
            %(review.server,review.report_type, review.created)
        return response
    return HttpResponse(u"Coś nie bangla.", mimetype='text/html')

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<style type="text/css"> 
@font-face {
   font-family: "arial","helvetica","symbol";
   src: url({{ MEDIA_ROOT}}/font/arial.ttf);
}

@font-face {
   font-family: "arial black";
   src: url({{ MEDIA_ROOT}}/font/arialbd.ttf);
}

@font-face {
   font-family: "verdana";
   src: url({{ MEDIA_ROOT}}/font/verdana.ttf);
} 


@font-face {
   font-family: "Times New Roman" ,"wingdings";
   src: url({{ MEDIA_ROOT}}/font/Times_New_Roman.ttf);
}

@font-face {
   font-family: "Comic Sans Ms";
   src: url({{ MEDIA_ROOT}}/font/Comic_Sans_MS.ttf);
}

@page {
  margin: 1cm;
  margin-bottom: 2.5cm;
  @frame footer {
    -pdf-frame-content: footerContent;
    bottom: 2cm;
    margin-left: 1cm;
    margin-right: 1cm;
    height: 1cm;
  }
} 

html, body, table, caption, tbody, tfoot, thead, tr, th, td {
    font-family: "Times New Roman";
}
</style>

<title>Raport {{ review.report_type }} {{ review.server }} {{ review.created }}</title>
</head>
<body> 
  {{ review.report|safe }} 
  <div id="footerContent">
    {%block pager %}
      <pdf:pagenumber>
    {%endblock%}
  </div>
</body>
</html>