Sunday, August 26, 2007

Letter to my employer

To Whom It May Concern:

This company’s so-called “system” is in an irreparable state.
The how and when of this atrocity’s collapse needs to be
addressed.
Replacement of our current system with foreign methodologies
will only become a determent to the process and speed its inevitable demise.

I place no specific blame on those whose ignorance may have
caused this lack of design, and no amount of meetings and complaining amongst
the IS department will be anything but counter-productive towards the goal of
replacing this system.

In order to save this company, one of two things must occur:

1)Ignore the problems. Let the existing system remain and work with it as long as
possible and wait for all things to grind to a halt. Then move on to step 2.

2) Shut down the plant for a given period, and design a new system from scratch.
Decide on a single, standardized, and strictly enforced
set of processes and methodologies, construct a new system around it, and
“re-boot” the plant with this new system.


Neither of these options sounds in any way conceivable to
anyone with a business-oriented mind, but I honesty think that the former will
occur if nothing is done.

I realize that hearing something like this from someone in
my position may even be considered “crossing the line,” but you must believe
that I only have the best interest of the company in mind.

I could provide you with several examples to prove the above
claims, and even if you were to refuse all possibility of such a dramatic
change, I still want you to be aware of what I believe to be the inevitable.

I want this company to succeed just as much as anyone, and I
believe that in order for that to happen, I must express my fears and concerns
now. If you would like to meet in private about these concerns, I would be more
than happy to elaborate on what I have stated here.

Sincerely,
nibbles&bits

Thursday, August 23, 2007

Object-Oriented Objectivism

A whole collection of blogs have made their statements against Object-Oriented programming.

I say one thing to all of you: It's all about who you are. In my opinion, developers, more than anyone else, reflect their personalities in their work. For example, I'm a very visual person; I always, always, always build my interface first. Now of course like any well designed software it changes over time, but for me, having an interface to go by reminds me of what the goal is--user satisfaction. Which is why I'm so addicted to OO:

Users, no matter how tech-savvy, think in nouns and verbs: "I click the button, I get a report.", "My document must be saved." Even developers, despite their own development practices, if they use an IDE, write code with objects in mind: "I submit a build, which has bugs, that are fixed."

Why should this not be reflected in our code? I was recently tasked with the creation of a simple utility for "admin" users to submit Software Development/Change Requests:

public partial class frmSubmit : WinForms.Form
{
SDCR thisSDCR;

public frmSubmit()
{
InitializeComponent();

thisSDCR = new SDCR(SubmitSDCR.Properties.Settings.Default.Server, Properties.Settings.Default.Database);

lblRequestNo.Text = thisSDCR.RequestNo.ToString();
FillReasonList();

if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
this.Text += " v" + System.Deployment.Application.ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();

#if DEBUG
txtRequestor.Text = "Test";
pthExecPath.Text = @"\\mfgvolumes\GDrive\SOFTWARE\ClickOnce\Install\SubmitSDCR\SDCR_Rev 2.xls";
txtRequestDesc.Text = "Request";
lstReasons.SelectedIndices.Add(0);
lstReasons.SelectedIndices.Add(3);
#endif
this.ActiveControl = txtRequestor;
}

private void ClickSubmit(object sender, EventArgs e)
{
if (!ValidateInput()) return;
Submit();
Print();
DisplayInfoBox("Sumitted SDCR", "Your SDCR has been submitted!\n\rCheck your printer for a hard copy for your records.");
ExitApplication(this, new EventArgs());
}

private void FillReasonList()
{
foreach (ChangeReason c in ReasonCollection.GetPossible(SubmitSDCR.Properties.Settings.Default.Server, Properties.Settings.Default.Database))
{
lstReasons.Items.Add(c);
}
}
private void Submit()
{
thisSDCR.EmergencyRequest = chkEmergency.Checked;
thisSDCR.InScope = chkInScope.Checked;
thisSDCR.Requestor = txtRequestor.Text;
thisSDCR.RequestDate = dtpRequestDate.Value;
thisSDCR.ExecutablePath = pthExecPath.Text;
thisSDCR.DescOfRequest = txtRequestDesc.Text;
thisSDCR.DescOfReason = chkOther.Checked ? txtReasonDesc.Text : string.Empty;
int length = lstReasons.SelectedItems.Count;
for (int i = 0; i < valid =" true;" valid =" false;" valid =" false;" valid =" false;"> 0) return true;
if (lstReasons.SelectedItems.Count > 0) return true;
Globals.DisplayInfoBox("Invalid Input", "You must select aReason for Change, or specify a reason in the Description box. Check the form and try again.");
return false;
}

private void chkOther_CheckedChanged(object sender, EventArgs e)
{
txtReasonDesc.Enabled = chkOther.Checked;
lstReasons.Enabled = !chkOther.Checked;
if (!chkOther.Checked)
{
txtReasonDesc.Clear();
this.ActiveControl = lstReasons;
}
else
this.ActiveControl = txtReasonDesc;
}
private void DisableReasonList(object sender, EventArgs e)
{
if (!lstReasons.Enabled)
lstReasons.SelectedIndex = -1;
}
private void ExitApplication(object sender, EventArgs e)
{
this.Close();
}
}


