fv_2007
I am a no bullshit it consultant with 15 years of experience. I just to be a software architect but now I see myself as a software designer who is cutting unnecessary stuff away and making things happen. I work as a specialist in languages constructs in business like bank/investment/tele. I follow state-of-the-art technologies and principles and I often attending conferences ...
View Frank Vilhelmsen's profile on LinkedIn Recommend Me

Child Care Benefit June 09, 2008 11:52 5 months ago

Jeg har lige modtaget en java kildefil fra en kollega med ca. 300 linjer. Jeg vil ikke vise den fordi den er alt for verbose eller lowlevel. Der er en main metode og et par metoder med noget dato fis. I teorien skulle klassen kunne beregne børneydelse og er en del af en større skattepakke der er baseret på Magnus og kan beregne både skat og budget.

Det var faktisk noget jeg skulle ha brugt min tid på men min kollega kunne bare ikke gøre for det. Opgaven er jo faktisk sjov når man kan de ret enkelte regler som udgør denne ydelse. Og Java klassen regner rent faktisk korrekt.

Det giver til gengæld mig en god mulighed for at abstrahere lidt over noget kode hvilket jeg synes er sjovt. Der hvor kæden hopper af for mig er mængden af kodelinjer brugt på simple konstruktioner. Fint nok, jeg bruger da koden i det forretningsmodul hvori denne funktionalitet skal være men kan ikke lade være at tænke over de implikationer det har på for eksempel drift, vedligehold, videreudvikling osv.

Hvad betyder det når få og ret enkelt regler bliver implementeret og fragmenteret ud i 300 linjer procedural kode? Ja til at starte med er det jo ikke enkelt mere. Jo jeg medgiver at alle os der arbejder professionelt med Java tendere til at gøre alting mere komplekst end det i virkeligheden er. Selv vores projektledere kan ikke genkende selv simple opgave efter vi har fundet en lille variation af et kendt teknisk problem som vi lige skal løse først, alle opgaver ender med at være Java problemer.

Et andet problem er læsbarhed. Kan jeg i det hele taget forstå koden. Kan koden klassificeres efter kravet om beautyful code (en anden post). Nej, allerede efter ca. 40 linjer gider jeg ikke læse mere. Giver det fremtidige problemer? Ja, for reaktionen er jo at jeg selv vil bygge en helt ny udgave når der kommer en mindre tilføjelse.

Beautyful code

Et at de vigtigste objektorienterede principper er genbrug. Men meget få tænker i de baner når de udvikler software. Ofte er undskyldningen at der ikke er tid! Pis, hvis der er tid til dårligt design er der også tid til bedre design.

Hvordan organiseres logiskesammenhørerne sprog konstruktioner? Skal man fokusere på sproget eller på forretningen? Et andet objektorienteret princip omhandler adfærd og måske ville det være nyttigt at bruge de gamle dyder og give objektet mulighed for at løse sine egen opgaver ved at implementer disse egenskaber i klassen selv. Sproget betyder mindre hvis man implementerer efter objektorienteret paradigmer.

Hvis man vil lave god software mener jeg at man må forstå præmisserne om opgaven. En ting som undrede mig var at der i Java koden ikke er brugt datastrukturer til at repræsentere fx, perioder, årgange og kvartaler. Ca. 25% er brugt til simple traversering af dato. Det kan jeg gøre bedre. Faktisk vil jeg definere alle de ting som jeg med sikkerhed ved fra start og binde dem i strukturer.

Et andet sted hvor jeg virkelig kan gøre en forskel er omkring selve algoritmen som beregner de næste 12 måneders børneydelse. Java klassen har defineret 100 linjer til denne metode alene. Først findes de næste 4 kvartaler. Dernæst det ultimative stopkriteriet som er at børneydelsen udløber den dag man fylder 18. Sjovt er det at man begynder først på den 20 i næste kvartal efter fødsel. Til slut er det blot at plukke de respektive beløb.

module Childcontribution

  class Calculate_benefits

    def initialize(child)
      @child  = child
      @petite_18_teen_birthday = Date.new(y=@child.year+18, m=@child.month, d=@child.day)
      @today = Date.today
      periods
      quarters
      ranges
    end

    def payment_next_12_month

      @ydelse = Hash.new(0)
      @quarters.each do |quarter| 
        y = calculate_age(quarter, @child)
        if y == 18
          if birthday_in_last(quarter) 
            @ydelse[quarter] = calculate_speacial_case(quarter) 
          else
            @ydelse[quarter] = 0
          end
        else 
          @ydelse[quarter] = @ranges[y]
        end
      end

      @ydelse.each_pair do |key, value|
        puts "Ydelse pr. #{key} kr. #{value} " 
      end

      amount = 0
      @ydelse.values.collect {|value| amount += value }
      amount
    end

    private

    def birthday_in_last(quarter)
      start = @periods[@periods.rindex(quarter)-1]
      is_birthday_in_last = start < @petite_18_teen_birthday && quarter > @petite_18_teen_birthday
    end

    def calculate_speacial_case(quarter)
      start_date = @periods[@periods.rindex(quarter)-1]
      puts day_pay = @ranges[@ranges.size-1] / 90 # 2515 / 90
      days = @petite_18_teen_birthday - start_date
      day_pay * days
    end

    def calculate_age(quarter, birthday)
      (quarter - birthday).to_i / 365
    end

    def ranges
      @ranges = Hash.new(0)
      (0..2).each  { |n| @ranges[n] = 4039 } # 0-2- Årige 
      (3..6).each  { |n| @ranges[n] = 3198 } # 3-6- Årige 
      (7..17).each { |n| @ranges[n] = 2516 } # 7-17 Årige 
    end

    def periods 
      @periods  = Array.new()
      for y in [2007, 2008, 2009, 2010] 
        for m in [1, 4, 7, 10]
          @periods << Date.new(y=y,m=m,d=20)  
        end
      end
    end

    def quarters
      @quarters = Array.new(0) # Hash.new(0)
      for i in 0...@periods.length
        if @periods[i] > @today
          for n in i...i+=4
            @quarters << @periods[n]
          end
          break
        end
      end
    end

  end
end

child = Date.new(y=1991,m=1,d=1)
calc = Childcontribution::Calculate_benefits.new(child)
puts "Next 12 month #{calc.payment_next_12_month}" 


By Frank Vilhelmsen - 3 tags: blog java ruby - Add comment