The problem of butcheries is that people always look for the fastest way to find a solution. Planning, drawing and thinking is expensive. Butchering is not.
The following match summarize the dilemma of the butcher.
Have something working writing one single wrong line of code in the wrong place Vs Have something working redesigning the code (because something was forgotten when the code was designed the first time) to have an elegant and general solution to the problem.
Well you all know who will be the winner of the match in the butcher's mind.
The problem though is more complex than "laziness" the biggest problem is that the butcher often cannot go for the second solution for one of the following two reasons:
1) He's a butcher, butcher he was born and butcher he will always be. Not really gifted form mother nature the butcher understood since his first days the power of conditional instructions.
IF THEN ELSE...mmm...if this is this then this can be like that.....mmmm and if it's different...mmm ELSEIF! The butcher hardly resists IF temptations and ends up solving the 99% of his problems with an IF. The code at the end looks like a labyrinth. His real problem is that he does not understand designs and in his mind most of them are just hard-to-understand-solutions for problems that in his mind would only require two letters. IF.
OOP butchers are easily recognizable cause of the huge size of their classes. The truth is that butchers are nostalgic people who are missing the old PASCAL school. They create a class called MyApplication and put everything within it. Who said OOP was difficult?
2)The butcher is working in a butcher's shop so he has no way out. The code is chopped and minced as dead meat. He usually joined his company in the middle of the Butchers Summer Festival, the applications looks like a Dali's painting and he doesn't know where to start to tidy up the code. Hard to find an escape from such a place, the developer usually ends up sticking with company's polices.
Programming is an art, and noone could recognize a butchery without having been a butcher himself in the old times. The main problem I think is to catch the right problems. The 90% of butcheries born because of people ask the wrong question when they face a problem. When a developer ask himself the wrong question the wrong answer follows. The wrong answer is called CHOP IT. A lot of times I've heard questions "how to do this" where this was generally a particular something to have the application working in the punctual situation. Posing the question at the right level help people to avoid such situation. So my little advice if you feel like you are going to do a butchery is: ask yourself why you need that. Then ask yourself why you need that that needs the butchery and so on. Moving the problem far from the code minimize the risk of an inappropriate solution. This can't apply always of course but I find it useful in a good number of situations. I'll write more on this topic...Bye now.
Thursday, September 20, 2007
Tuesday, September 11, 2007
[VC++] CreateProcess out of Focus - The Mess is on
Problem: After launching an external application using CreateProcess, the application goes out of focus instead of displaying as foreground app as desired.
Resolution: Either the new application is not allowed to set itself as foreground process (so use AllowSetForegroundWindow to solve it) or something in your main app (the one that is launching the external) is setting the focus back to itself after the "slave" app is launched (if your app is big the shit is on).
We obviously talking about "slave" applications that are supposed to display in foreground.
I am trying to get into a new project which is huge and old (VC++6 rocks) and fixing some minor bugs in the meanwhile.
Desired behaviour was the following: Click on a button, a third-party application comes up.
real world behaviour: click on button, app comes up, then it goes out of focus; click again, everything works fine and so on.
In first instance I thought something was happening after the first click, something that was telling the app not to come back on focus from the second click on, maybe a global variable being set as a flag or something like that; but everything in the OnClick handler was fine and the trace of our third-party app having been launched was not being stored anywhere.
void CmyFrm::OnBtnClick()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
memset(&pi, 0, sizeof(pi));
if (!CreateProcess(m_strPath, NULL, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE CREATE_SEPARATE_WOW_VDM, NULL, NULL, &si, &pi))
{
AfxMessageBox("Could not start the application.");
}
else
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
}
As once the application was lanuched that was it, it had to be something in my code that was bringin back my main app on focus. Nasty situation in a huge project you just started working on. Rambling on some forums I made acquaintance with a guy called AllowSetForegroundWindow, a User32.dll function that allows a process to set the foreground window. This should be the default condition, so I wasn't too sure about this, but some buddies on a forum tried to convince me that it must be the reason: my third-party app for some reason didn't have the right to seto the foreground stuff. Let's go for it, I said, but unfortunately I didn't have the last VS6 SDK compatible with Win2K, so I had to dowload it(http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm - how the hell I found this is a mistery, noway to google it) and install it before using the AllowSetForegroundWindow function. Useless to say I lost hours before discovering I could've used that function directly from the dll:
DWORD (WINAPI * AllowSetForegroundWindow)(DWORD pid) = (DWORD(WINAPI*)(DWORD))
GetProcAddress(GetModuleHandle(TEXT("user32.dll")), "AllowSetForegroundWindow");
if(AllowSetForegroundWindow)
AllowSetForegroundWindow(pi.dwProcessId);
Anyway, it didn't solve anything (even if it appears to be a common cause of this kind of behaviour). Every thing was still messed up.
I started roaming through the code and looking for some clue or idea, but nothing. I ended up with the idea that somewhere in the frame or in the mainWindow the focus was being set generating this crappy issue.
I was just banging my head and then it came, out of nothing: I noticed that when the mainwindow was coming back on focus the button just clicked in order to run the other application was no more on focus, another button was instead: the devilish help button.
From that point on it was eventually easy to set up 100 breakpoints (what a mess when I had to take them off - no idea about how to remove all breakpoints in VS6, so if someone knows you're welcome!) on every occurrence of m_HelpButton.SetFocus().
With my surprise the guitly method was the override of the Main Window OnPaint handler, where for some reason the focus was being set on the help button if lost and some other strange duties were being performed (font settings and stuff like that).
void CMainWindow::OnPaint()
{
CPaintDC dc(this); // device context for painting
if(GetFocus() == NULL)
{
if(&m_BtnHelp != NULL)
{
m_BtnHelp.SetFocus();//commeting this line solves the problem
}
}
SetWindowText(m_strVersion);
m_AMember.SetFont(&m_fontAMember);
}
Quoting one of the forum buddies (God bless them) "Messing with the focus in OnPaint is the ultimate stupid thing... The same is to setting there a font to anything. And setting a window text there doesn't look like being smart either. Doing the things where they don't belong must result in hardly predictable behavior. I even don't try to guess why that happens. Or why did that even work." Now, I wouldn't blame the guy who did this, and I cannot complain either, because I do myself shit like that and worse all the time, but I'd sure take a note on this.
Anyway, I solved it (after messing a while with the FindWindow function) with this line:
WaitForSingleObject( pi.hProcess, INFINITE );
inserted before closing the handlers for the new process.
This is basically setting a delay (second parameter) giving time to CreateProcess to do all its stuff (another thing I learned from this is that apparently CreateProcess does a shitload of operations before actually executing your guy). if you set the parameter to INFINITE as I did the function will return only when the application quits. For instance, you could set it to 10000 to give ten seconds to CreateProcess to set up and run what it needs to (one could do the same with Sleep(10000), but then there would be no relation with the process).
Unsolved: the focus was being set on the OnPaint Event Handler, so why the second time you clicked the button it was displaying fine (I can witness the breakpoint was being hit)? No idea.
Resolution: Either the new application is not allowed to set itself as foreground process (so use AllowSetForegroundWindow to solve it) or something in your main app (the one that is launching the external) is setting the focus back to itself after the "slave" app is launched (if your app is big the shit is on).
We obviously talking about "slave" applications that are supposed to display in foreground.
I am trying to get into a new project which is huge and old (VC++6 rocks) and fixing some minor bugs in the meanwhile.
Desired behaviour was the following: Click on a button, a third-party application comes up.
real world behaviour: click on button, app comes up, then it goes out of focus; click again, everything works fine and so on.
In first instance I thought something was happening after the first click, something that was telling the app not to come back on focus from the second click on, maybe a global variable being set as a flag or something like that; but everything in the OnClick handler was fine and the trace of our third-party app having been launched was not being stored anywhere.
void CmyFrm::OnBtnClick()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
memset(&pi, 0, sizeof(pi));
if (!CreateProcess(m_strPath, NULL, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE CREATE_SEPARATE_WOW_VDM, NULL, NULL, &si, &pi))
{
AfxMessageBox("Could not start the application.");
}
else
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
}
As once the application was lanuched that was it, it had to be something in my code that was bringin back my main app on focus. Nasty situation in a huge project you just started working on. Rambling on some forums I made acquaintance with a guy called AllowSetForegroundWindow, a User32.dll function that allows a process to set the foreground window. This should be the default condition, so I wasn't too sure about this, but some buddies on a forum tried to convince me that it must be the reason: my third-party app for some reason didn't have the right to seto the foreground stuff. Let's go for it, I said, but unfortunately I didn't have the last VS6 SDK compatible with Win2K, so I had to dowload it(http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm - how the hell I found this is a mistery, noway to google it) and install it before using the AllowSetForegroundWindow function. Useless to say I lost hours before discovering I could've used that function directly from the dll:
DWORD (WINAPI * AllowSetForegroundWindow)(DWORD pid) = (DWORD(WINAPI*)(DWORD))
GetProcAddress(GetModuleHandle(TEXT("user32.dll")), "AllowSetForegroundWindow");
if(AllowSetForegroundWindow)
AllowSetForegroundWindow(pi.dwProcessId);
Anyway, it didn't solve anything (even if it appears to be a common cause of this kind of behaviour). Every thing was still messed up.
I started roaming through the code and looking for some clue or idea, but nothing. I ended up with the idea that somewhere in the frame or in the mainWindow the focus was being set generating this crappy issue.
I was just banging my head and then it came, out of nothing: I noticed that when the mainwindow was coming back on focus the button just clicked in order to run the other application was no more on focus, another button was instead: the devilish help button.
From that point on it was eventually easy to set up 100 breakpoints (what a mess when I had to take them off - no idea about how to remove all breakpoints in VS6, so if someone knows you're welcome!) on every occurrence of m_HelpButton.SetFocus().
With my surprise the guitly method was the override of the Main Window OnPaint handler, where for some reason the focus was being set on the help button if lost and some other strange duties were being performed (font settings and stuff like that).
void CMainWindow::OnPaint()
{
CPaintDC dc(this); // device context for painting
if(GetFocus() == NULL)
{
if(&m_BtnHelp != NULL)
{
m_BtnHelp.SetFocus();//commeting this line solves the problem
}
}
SetWindowText(m_strVersion);
m_AMember.SetFont(&m_fontAMember);
}
Quoting one of the forum buddies (God bless them) "Messing with the focus in OnPaint is the ultimate stupid thing... The same is to setting there a font to anything. And setting a window text there doesn't look like being smart either. Doing the things where they don't belong must result in hardly predictable behavior. I even don't try to guess why that happens. Or why did that even work." Now, I wouldn't blame the guy who did this, and I cannot complain either, because I do myself shit like that and worse all the time, but I'd sure take a note on this.
Anyway, I solved it (after messing a while with the FindWindow function) with this line:
WaitForSingleObject( pi.hProcess, INFINITE );
inserted before closing the handlers for the new process.
This is basically setting a delay (second parameter) giving time to CreateProcess to do all its stuff (another thing I learned from this is that apparently CreateProcess does a shitload of operations before actually executing your guy). if you set the parameter to INFINITE as I did the function will return only when the application quits. For instance, you could set it to 10000 to give ten seconds to CreateProcess to set up and run what it needs to (one could do the same with Sleep(10000), but then there would be no relation with the process).
Unsolved: the focus was being set on the OnPaint Event Handler, so why the second time you clicked the button it was displaying fine (I can witness the breakpoint was being hit)? No idea.
Monday, September 10, 2007
[Java, Maven, Jetspeed-2] Can't build Jetspeed-2 with maven, settings.xml getting me bored
Problem: Maven2 doesn't build my Jetspeed-2 portal with a strange cast exception
Solution: Check %USERPROFILE%/.m2/settings.xml file position
Solution: Check %USERPROFILE%/.m2/settings.xml file position
My boss went in my office and said "Ok Scuffia, your time has come! With the mighty power of the holy Apache Ant you will package your application, no matter how nor why, but I want a spelled Ant script that builds all your application need to run!" .
First of all my application is composed by:- a Core (a simple Java Library with about 30 classes) that uses 4 other libraries (mainly XML Parsers, loggers, DB accessors)
- A portal container (Jetspeed-2)
- At the moment only one portlet (used to access data)
- A servlet that is an interface between the Core and the Portlet
- A web service (using Axis 1.x) that exports Core methods (in practice the same functionality as the servlet)
There were no problems to rule Ant scripts as to build the Core library (with all depencencies and all needed configuration files, like .properties files); as my application need to be held in one folder, I decided to put together Ant and all source folders.
I also decided to use Maven to build Jetspeed-2 and all portlets, bacause all installation scripts were already done (building, linking, db creating, and resource copying); Maven uses a local repository, in wich it stores downloaded libraries (from servers whose URL are in the configuration file); as my boss needs a completly "offline" installation, all libraries are supposed to be fully downloaded and ready to be linked. Obiously Maven has its configuration file (under ./mavenFolder/conf/settings.xml) in wich you can set the path to the repository: moreover you can choose a configuration different for each user of your OS (Win XP in my case), putting each configuration file inside %USERPROFILE%/.m2/, wich "overwrites" general settings.
Building the portal was as simple as writing:I also decided to use Maven to build Jetspeed-2 and all portlets, bacause all installation scripts were already done (building, linking, db creating, and resource copying); Maven uses a local repository, in wich it stores downloaded libraries (from servers whose URL are in the configuration file); as my boss needs a completly "offline" installation, all libraries are supposed to be fully downloaded and ready to be linked. Obiously Maven has its configuration file (under ./mavenFolder/conf/settings.xml) in wich you can set the path to the repository: moreover you can choose a configuration different for each user of your OS (Win XP in my case), putting each configuration file inside %USERPROFILE%/.m2/, wich "overwrites" general settings.
mvn -P tomcat,min
that stated to build the portal with the underneath web server Tomcat, with just the portal itself and only the administrative portlets (that help administrator to manage users and portlets).
I was so happy that I knew all to do, that I thought to end the work in just 1 working day (inlcuding neverending breaks!)...but It was not so simple!
Each time I tried to build, I got the same error:
D:\GAPWORKSPACE\jetspeed-portal\gapportal\
etc\build.xml:502: java.lang.ClassCast Exception:
org.apache.maven.usability.MojoExecutionExceptionDiagnoser
cannot be cast to
org.apache.maven.usability.diagnostics.ErrorDiagnoser
It lasted for about 3 working days, with my powerlessness: I followed all errors, trying to change code, reading each Maven building script (O.O), when I saw that, as I was using only ./mavenFolder/conf/settings.xml file because I wanted to have the whole stuff inside the same directory and no other file elsewhere, Maven tried to use anyway %USERPROFILE%/.m2/ directory and, only for some libraries, were looking for them in %USERPROFILE%/.m2/repository/, in wich actually there was nothing...
THIS TOOK ME 3 FUCKING DAYS!!!!!
So, although it is not so nice, I decided to have a copy of settings.xml in the user directory, so maven always knows where the repoository is.
And that's the end of my asshole tragedy.
I was so happy that I knew all to do, that I thought to end the work in just 1 working day (inlcuding neverending breaks!)...but It was not so simple!
Each time I tried to build, I got the same error:
D:\GAPWORKSPACE\jetspeed-portal\gapportal\
etc\build.xml:502: java.lang.ClassCast Exception:
org.apache.maven.usability.MojoExecutionExceptionDiagnoser
cannot be cast to
org.apache.maven.usability.diagnostics.ErrorDiagnoser
It lasted for about 3 working days, with my powerlessness: I followed all errors, trying to change code, reading each Maven building script (O.O), when I saw that, as I was using only ./mavenFolder/conf/settings.xml file because I wanted to have the whole stuff inside the same directory and no other file elsewhere, Maven tried to use anyway %USERPROFILE%/.m2/ directory and, only for some libraries, were looking for them in %USERPROFILE%/.m2/repository/, in wich actually there was nothing...
THIS TOOK ME 3 FUCKING DAYS!!!!!
So, although it is not so nice, I decided to have a copy of settings.xml in the user directory, so maven always knows where the repoository is.
And that's the end of my asshole tragedy.
[VC++] Dialog not showing up - ActiveX kicked my butt
Problem: Dialogs/Windows contaning ActiveX controls won't display.
Solution: MSCOMCTL.OCX (or some other OCX library) missing and/or not registered.
I'll tell you in a few a lines about a recent problem I had with ActiveX controls.
An old VC++ 6 software that had always worked before stopped working when we received a new set of dell production machines. No difference at all between new machines and old ones.
The application wasn't crashing but some dialogs were not showing up and I had no idea. The only clue was that the software started working on machines with VC++ 6 (VS6) installed.
After a day spent comparing the system32 directory of the machines and googling like crazy, I decided to start with the first hands-on approach (borrowed from Giulio Concas, a brilliant old teacher o'mine): FLY IN THE NIGHT, AKA "No idea about what to do". Given some similar problems solved this way on some forums I decided to convert the application to the .NET environment (a real pain inthe ass of newer standards compliance) 'cause "maybe this will fix it": Obviously it didn't.
Then I spent some time tracking the dll dependencies with (dependency walker) and went replacing all runtime dlls. Nothing.
Forgot to tell that the new machines were bounded to heavy devices and they didn't have any internet connection. So I couldn't neither debug remotely nor locally (installing VS6 the application would've started working).
The situation was quite desperate given such a silly problem.
After spending several hours trying stupid things and complaining about everything, I was pointed in the right direction on a forum (CodeGuru): when you don't have ActiveX controls registered windows couldn't display properly (or at all) without crashing. The beahviour was the same but I didn't know I had ActiveX controls on the dialogs so I just went back trying everything and hoping in a miracle. After a bit of time I noticed a progress bar I had on a dialog was an ActiveX control (Thought it was just a standard ProgressBar!), so I recalled everything and I was able to pack up and solve the problem.
MSCOMCTL.OCX was missing on the new machines (WinXP SP2, when I say new I mean 2007 stuff): go figure it. Moreover, go figure WHY Microsoft decided to stop shipping this stuff with XP.
This ridiculous mess took 3 working days, and I was just saved by the bell, as usual.
Solution: MSCOMCTL.OCX (or some other OCX library) missing and/or not registered.
I'll tell you in a few a lines about a recent problem I had with ActiveX controls.
An old VC++ 6 software that had always worked before stopped working when we received a new set of dell production machines. No difference at all between new machines and old ones.
The application wasn't crashing but some dialogs were not showing up and I had no idea. The only clue was that the software started working on machines with VC++ 6 (VS6) installed.
After a day spent comparing the system32 directory of the machines and googling like crazy, I decided to start with the first hands-on approach (borrowed from Giulio Concas, a brilliant old teacher o'mine): FLY IN THE NIGHT, AKA "No idea about what to do". Given some similar problems solved this way on some forums I decided to convert the application to the .NET environment (a real pain inthe ass of newer standards compliance) 'cause "maybe this will fix it": Obviously it didn't.
Then I spent some time tracking the dll dependencies with (dependency walker) and went replacing all runtime dlls. Nothing.
Forgot to tell that the new machines were bounded to heavy devices and they didn't have any internet connection. So I couldn't neither debug remotely nor locally (installing VS6 the application would've started working).
The situation was quite desperate given such a silly problem.
After spending several hours trying stupid things and complaining about everything, I was pointed in the right direction on a forum (CodeGuru): when you don't have ActiveX controls registered windows couldn't display properly (or at all) without crashing. The beahviour was the same but I didn't know I had ActiveX controls on the dialogs so I just went back trying everything and hoping in a miracle. After a bit of time I noticed a progress bar I had on a dialog was an ActiveX control (Thought it was just a standard ProgressBar!), so I recalled everything and I was able to pack up and solve the problem.
MSCOMCTL.OCX was missing on the new machines (WinXP SP2, when I say new I mean 2007 stuff): go figure it. Moreover, go figure WHY Microsoft decided to stop shipping this stuff with XP.
This ridiculous mess took 3 working days, and I was just saved by the bell, as usual.
Friday, September 7, 2007
[DISCLAIMER]
Hi,
I am Johnny Idol (AKA Giovacchia) and this is a blog about software development and computing related incredible messes, solved in mysterious ways or not solved at all.
[DISCLAIMER]
In wartime there are no compromises, you gotta be as fast as you can and watch your ass at the same time. Imagine a doctor in the middle of a battle trying to save injured soldiers: is he going to care about the simmetry of the stitches or spend a lot of time on every guy? Maybe he tried once, and one of the guys is now perfectly healthy, but a significant percentage of the others is resting in peace. He learned then that in wartime it can't take too long.
Best practices are what we like to read and speak about, but butchery is what we secretely do.
Gotta go track some bugs,
talk you soon.
I am Johnny Idol (AKA Giovacchia) and this is a blog about software development and computing related incredible messes, solved in mysterious ways or not solved at all.
[DISCLAIMER]
In wartime there are no compromises, you gotta be as fast as you can and watch your ass at the same time. Imagine a doctor in the middle of a battle trying to save injured soldiers: is he going to care about the simmetry of the stitches or spend a lot of time on every guy? Maybe he tried once, and one of the guys is now perfectly healthy, but a significant percentage of the others is resting in peace. He learned then that in wartime it can't take too long.
Best practices are what we like to read and speak about, but butchery is what we secretely do.
Gotta go track some bugs,
talk you soon.
[Java] Welcome to this new incredibly epic blog
Although it is not properly a Java blog I, in the person of Scuffia, will post my own Java defeats!
Moreover I take advantage of this room to thank Giovacchia for this opportunity and I hope to improove my english...that is a very f*****g hard goal!
Goodbye!
Moreover I take advantage of this room to thank Giovacchia for this opportunity and I hope to improove my english...that is a very f*****g hard goal!
Goodbye!
Subscribe to:
Posts (Atom)