To me, as long as the underlying objects work, and return the data I expect, I could care less about how nested the inheritance hierarchy is. So SDCR inherits DataAccessObject, which inherits DataConnectionObject, which contains a Dataset, which contains a DataTableCollection, which contains a DataTable, which contains a DataRowCollection, which contains a DataRow, which contains an array of objects, which is where my Request Number is stored.
I could either create my own implementation of all of this every time I write a new app, or I could just build an object called SDCR, set it's RequestNo, Name, and Date property can call it's Submit() method, and be done with it.

To me, OO = Reusable. A DLL full of useful common functions is one thing, an object full of ready-made access to a database with a simple "new SDCR("bob","change").Submit()" is a whole other world of usefulness.

Tuesday, August 21, 2007

Threading adventures update

So after speaking with the resident multi-threading guru, I came to the conclusion that, albeit an obvious one, still disappoints me.

See, the problem with my model was that I was trying to "push" the actions in the events onto the form instead of "pulling" the data in and forgetting about it. So unfortunately,

public frmTestBed(NitonXL800 gun)
{
InitializeComponent();

if (gun != null) tester = gun;
else tester = new NitonXL800();

tester.DataReceived += new ComDeviceDataReceivedEventHandler(tester_DataReceived);
tester.PortClosed += delegate(object sender, EventArgs e) { StopProgress(); };
}

void tester_DataReceived(object sender, ComDeviceEventArgs e)
{
txtOutput.Text = tester.Buffer;
}


Is completely out of the question, and must be replaced with:

public frmTestBed(NitonXL800 gun)
{
InitializeComponent();

if (gun != null) tester = gun;
else tester = new NitonXL800();

tester.DataReceived += new ComDeviceDataReceivedEventHandler(tester_DataReceived);
}

void tester_DataReceived(object sender, ComDeviceEventArgs e)
{
GetData updater = delegate(string data) { txtOutput.Text = data; StopProgress(); };
txtOutput.BeginInvoke(updater, e.DataRecieved);

}

My hope with this whole thing was to have the NitonXL800 object do all the marshaling for the developer, allowing the first solution. The problem he helped me realize was that "tester_DataRecieved" will always exist in a separate thread since it actually exists inside "tester". So again, getting the data from the thread is easy, just have BeginInvoke do the marshaling, but the simple truth is that it's just not "nice" to manipulate the form from the child thread, even though it is essentially owned by the form's thread.

But really, this whole problem was nothing but a design issue: Why would you want some random class modifying your form, anyway, even if it does exist in your thread? That's like my form knowing what the Baud Rate of my serial port is!

Now how exactly BeginInvoke pulls off the execution of StopProgress would definitely be an interesting conversation...

...in a galaxy far, far away...

