Oh, I see. I didn't explain the situation in all his glory. The given project is off-focus for the management, because it is working the way it is. The client bank is trying to cut the cost of the support, and all this sh*t is droping directly over my head. So I try to make all that mess working (and I perfectly know that I am doomed), but I think that it is worthy to share all funny (?) stories of that journey with you, people.
partizanin
@partizanin
Best posts made by partizanin
Latest posts made by partizanin
-
RE: Close encounter
-
RE: Close encounter
Yes, if we never count the effort of the eventual rewrite of the entire package (which is flooded with refernces to these global variables), and the front-end code that uses it... (and the testing effort)
-
Close encounter
I had this close encounter of the third kind some days ago.
The system that our company supports processes applications for micro-credits (among other things). The client bank requested that if the applicant meets some criteria, some checks in the approving process to be skipped. One of the requirements were the pending exposition (the sum of all requested money in the candidate's applications of last seven days, that was not imporved) to be less than 4000 (some currency).
This particular task was an easy one, or so I thinked. There already were a function, which calculated that same pending exposition. This function was in production for years and was proven correct. So I used it. But when the testing team tested the changes, they rejected them, saying that the pending exposition rule does not work.
I was surprised, so I checked the code. The function, contained in a Oracle package, is written by a fellow teammate, let's name her Alice (which, btw, has a pretty high academic degree), and looks something like that:Function CalcPendingExp(aPersonID in applications.person_id%TYPE) return number is
I got the select and ran it, replacing vPersonID with the ID from the test case. It returned a value prety much above the threshold (4000). Then I ran debuger. After execution of the first select, the value of vExp became 0. I was shocked. Then removed nvl. vExp became NULL. Then I ran the select again, replacing vPersonID with the problematic one and replacing nvl and sum with *. The select returned about 10 rows, each with amount > 0. I was shocked again.
vExp number;
begin
select nvl(sum(requested_amount), 0)
into vExp
from applications a
where a.person_id = vPersonID
and a.application_date >= trunc(sysdate, 'DD') - 6
and a.application_status not in (<some status codes>);
-- snip some additional code, which adds to vExp various amounts, stored elsewhere
return vExp;
end CalcPendingExp;
I started to think that maybe the magnetic poles are switching, or the laws of physics had expired, or maybe Oracle database has some very obscure bug, which demonstrates itself in very rare conditions. I spent following 20-30 minutes tweaking the select in the procedure, attempting to achieve something different than 0. Without any success.
Then I incidently noticed, that the argument that I replaced in my tests with a constant value, is called vPersonID, while the argument of the function is called aPersonID. But why this function compiles at all? It turns out, that the value passed to aPersonID is completely ignored and that vPersonID is a global package variable. When I use the function directly it is uninitialized (null), so the select did not find nothing. There is another procedure (GetData), which fills values of all the global package variables (about 30 of them) with the values of a given application.
I have some VERY bitter words to say to Alice, when I see her. -
RE: How much redundant code one can produce in a lifetime (and why)?
@Mo6eB said:
Ivan's code uses variables with normal english names without typos and his comments are also normal english
Ivan's English language skills are quite OK. It's his programming and social skills that need polishing. I wish that it was other way around.
@ubersoldat said:
I really don't like VB in saturdays (or never)
It's actually PowerScript (used in PowerBuilder), which is way more obscure :)
@ubersoldat said:
what is all of this supposed to be doing?
It is supposed to change values of some screen fields according to selected value in another drop-down field.
@ubersoldat said:
affraid of using functions/methods and separation of concerns
I suspect that he is not affraid, he just is huge fan of "lines of code" metric (if it can be metric at all) - he used to praise himself for thousand of lines of code written in a week/month/whatever. And please, don't let me even start on separation of concerns... If soon have more time, I'll post some excerpts which demonstrates Ivan's approach to that.
Cheers.
-
RE: How much redundant code one can produce in a lifetime (and why)?
@Lorne Kates said:
What manner of wizard are you?
Well, thank you for your kind words. I hate reading unidented code (or code published in non-proportional fonts), so I tried my best :)
@Lorne Kates said:
At the very least you can drown your sorrows in a couple big, tall pints of green-tinted whiskey
I most certanly will. Unfortunately, it's not easy to find green whiskey or green ale around here, but we have something called Menta, which will honor st. Patrick as good as whiskey.
@El_Heffe said:
Or he's drunk
Not yet. But soon :)
-
How much redundant code one can produce in a lifetime (and why)?OK, I'm officialy pissed now. Can't even count how much wtf's are there.Below is the code of a event handler in a legacy windows desktop application which I inherited. Keep in mind, that this... WONDER comes from an ex-colleague (let's call him Ivan), who used to be the senior programmer in our small software company. Ivan left several months ago, because he doesn't feel like writing code anymore. He insisted that he was achieved the excelency and that the company must pay him to teach others how to write the perfect code and to guide them. Of course, no one was trying to stop Ivan when he announced his departure.This event handler belongs to a instalment calculator for small personal credits. The whole calculator (by the words of the original "developer") consists of over 20 000 lines of code, and is extremely complicated (who cares about maintenance, anyway :( ). There are many more pearls of WTF, like mixing business calculations with GUI controlling code, calculations with absurd precission, funny error messages etc., but I will keep them for later (when I bump into them again).Wondering why over 20 000 lines of code? That's why:
datawindowchild ldwch_temp long ll_found, i long ThisIsNullLong decimal ThisIsNullDecimal, ldc_pv_prc string ThisIsNullString, ls_pv_type, ls_pv_text, ls_filter decimal {2} ldc_ps_gpr
SetNull(ThisIsNullLong)
SetNull(ThisIsNullDecimal)
SetNull(ThisIsNullString)if ISNULL(al_pay_scheme_id) then
dw_main.SetItem(1, "ps_period", ThisIsNullLong)
dw_main.SetItem(1, "ps_gpr", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gratis", ThisIsNullLong)
dw_main.SetItem(1, "ps_interest", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_pv_type", ThisIsNullString)
dw_main.SetItem(1, "ps_pv_prc", ThisIsNullDecimal)
dw_main.SetItem(1, "pv_text", ThisIsNullString)
dw_main.SetItem(1, "pv_custom", "N")
dw_main.SetItem(1, "pv_client", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gift_beg", ThisIsNullLong)
dw_main.SetItem(1, "ps_gift_end", ThisIsNullLong)
dw_main.SetItem(1, "ps_ins_perc", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_recurrence", ThisIsNullLong)
dw_main.Modify("pv_custom.Visible=0")
dw_main.Modify("pv_client.Visible=0")
dw_fees.Reset()
iuo_pp.iuo_ins.il_pay_scheme_id = al_pay_scheme_id
return TRUE
end ifif dw_main.GetChild("pay_scheme_id", ldwch_temp) = -1 then
dw_main.SetItem(1, "ps_period", ThisIsNullLong)
dw_main.SetItem(1, "ps_gpr", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gratis", ThisIsNullLong)
dw_main.SetItem(1, "ps_interest", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_pv_type", ThisIsNullString)
dw_main.SetItem(1, "ps_pv_prc", ThisIsNullDecimal)
dw_main.SetItem(1, "pv_text", ThisIsNullString)
dw_main.SetItem(1, "pv_custom", "N")
dw_main.SetItem(1, "pv_client", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gift_beg", ThisIsNullLong)
dw_main.SetItem(1, "ps_gift_end", ThisIsNullLong)
dw_main.SetItem(1, "ps_ins_perc", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_recurrence", ThisIsNullLong)
dw_main.Modify("pv_custom.Visible=0")
dw_main.Modify("pv_client.Visible=0")
dw_fees.Reset()
MessageBox(go.m.msg(go.m.ERR), go.m.msg(go.m.DDDW_GETCHILD, go.m.msg(3726)), StopSign!)
return FALSE
end ifll_found = ldwch_temp.Find("pay_scheme_id=" + trim(string(al_pay_scheme_id)), 1, ldwch_temp.RowCount())
if ll_found <= 0 then
dw_main.SetItem(1, "ps_period", ThisIsNullLong)
dw_main.SetItem(1, "ps_gpr", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gratis", ThisIsNullLong)
dw_main.SetItem(1, "ps_interest", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_pv_type", ThisIsNullString)
dw_main.SetItem(1, "ps_pv_prc", ThisIsNullDecimal)
dw_main.SetItem(1, "pv_text", ThisIsNullString)
dw_main.SetItem(1, "pv_custom", "N")
dw_main.SetItem(1, "pv_client", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gift_beg", ThisIsNullLong)
dw_main.SetItem(1, "ps_gift_end", ThisIsNullLong)
dw_main.SetItem(1, "ps_ins_perc", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_recurrence", ThisIsNullLong)
dw_main.Modify("pv_custom.Visible=0")
dw_main.Modify("pv_client.Visible=0")
dw_fees.Reset()
return FALSE
end ifdw_main.SetItem(1, "ps_period", ldwch_temp.GetItemNumber(ll_found, "ps_period"))
dw_main.SetItem(1, "ps_gpr", ldwch_temp.GetItemDecimal(ll_found, "ps_gpr"))
dw_main.SetItem(1, "ps_gratis", ldwch_temp.GetItemNumber(ll_found, "ps_gratis"))
dw_main.SetItem(1, "ps_interest", ldwch_temp.GetItemDecimal(ll_found, "ps_interest"))
ls_pv_type = ldwch_temp.GetItemString(ll_found, "ps_pv_type")
dw_main.SetItem(1, "ps_pv_type", ls_pv_type)
ldc_pv_prc = ldwch_temp.GetItemDecimal(ll_found, "ps_pv_prc")
dw_main.SetItem(1, "ps_pv_prc", ldc_pv_prc)
dw_main.SetItem(1, "ps_gift_beg", ldwch_temp.GetItemDecimal(ll_found, "ps_gift_beg"))
dw_main.SetItem(1, "ps_gift_end", ldwch_temp.GetItemDecimal(ll_found, "ps_gift_end"))
dw_main.SetItem(1, "ps_ins_perc", ldwch_temp.GetItemDecimal(ll_found, "ps_ins_perc"))
dw_main.SetItem(1, "ps_recurrence", ldwch_temp.GetItemNumber(ll_found, "ps_recurrence"))ids_ps_fees.SetFilter("pay_scheme_id=" + trim(string(al_pay_scheme_id)))
ids_ps_fees.Filter()
ls_filter = ""
for i = 1 to ids_ps_fees.RowCount()
if i > 1 then ls_filter = ls_filter + ","
ls_filter = ls_filter + string(ids_ps_fees.GetItemNumber(i, "fee_id"))
next
if ls_filter <> "" then
ls_filter = "fee_id in (" + ls_filter + ")"
else
ls_filter = "0 = 1"
end ifdw_fees.uf_clear_sort()
if dw_fees.uf_Retrieve_ds(gnom.uf_get_ds("fees"), ls_filter) = -1 then
dw_main.SetItem(1, "ps_period", ThisIsNullLong)
dw_main.SetItem(1, "ps_gpr", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gratis", ThisIsNullLong)
dw_main.SetItem(1, "ps_interest", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_pv_type", ThisIsNullString)
dw_main.SetItem(1, "ps_pv_prc", ThisIsNullDecimal)
dw_main.SetItem(1, "pv_text", ThisIsNullString)
dw_main.SetItem(1, "pv_custom", "N")
dw_main.SetItem(1, "pv_client", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gift_beg", ThisIsNullLong)
dw_main.SetItem(1, "ps_gift_end", ThisIsNullLong)
dw_main.SetItem(1, "ps_ins_perc", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_recurrence", ThisIsNullLong)
dw_main.Modify("pv_custom.Visible=0")
dw_main.Modify("pv_client.Visible=0")
dw_fees.Reset()
return FALSE
end iffor i = 1 to dw_fees.RowCount()
ll_found = ids_ps_fees.Find("fee_id=" + string(dw_fees.GetItemNumber(i, "fee_id")), 1, ids_ps_fees.RowCount())
if ll_found > 0 then
dw_fees.SetItem(i, "ps_fee_ord_no", ids_ps_fees.GetItemNumber(ll_found, "ps_fee_ord_no"))
else
dw_fees.SetItem(i, "ps_fee_ord_no", ThisIsNullLong)
end if
next
dw_fees.Sort()
dw_fees.uf_SelectFirst()ua_datastore lds_temp
lds_temp = gnom.uf_get_ds("pv_type")
if not IsValid(lds_temp) then
dw_main.SetItem(1, "ps_period", ThisIsNullLong)
dw_main.SetItem(1, "ps_gpr", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gratis", ThisIsNullLong)
dw_main.SetItem(1, "ps_interest", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_pv_type", ThisIsNullString)
dw_main.SetItem(1, "ps_pv_prc", ThisIsNullDecimal)
dw_main.SetItem(1, "pv_text", ThisIsNullString)
dw_main.SetItem(1, "pv_custom", "N")
dw_main.SetItem(1, "pv_client", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_gift_beg", ThisIsNullLong)
dw_main.SetItem(1, "ps_gift_end", ThisIsNullLong)
dw_main.SetItem(1, "ps_ins_perc", ThisIsNullDecimal)
dw_main.SetItem(1, "ps_recurrence", ThisIsNullLong)
dw_main.Modify("pv_custom.Visible=0")
dw_main.Modify("pv_client.Visible=0")
dw_fees.Reset()
MessageBox(go.m.msg(go.m.ERR), go.m.msg(3727), StopSign!)
return FALSE
end if// Fill PV_TEXT
ll_found = lds_temp.Find("nh_id='" + ls_pv_type + "'", 1, lds_temp.RowCount())
if ll_found <= 0 then
dw_main.SetItem(1, "pv_text", ThisIsNullString)
else
ls_pv_text = lds_temp.GetItemString(ll_found, "nh_name")
if ls_pv_type = "P" then
ls_pv_text = f_str_replace(ls_pv_text, "#%1", string(ldc_pv_prc))
end if
dw_main.SetItem(1, "pv_text", ls_pv_text)
end ifif ls_pv_type = "N" then
dw_main.SetItem(1, "pv_custom", "N")
dw_main.SetItem(1, "pv_client", ThisIsNullDecimal)
dw_main.Modify("pv_custom.Visible=0")
dw_main.Modify("pv_client.Visible=0")
else
if dw_fees.Find("fc_type='O' and fee_apply='P'", 1, dw_fees.RowCount()) > 0 then
dw_main.SetItem(1, "pv_custom", "N")
dw_main.SetItem(1, "pv_client", ThisIsNullDecimal)
dw_main.Modify("pv_custom.Visible=0")
dw_main.Modify("pv_client.Visible=0")
else
ldc_ps_gpr = dw_main.GetItemDecimal(1, "ps_gpr")
if ISNULL(ldc_ps_gpr) then ldc_ps_gpr = 0.00
if ldc_ps_gpr < 0.00 then ldc_ps_gpr = 0.00
if ldc_ps_gpr > 0.00 then
dw_main.SetItem(1, "pv_custom", "N")
dw_main.SetItem(1, "pv_client", ThisIsNullDecimal)
dw_main.Modify("pv_custom.Visible=0")
dw_main.Modify("pv_client.Visible=0")
else
if ab_check_fin_type then // show/hide PV_CUSTOM and PV_CLIENT according to FIN_TYPE_ID
wf_change_fin_type(dw_main.GetItemString(1, "fin_type_id"))
end if
end if
end if
end ifiuo_pp.iuo_ins.il_pay_scheme_id = al_pay_scheme_id
return TRUE