This blog entry has a point about inheritance.
I sometimes use inheritance to refactor methods that are copy/paste in objects.
I often end up with Bar1 and Bar2 extends FooAbstract.
With method: Fish FooAbstract.fishing().
But how do I test fishing() method?
Not in FooAbstractTest since Foo is abstract...
I often put tests in Bar1 but if Bar2 changes the default behavior, I won't get a red bar!
Also I can refactor tests in a FooAbstractTest extends TestCase and make
Bar1 et Bar2 extends FooTestAbstract (but I don't like that much...)
I have to think about this a little bit more....
I may give up inheritance to refactor and use delegation instead...
25 Oct 2004
Keep your old lava lamps
A way for the team (even in remote location) to know about the build status of your continuous builds.
22 Oct 2004
More than just architecture
I found some good points in this interview from Rick Cattell.
Talking about IoC, Ejb etc... is good but the main goal in this job is to deliver something usefull and works (even if it's badly coded, but unit tests help getting that right later)
An other problem (I see this as a really big issue), is engineers knowing best what is good for users more than users themselves...
I mean the only way to tell if a software is really good is to make usability tests whith users and make everyone (developpers included) see the tests ans tests results.
For exemples of technics to achieve usability tests you can refer to Jakob Nielsen's web site.
When talking to normal people, I feel like some crazy scientist no one understands.
Q: If you knew everything then that you know now, what different choices might you have made in your career?
A: (...)I didn't realize how important it was, (...), to work on things that people are actually going to use.(...) if you want to see your ideas used in the real world, you have to think about more than just the engineering.
Talking about IoC, Ejb etc... is good but the main goal in this job is to deliver something usefull and works (even if it's badly coded, but unit tests help getting that right later)
An other problem (I see this as a really big issue), is engineers knowing best what is good for users more than users themselves...
I mean the only way to tell if a software is really good is to make usability tests whith users and make everyone (developpers included) see the tests ans tests results.
For exemples of technics to achieve usability tests you can refer to Jakob Nielsen's web site.
20 Oct 2004
J2SE 5.0 Name and Version Change
The Sun explanation of the new Java products'naming.
- No more 1.5.0 forget the leading "1." now it's 5.0
- Forget the 2 in J2SDK now it's simply JSDK and J2RE becomes JRE.
- But It seems JEE did not replace J2EE, nor J2SE...
No static author tag in javadoc
These days, I finding the author tag in javadoc more and more useless...
What the point in finding:
Also using @author staticMysteryMan is in total contradiction with XP rule:
What the point in finding:
@author someoneWhoWorkedOnlyFewMonthOnTheProject3YearsAgoUsing Cvs features like $Author$ tag, is far more usefull since it replaces the personne name with the one you use for cvs's commit.
Also using @author staticMysteryMan is in total contradiction with XP rule:
Collective Code Ownership,since people tends to say "It's not mine look it's staticMysteryMan who made it" even if staticMysteryMan only created it 3 years ago and every one in the team refactored it since then...
Action Item
Just to relax... reading comics about entreprise might be a strange way to relax, should consider taking vacation someday ;-)
14 Oct 2004
Integrate often (cvs branch)
Even if I already new that often (or continuous) integration is the key to achieve a zen developper attitude.
I recently descovered that merging branchs in cvs has to be run often to reduce any conflict nigthmare in cvs.
Someone (or better everyone in the team) should make an intermediate-merge during the life time of the branch.
If you don't do that, the branch'team will work on "out of date" sources with bugs that had been corrected on the HEAD chunk long time ago.
The longer you wait for an inter-merge the more you get conflicts and that's not what you want!
I recently descovered that merging branchs in cvs has to be run often to reduce any conflict nigthmare in cvs.
Someone (or better everyone in the team) should make an intermediate-merge during the life time of the branch.
If you don't do that, the branch'team will work on "out of date" sources with bugs that had been corrected on the HEAD chunk long time ago.
The longer you wait for an inter-merge the more you get conflicts and that's not what you want!
13 Oct 2004
RiA Listing at last
At last, I found a listing of the main RiA (Rich Internet Applications) solutions:
http://leepoint.net/notes-java/30GUI/95misc/80gui-generator.html
This server side article is also interesting.
My short list (main challengers) for RiA at the moment is:
http://leepoint.net/notes-java/30GUI/95misc/80gui-generator.html
This server side article is also interesting.
My short list (main challengers) for RiA at the moment is:
- JDNC and web start (Sun)
- AUIML (IBM)
- Xul (Mozilla)
- Xalm (Microsoft)
12 Oct 2004
Database refactoring
I recently studied a database refactoring:
Before refactoring we had a user table like this:
User
UserId(PK) | FisrtName | LastName | LastConnexion | Login | Password
The evolution: 1 user can now have multiple login/password (let's say one login for the official site and one for the administration site)
So the logical database scheme evolution would be:
User
UserId(PK) | FisrtName | LastName
Login
UserId(FK) | Admin(boolean) | LastConnexion | Login | Password
with Login table PK is (UserId + Admin)
So now we have:
User (1 to many) Login
If we focus on the 4 basic sql queries: INSERT, UPDATE, SELECT, DELETE
Before evolution:
Alternative solution:
Replace User Table by a User View with (almost the same data)
DELETE User Table (save data before)
CREATE TABLE NewUser
NewUser
UserId(PK) | Admin(PK) | FisrtName | LastName | LastConnexion | Login | Password
BUT the drawbacks of this technic is that FisrtName and LastName are repeated unnecessarily which can lead to invalid data.
You need to balance time to change code vs (database space lost + risk of invalid data)
Additionnal informations: one good place to start is here: http://www.agiledata.org/
Before refactoring we had a user table like this:
User
UserId(PK) | FisrtName | LastName | LastConnexion | Login | Password
The evolution: 1 user can now have multiple login/password (let's say one login for the official site and one for the administration site)
So the logical database scheme evolution would be:
User
UserId(PK) | FisrtName | LastName
Login
UserId(FK) | Admin(boolean) | LastConnexion | Login | Password
with Login table PK is (UserId + Admin)
So now we have:
User (1 to many) Login
If we focus on the 4 basic sql queries: INSERT, UPDATE, SELECT, DELETE
Before evolution:
INSERT INTO User(UserId, FisrtName, LastName, LastConnexion, Login, Password)
VALUES (value1, value2,....);
UPDATE User
SET LastConnexion = new_value
WHERE UserId = some_value;
SELECT UserId, FisrtName, LastName
FROM User
WHERE Login = some_value;
DELETE FROM UserIf we do the "classical" refactoring we need to modify the existing sql queries (modification are in bold/italic):
WHERE UserId = some_value;
INSERT INTO User(UserId, FisrtName, LastName)
VALUES (value1, value2,....);
INSERT INTO User(UserId, Admin, LastConnexion, Login, Password)
VALUES (value1, 0, value2,....);
UPDATE Login
SET LastConnexion = new_value
WHERE UserId = some_value;
SELECT UserId, FisrtName, LastName
FROM User, Login
WHERE Login = some_value
AND User.UserId = Login.UserId
AND Admin = 0;
DELETE FROM LoginWe can see that this modification create many changes in code.
WHERE UserId = some_value
AND Admin = 0;
DELETE FROM Login
WHERE UserId = some_value
AND Admin = 1;
DELETE FROM User
WHERE UserId = some_value;
Alternative solution:
Replace User Table by a User View with (almost the same data)
DELETE User Table (save data before)
CREATE TABLE NewUser
NewUser
UserId(PK) | Admin(PK) | FisrtName | LastName | LastConnexion | Login | Password
CREATE VIEW User
AS
SELECT (UserId, Admin, FisrtName, LastName, LastConnexion, Login, Password) FROM NewUser
WHERE Admin = 0;
INSERT INTO User(UserId, Admin, FisrtName, LastName, LastConnexion, Login, Password)
VALUES (value1, 0, value2,....);
UPDATE User
SET LastConnexion = new_value
WHERE UserId = some_value;
SELECT UserId, FisrtName, LastName
FROM User
WHERE Login = some_value;
DELETE FROM UserYou can see that modifications are reduce in code.
WHERE UserId = some_value
AND Admin = 0; (not sure you need this)
BUT the drawbacks of this technic is that FisrtName and LastName are repeated unnecessarily which can lead to invalid data.
You need to balance time to change code vs (database space lost + risk of invalid data)
Additionnal informations: one good place to start is here: http://www.agiledata.org/
Subscribe to:
Posts (Atom)