My adventures in .NET land have brought me to an interesting cross-roads.
See, most of the actual code modification I do in any environment is refactoring and re-architecture of existing assemblies; my roots in OO leave me in a moral dilemma every time i see something like:
Public Function GetProperty(Optional propName As String = "Any", _
Optional vIndex As Long = -1, _
Optional vType As PropertyType = MI_Value) As String()
Dim I As Integer
Dim j As Integer
Dim Temp() As String
On Error GoTo GET_PROP_Error
ReDim Temp(0) As String
Temp(0) = ""
ErrorState = 0
'check to see if a string or an index has been passed.
If Not propName = "Any" And vIndex = -1 Then
j = 0
For I = 1 To Properties.Count
If UCase(Properties.Item(I).Key) = UCase(propName) Then
j = j + 1
ReDim Preserve Temp(j) As String
If vType = MI_Key Then
Temp(j - 1) = Properties.Item(I).Key
ElseIf vType = MI_Value Then
Temp(j - 1) = Properties.Item(I).Value
ElseIf vType = MI_Both Then
j = j + 1
ReDim Preserve Temp(j) As String
Temp(j - 2) = Properties.Item(I).Key
Temp(j - 1) = Properties.Item(I).Value
End If
End If
Next I
If (j > 0) Then
ReDim Preserve Temp(j - 1)
End If
GetProperty = Temp
ElseIf Not vIndex = -1 And propName = "Any" Then
On Error GoTo GET_PROP_BY_INDEX_Error
ReDim Temp(0) As String
If vType = MI_Key Then
Temp(0) = Properties.Item(vIndex).Key
ElseIf vType = MI_Value Then
Temp(0) = Properties.Item(vIndex).Value
ElseIf vType = MI_Both Then
ReDim Preserve Temp(1) As String
Temp(0) = Properties.Item(vIndex).Key
Temp(1) = Properties.Item(vIndex).Value
End If
GetProperty = Temp
Else
For I = 1 To Properties.Count
If UCase(Properties.Item(I).Key) = UCase(propName) Then
If j = vIndex Then
ReDim Temp(0) As String
If vType = MI_Key Then
Temp(0) = Properties.Item(I).Key
ElseIf vType = MI_Value Then
Temp(0) = Properties.Item(I).Value
ElseIf vType = MI_Both Then
ReDim Preserve Temp(1) As String
Temp(0) = Properties.Item(I).Key
Temp(1) = Properties.Item(I).Value
End If
GetProperty = Temp
Exit Function
Else
j = j + 1
End If
End If
Next I
ErrorState = -10 'item not found in collection
GetProperty = Null
End If
If Temp(0) = "" Then
ErrorState = -10
GetProperty = Temp
Else
ErrorState = 0
End If
Exit Function

GET_PROP_BY_INDEX_Error:
ErrorState = -10 'item not found in collection
Exit Function

GET_PROP_Error:
ErrorState = -9 'Error accessing collection during search

End Function;

It makes me cringe.
Now granted, the above excerpt is (obviously) VB6, which warrants a whole host of implicit, and often required, architecture problems, but I nonetheless develop a certain pang upon sight of such atrocities.

But recently have have run into an issue in my own little framework, something I've codenamed "Project Cloud". It's a base framework for the future implementation of a new ERP system at my company. If all goes well, I will be pitching the idea to the corporate office, whom for whatever reason has chosen our particular division as the source of the next globally unified system, which they have been calling "AQCS".

The dilemma at hand lies in my implementation of event-base asynchronous IO through a serial port. The design consists of a hierarchy of 3 classes:

HardwareDevice - This simply handles the relevant information about the device being communicated with. Things like manufacturer name and model number are stored here (mostly just for better exception information).
ComDevice : HardwareDevice, System.ComponentModel.ISynchronizeInvoke - Though the name suggests something entirely different, this is a device which communicates though a "COM", or Serial port. "COM", of course, comes from the naming scheme of the ports themselves - "COM1", "COM2", etc.
NitonXL800 : ComDevice - This class, as the name suggests, is specific to a single device, it's constructors fill HardwareDevice with the relevant info, as well as provide ComDevice with port setup options.

The actual implementation of the classes is quite simple:


public abstract class HardwareDevice
{
private string name;
private string manufacturer;

public HardwareDevice()
: this("Unknown Device", "Unknown Manufacturer") { }

public HardwareDevice(string name)
: this(name, "Unknown Manufacturer") { }
public HardwareDevice(string name, string manufacturer)
{
this.name = name;
this.manufacturer = manufacturer;
}

public string Manufacturer
{
get { return manufacturer; }
set { manufacturer = value; }
}

public string Name
{
get { return name; }
set { name = value; }
}

}
}

