I noticed today that my statement about why I had to adopt best practices was very similar in emotional content to this famous moment in American cinema. Please hum the theme music as you read the text:

"As God is my witness, as God is my witness they're not going to lick me. I'm going to live through this and when it's all over, I'll never let a project become a death march again. No, nor any of my folk. If I have to lie, steal, cheat or kill. As God is my witness, I'll never let a project become a death march again..."
That is what she said. Or something very similar, I don't recall correctly.
In any case, today I aggressively used redmine, the open source project management software, to track every activity that I am doing for my current project. This is part of my efforts not to let my current project become a death march.
Redmine was introduced to me by @GeoDAWG. He set it up for the project that I am using and for the another project. If we had actually kept using redmine in the other project, we would have saved ourselves from a lot of grief.
Strengthening a practice that already exists is low hanging fruit, so I am going to go for it.
What has changed right now is that now I have the strong motivation to keep it up to date. So that is what I did today: I updated tickets, wrote new tickets, and added more items and reorganized the wiki for the project.
Before I thought updating tickets was boring; now I think it is boring, but critical.
So I am going to get serious about adopting agile practices.
Since I first read about agile development, a lot of it made sense to me. I attempted to embrace many of its practices. Some have become habits; most of them are still goals.
Since the zombie project, that has changed. Now I know that it is not only something nice to strive for, but that it is necessary, important.
And that is something that one can only earn via experience: to get that full, instant, visceral reaction to something that makes us act.
My favorite analogies to this are economic crises: most people know that they are wrong, and that they should be avoided, but those who can control the economy just don't care as long as they are making money. It is only those who have lived through deep economic crises who know the deep pain, the massive social change, and the lost opportunities that come with them. That is probably why the post-Depression political and business leaders were so careful with the economy; the boomer generation of leaders never really lived through that. But ask a person who lived through the Depression about another one, and they will passionately say that it should be avoided at all costs.
That is how I feel about software development now: crisis projects should be avoided at all costs. And that is what agile practices attempt to prevent or attempt to manage in a rational manner.
So here I go, ready to start embracing agile practices. I will be documenting my experience here. Hopefully it will be done quite regularly since I will attempt to do one action to move towards agile practices every day.
After doing some research, it seems that there is no clear way to unit test asp .net WebForms.
ASP .Net web forms behavior collides with the current testing principles. The big one being that you only test public methods. Well, it seems that most Web Form pages don't have ANY public methods, making it impossible to test following the unit test principle. For those developers that want to do testing, it means that they have to expose the different private methods that they are using as public methods, breaking a big principle in OOD, which is that public methods are the interface to the object. So the developer who wants to unit test their code either breaks the principle of not testing privates or breaks the OOD principle of exposing as little interface as possible.
So the solutions that I have found either involves some complex code bending to allow for the testing of private methods, doing weird practices such as exposing private methods as public.
The other big solution seems to be to move to the MVC framework. Ideal solution for new projects if one has the time to learn the framework, but won't help that much if one has to work with legacy code.
The one idea that popped into my mind as I was writing this is that maybe it is possible to mvc-ize a bit the code. If every interaction of the page has to rely on objects, then we can test those objects. This seems to have some limitation in that separating database interactions may be difficult, impossible, or create greater problems that it attempts to solve. But at least it, if used properly, allow for testing of potentially breakable parts of the code.
I will experiment with this idea and see what happens.
Okay, this is something I was going to blog about a month ago, but then the January storm hit and derailed that.
So, these are the first 22 exercises of the 99 Prolog Problems. I am doing them in Erlang. I know, I know, this is super cryptic by naming the functions after its problem number rather than by nice descriptive problems, but I was taking the easy way out; I just wanted to do them pretty quickly rather than show them off as an exercise on proper programming technique.
For what it is worth, here they are:
-module(p99a).
-export([a1/1, a2/1, a3/2, a4/1, a4b/1, a5/1,
a6/1, a7/1, a7b/1, a8/1, a8b/1, a9/1, a10/1,
a11/1, a12/1, a13/1, a14/1, a15/2,
a16/2, a17/2, a18/3, a19/2, a20/2,
a21/3, a22/2]).%Find the last element of a list.
a1([], Result) -> Result;
a1([H|T], _) -> a1(T,H).a1(List) -> a1(List, "Not a list").
%Find the last but one element of a list.
a2([_|[]], Result) -> Result;
a2([H|T], _) -> a2(T,H).a2(List) -> a2(List, "not a list").
%Find the K'th element
a3([], _, _) -> {error, "out of range"};
a3([H|T], Nth, Index) ->
if Index == Nth -> H;
true -> a3(T, Nth, Index + 1)
end.a3(List, Nth) -> a3(List, Nth, 1).
%Find the number of elements of a list.
a4([], Result) -> Result;
a4([_|T], Result) -> a4(T, Result + 1).a4(L) -> a4(L, 0).
a4b([]) -> 0;
a4b([_|T]) -> a4b(T) + 1.%Reverse a list.
a5([], R) -> R;
a5([H|T], R) -> a5(T, [H|R]).a5(L) -> a5(L, []).
%Find out whether a list is a palindrome.
equal([], []) -> true;
equal([H|T], [H1|T1]) ->
if H == H1 -> equal(T, T1);
true -> false
end.a6(L) -> equal(L, a5(L)).
%Flatten a nested list structure.
% a7 is concat in the O'Reilly Erlang book
% a7b is flatten per se
strip([], R) -> a5(R);
strip([H|T], R) -> strip(T, [H|R]).a7([], R) -> R;
a7([H|T], R) -> a7(T, strip(H, R)).a7(L) -> a7(L, []).
a7b([],R) -> R;
a7b([H|T], R) when is_list(H) -> a7b(T, a7b(H, R));
a7b([H|T], R) -> a7b(T, [H|R]).a7b(L) -> a5(a7b(L, [])).
% Eliminate consecutive duplicates of list elements.
a8([], _, R) -> R;
a8([H|T], P, R) when P == H -> a8(T, P, R);
a8([H|T], P, R) when P /= H -> a8(T, H, [H | R]).a8([H|T]) -> a5(a8(T, H, [H|[]])).
a8b([], _) -> [];
a8b([H|T], P) when P == H -> a8b(T, P);
a8b([H|T], P) when P /= H -> [H|a8b(T, H)].a8b([H|T]) -> [H|a8b(T,H)].
% Pack consecutive duplicates of list elements into sublists.
pack([], _, R) -> [R];
pack([H|T], P, R) when H == P -> pack(T, P, [H|R]);
pack([H|T], _, R) -> [R| a9([H|T], H)].a9([], _) -> [];
a9([H|T], P) when H == P -> pack([H|T], P, []);
a9([H|T], _) -> a9(T, H).a9([H|T]) -> a9([H|T], H).
% Run-length encoding of a list.
a4c(L,[H|_]) -> [a4(L), H].
a10h([]) -> [];
a10h([H|T]) -> [a4c(H,H)| a10h(T)].a10(L) -> a10h(a9(L)).
% Run-length encoding of a list.
a4d(L,[H|_]) ->
X = a4(L),
case X of
1 -> H;
_Other -> [X,H]
end.a11h([]) -> [];
a11h([H|T]) -> [a4d(H,H)| a11h(T)].a11(L) -> a11h(a9(L)).
% Decode a run-length encoded list.
unpack([0,_], R) -> R;
unpack([N,C|_],R) -> unpack([N-1,C], [C|R]).a12([], R) -> R;
a12([H|T], R) when is_list(H) -> a12(T, unpack(H,R));
a12([H|T], R) -> a12(T, [H|R]).a12(L) -> a5(a12(L, [])).
% Run-length encoding of a list (direct solution).
a13([],P,C, R) ->
case C of
1 -> [P|R];
_Other -> [[C,P]|R]
end;
a13([H|T], P, C, R) when H =:= P -> a13(T, P, C+1, R);
a13([H|T], P, C, R) when H =/= P ->
case C of
1 -> a13(T,H,1,[P|R]);
_Other -> a13(T,H,1,[[C,P]|R])
end.a13([H|T]) -> a5(a13([H|T], H, 0, [])).
% Duplicate the elements of a list.
a14([]) -> [];
a14([H|T]) -> [H,H|a14(T)].% https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/
repeat(_,0) -> [];
repeat(C,T) -> [C|repeat(C, T-1)].a15([],_) -> [];
a15([H|T],C) -> a7b([repeat(H,C)|a15(T, C)]).% Drop every N'th element from a list.
a16([], _, _) -> [];
a16([_|T],C,N) when N rem C =:= 0 -> a16(T, C, N+1);
a16([H|T],C,N) -> [H|a16(T,C,N+1)].a16(L,C) -> a16(L,C,1).
% Split a list into two parts; the length of the first part is given.
a17([],_,_,L) -> {a5(L),[]};
a17([H|T],N,R,L) when N =:= R -> {a5([H|L]), a5(T)};
a17([H|T],N,R,L) -> a17(T,N,R+1,[H|L]).a17(L, 0) -> {L, []};
a17(L,N) -> a17(L,N,1,[]).% Extract a slice from a list.
a18([],_,_,_) -> [];
a18([H|T],I,K,N) when N >= I, N =< K -> [H|a18(T,I,K,N+1)];
a18([_|T],I,K,N) -> a18(T,I,K,N+1).a18(L,I,K) ->a18(L,I,K,1).
% Rotate a list N places to the left.
a19(L, N) -> SP = N rem a4(L),
if
SP < 0 -> S = a4(L) + SP;
true -> S = SP
end,
{H, T} = a17(L, S),
a7([T,H]).% Remove the K'th element from a list.
a20([],_,_, L) -> L;
a20([H|T],N,I,L) when N =:= I -> {H, a5(a20(T,N,I+1,L))};
a20([H|T],N,I, L) -> a20(T,N, I+1, [H|L]).a20(L,N) -> a20(L,N,1,[]).
% Insert an element at a given position into a list.
a21([],E,P,N) when P =:= N -> [E];
a21([],_,_,_) -> [];
a21([H|T], E, P, N) when P =:= N -> [E,H| a21(T,E,P,N + 1)];
a21([H|T], E, P, N) -> [H|a21(T, E, P, N+1)].a21(L, E, P) -> a21(L, E, P, 1).
%*) Create a list containing all integers within a given range.
a22(A,B) when A > B -> [];
a22(A,B) -> [A|a22(A+1,B)].
Short
Select COLUMN_NAME from all_tab_columns where table_name=upper('tableName')
Yesterday I had the joy of having the Oracle 11g install majorly mislead me. Even though it couldn't really work on my windows computer due to it having a dhcp ip, the installer gave me a "warning" that got buried in their amazingly small viewing area, and it let me continue the install. Even better, by letting me log into the db in SQL*Plus, it totally faked me out into believing that the installation was successful. It was only when I tried to work with it in .net that i started getting the annoying tns not running error.
So I search for to see what the problem is, and there are tons of posts in the oracle forums on this error, everyone with a different problem and solution. I dutifully try the different solutions, I get it to "work" according to the solutions, i.e, I get the hellish service to actually run, and yet it still won't work in .net.
And this is RIGHT AFTER INSTALLATION, WHEN THE DAMN THING SHOULD WORK.
So I decided to uninstall and install again. While installing again, I noticed that I got "warning" telling me in a weak worded way that stuff may happen in dhcp if I go ahead with the installation. The stupid feedback should read: "It WON'T WORK. Install the freaking Microsoft loopback Adapter First."
Fortunately this actually fixed the problem.
I don't know if Oracle just likes to prank developers, or if this is some kind of hazing to join the Oracle crowd. This error message is so common and is triggered by so many things that the desperate posts of people are received with a massive yawn by the regulars who tell you to search through their archives to find the solution.
And I guess that their ridiculously small viewing windows at the prerequisite check of the installer, which one cannot adjust, is their way of stating to the world that Oracle is a totally back-end development shop? Do they put interns to create the install GUIs?
I am still angry, and the best part of this is that I actually rested and went to sleep before posting this.
You initialize it like this:
var membership = Membership.Providers["orclmembershipProvider"];
var validated = membership.ValidateUser(user, password);
A bit different than MS's provider. The name of the provider that you give is the one that you put in the web.config
Answer:
grant create session to
I had to hunt for this one as well. Maybe the word ACCESS is used for something else.
Answer:
grant unlimited tablespace to
It took me a while to find this. Unfortunately I closed the window too quickly so I cannot give the link to the place where I found this entry.
Hugo