public class ComDevice : HardwareDevice
{
#region Fields
private SerialPort prt;
private StringBuilder buffer = new StringBuilder();
private bool closeOnRecieve = true;
#endregion
#region Constructors
protected ComDevice()
: this(string.Empty) { }
protected ComDevice(string name)
: this(name, string.Empty) { }
protected ComDevice(string name, string manufacturer)
: this(name, manufacturer, "COM1") { }
protected ComDevice(string name, string manufacturer, string portName)
: base(name, manufacturer)
{
prt = GetDefaultSetup(portName);
prt.DataReceived += new SerialDataReceivedEventHandler(prt_DataReceived);
}
#endregion
#region Util
protected void OpenPort()
{
OpenPort(true);
}
protected void OpenPort(bool close)
{
prt.Open();
OnPortOpened(new EventArgs());
}
protected void ClosePort()
{
prt.Close();
OnPortClosed(new EventArgs());
}
protected void ClearBuffer()
{
buffer = new StringBuilder();
}
public static SerialPort GetDefaultSetup(string port)
{
return new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
}
#endregion
#region Event Handler Pairs
private void prt_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
OnDataReceived(e);
}
protected virtual void OnDataReceived(SerialDataReceivedEventArgs e)
{
string buf = prt.ReadExisting();
buffer.Append(buf);
if (DataReceived != null)
DataReceived(this, new ComDeviceEventArgs(buf));

if (closeOnRecieve) ClosePort();

}
private void OnPortOpened(EventArgs e)
{
if (PortOpened != null)
PortOpened(this, e);
}
private void OnPortClosed(EventArgs e)
{
if (PortClosed != null)
PortClosed(this, e);
}
#endregion
#region Properties
protected string Buffer
{ get { return buffer.ToString(); } }
protected int BaudRate
{
get { return prt.BaudRate; }
set { prt.BaudRate = value; }
}
//etc...
protected StopBits StopBits
{
get { return prt.StopBits; }
set { prt.StopBits = value; }
}
#endregion
#region Events
protected event ComDeviceDataReceivedEventHandler DataReceived;
protected event EventHandler PortClosed;
protected event EventHandler PortOpened;
#endregion
}
#region Event Stuff
public delegate void ComDeviceDataReceivedEventHandler(object sender, ComDeviceEventArgs e);

[System.Diagnostics.DebuggerStepThrough()]
public class ComDeviceEventArgs
{
private string data;
private SerialDataReceivedEventArgs serialData;

public ComDeviceEventArgs()
: this(string.Empty) { }
public ComDeviceEventArgs(string received)
: this(received, null) { }
public ComDeviceEventArgs(SerialDataReceivedEventArgs e)
: this(string.Empty, e) { }
public ComDeviceEventArgs(string received, SerialDataReceivedEventArgs e)
{
if (e != null) serialData = e;
data = received;
}
public string DataRecieved
{
get { return data; }
}
public SerialData EventType
{
get { return serialData.EventType; }
}
}
#endregion

public class NitonXL800 : ComDevice
{
public NitonXL800()
: this("COM1") { }
public NitonXL800(string port)
: base("XL800", "Niton", port)
{
base.Encoding = System.Text.Encoding.ASCII;
base.ReadTimeout = 2000;
base.DataReceived += new ComDeviceDataReceivedEventHandler(NitonXL800_DataReceived);
base.CloseOnRecieve = false;
base.PortClosed += new EventHandler(NitonXL800_PortClosed);
base.PortOpened += new EventHandler(NitonXL800_PortOpened);
}

#region Event Handler Pairs
private void NitonXL800_DataReceived(object sender, ComDeviceEventArgs e)
{
OnDataReceived(e);
}
private void OnDataReceived(ComDeviceEventArgs e)
{
if (DataReceived != null)
DataReceived(this, e);
}
void NitonXL800_PortOpened(object sender, EventArgs e)
{
OnPortOpened(e);
}
private void OnPortOpened(EventArgs e)
{
if (PortOpened != null)
PortOpened(this, e);
}
void NitonXL800_PortClosed(object sender, EventArgs e)
{
OnPortClosed(e);
}
private void OnPortClosed(EventArgs e)
{
if (PortClosed != null)
PortClosed(this, e);
}
#endregion
#region Properties
public new string Buffer
{ get { return base.Buffer; } }
public bool PortOpen
{
get { return base.IsOpen; }
}
public int Timeout
{
get { return base.ReadTimeout; }
set { base.ReadTimeout = value; }
}
#endregion
#region Util
public void Read(bool close)
{
CloseOnRecieve = close;
base.OpenPort();
}
public void Read()
{
Read(true);
}
public void CancelRead()
{
// TDODO: Cancel read
}
#endregion
#region Overrides
public override string ToString()
{
return string.Format("{0} {0} in port {2}", base.Manufacturer, base.Name, base.PortName);
}
#endregion
#region Events
public new event ComDeviceDataReceivedEventHandler DataReceived;
public new event EventHandler PortClosed;
public new event EventHandler PortOpened;
#endregion
}


It's an incomplete implementation to say the least. Criticism aside, my problems arise below when I attempt to post e.DataRecevied to a control.
public partial class frmTestBed : Form
{
NitonXL800 tester;

public frmTestBed()
: this(null) { }
public frmTestBed(NitonXL800 gun)
{
InitializeComponent();

if (gun != null) tester = gun;
else tester = new NitonXL800();

tester.DataReceived += new ComDeviceDataReceivedEventHandler(tester_DataReceived);
tester.PortClosed += delegate(object sender, EventArgs e) { StopProgress(); };
tester.PortOpened += delegate(object sender, EventArgs e) { StartProgress(); };
}

void tester_DataReceived(object sender, ComDeviceEventArgs e)
{
string received = string.Empty;
GetData updater = delegate(string data) { txtOutput.Text = data; StopProgress(); };
txtOutput.BeginInvoke(updater, e.DataRecieved);
}
private void StartProgress()
{
pgReading.Style = ProgressBarStyle.Marquee;
pgReading.Value = 10;
}
private void StopProgress()
{
pgReading.Style = ProgressBarStyle.Blocks;
pgReading.Value = 0;
}

delegate void GetData(string data);
}

Oddly enough, getting the data to a control is easy, BeginInvoke works like a charm. But there in lies my moral dilemma: I'm an architect; a framework developer; I can't force those who write applications that target my framework to understand asynchronous programming, especially if my own knowledge of it is still not fully developed. Ideally, all any developer would have to do is hook up the DataReceived event of the NitonXL800 class, call Read(), and wait for DataReceived to fire so s/he can drop that info into whatever container requires it. I can't have some random threading exception when they don't use BeginInvoke.
As far as I can tell at the moment, I need some sort of liaison--Something that implements ISynchronizeInvoke that can marshal over the data into the executing thread before the event exits, so that the form below could care less about where the data actually came from.
The reason for this is (at least to me) somewhat interesting. As it turns out, even calls that have nothing to do with the data being retrieved by the event throw exceptions. Of course it's mostly assumption, but I have a sneaking suspicion that it's not the data that is owned by another thread, but the method that is executing in another thread. What this means is that with the design lined out above, I can get the data to the TextBox, but the StopProgress throws an InvalidOperationException since it's being called by the DataReceived event's thread.
After slapping myself in the head for my ignorance of such a simple concept, I determined that the assistance of someone more versed in this than me was required.

...And as soon as I find this person, I'll be sure to post the solution right way...

Friday, August 17, 2007

Hello, World.

main() {
printf("hello, world");
}

main( ) {
extrn a, b, c;
putchar(a); putchar(b); putchar(c); putchar('!*n');
}
a 'hell';
b 'o, w';
c 'orld';

public class HelloWorld
{
public static void main( String[] args )
{
System.out.println( "Hello world" );
}
}

... And my favorite...

namespace HelloWorldApp
{
public class HelloWorld
{
public static void main( String[] args )
{
System.Console.WriteLine("Hello world");
}
}
}

Anyone who can tell me the languages used above gets 10 points.

I'm nibbles&bits. I'm a Business Framework Developer (my own title) and self-professed C# geek. I figured my life was interesting enough to blog about.
As far as I can tell at this point, this blog will consists of mostly rants about work, C# code samples, and general news that happens to catch my interest.
My life is just starting: I'm getting a new car, and I'm 3 months away from being promoted at my job and potentially attending MIT soon after.
All I can say now is check back soon, and enjoy!