02 December 2009
Avoid Javascript if you can!
Now before you assume that I'm an ignorant wretch who's never really used JavaScript, let me tell you this. I've done a bit of client-side in my time. Including: A Mac OS X widget written with no JS framework, a jQuery plugin for filtering search results (written for and included in jqGrid since 3.5), and lots of custom code for various projects using jQuery or Prototype.
This is what clinched it for me: When I was doing a refactor of a particular piece of my main work project, I decided to fully embrace jQuery and use its UI components, themes, plugins, etc. The long and the short of it is that I will never do this again.
I mean, it's cool that you can create a snazzy jQuery UI widget with a div and a line of javascript, but making that work with your server-side language requires javascript glue. Even with jQuery making things easier, I had to write an inane amount of JS code to glue everything together (check or toggle css classes, setup and handle events like clicking, make ajax requests). My application was a tad complicated, and this was not helped by the fact that I now had to debug both client and server code (and the server code being the much easier part). Sometimes it's fun to make your own glue, but it's a massive expense just to have a pretty client-side control.
The take-away from this is that as an app developer (not a control developer) it's best to avoid using client-side code (Javascript) when possible. I can get around this in ASP .NET for the most part by using pre-made AJAX server controls from the Ajax Control Toolkit, or by using normal server-side controls in UpdatePanels. UpdatePanels potentially add a good bit of overhead, but for internal projects (which is most of what I do) having slightly better performance is not nearly worth the time it takes to make high performance glue.
Well, that's my perspective anyway. ;)
Microsoft showers students with software
- Visual Studio 2008 Pro
- Visual Studio 2005 Pro
- Expression Studio 3
- SQL Server 2008 Developer
- Windows 2008 R2
- Windows 2008
- Windows 2003 R2
- Robotics Developer Studio (Standard I assume?)
- Other free software (Visual Web Dev Express, SQL Express, etc.)
- Media for all of these costs an additional $13.00 per product
- The media is NOT the full retail package
- The media takes a long time to arrive (a month perhaps)
- Windows 7 Pro Upgrade (32 or 64 bit) - $29.99
- You do NOT get both 32 and 64 bit versions. So know what you need beforehand. 32-bit should work for any machine that can run Windows 7. 64-bit is better if you have the hardware for it.
- Office 2007 Ultimate - $59.95
- Visio 2007 Pro - $55.95
- Non-English language packs for Office/Visio - $9.95 each (no media available)
17 November 2009
Business and Data Layers
public class Customer : IInitable // my interface to make an Init method
{
public int customer_id { get; set; }
public string name { get; set; }
public CustomerTypeEnum type { get; set; }
public DateTime since { get; set; }
public List<History> HistoryEntries { get; private set; }
// note absence of constructor... CLR makes a default constructor this way
#region IInitable Members
public void Init()
{
... // set the HistoryEntries with something like this.HistoryEntries = History.Get.ByCustId(this.customer_id);
}
#endregion
public static class Get // nested class to handle fetch operations
{
public static List<Customer> All()
{
DataTable customer_table = DAL.DbName.Customers.Select.All();
List<Customer> ret_val = Converter.Fill<Customer>(customer_table);
return ret_val;
}
}
}
public static void Fill(object obj, DataRow row)When I need to convert a whole DataTable into a list of objects, I wrote another convenience method:
{
// get object's writable properties into dictionary by name
...
// loop through each column of the datarow
...
// if the prop name is the same as the column name
// check/handle: null values, enum types, type conversion
// assign obj to property
}
public static List<T> Fill(DataTable Table) where T: IInitable, new()
{ // where part means that T implements IInitable interface as has a default constructor
List<T> ret_val = new List<T>();
foreach (DataRow row in Table.Rows)
{
T obj = new T();
Fill(obj, row);
obj.Init(); // IInitable defines this method in case the object needs initialization after filling.
ret_val.Add(obj);
}
return ret_val;
}
Not that into NHibernate
- C# Objects
- XML Mappings (something extra to learn)
- Database relations
10 November 2009
ObjectDataSource TypeName and Nested Classes
The type specified in the TypeName property of ObjectDataSource 'myODS' could not be found.
Long story short, the object I was using was actually a nested class. Even though you write you code like this:
MyNamespace.MyClass.NestedClass.Action();
The actual fully qualified type name for an ObjectDataSource TypeName will be "MyNamespace.MyClass+NestedClass" with a SelectMethod of "Action". If you visit this MSDN page and look down to where it talks about delimiters, you will see that nested classes use a plus as a delimiter for some reason instead of the usual dot.
05 October 2009
Crystal Reports 2008 V1 and MySQL
I finally ended up finding this page, and using the JDBC drivers. They aren't perfect, and they are a pain to install (editing config files), but they seem to work better than ODBC. I suppose Crystal just hates MySQL... which is ironic since that's the database they embed in their server product!
Getting Crystal Server 2008 setup... now that's a whole different (and painful) ball of wax. If I had this to do over again, I think I would have evaluated Crystal alongside a solution from Logi first. From the hassle I've had just to get a Crystal Reports Server 2008 solution working (and still not successful so far), I can only imagine it being better with Logi.
17 April 2009
Using Reflection to fill a Business Layer object
Getting tired of endlessly assigning properties for business objects, I decided to try to make life easier on myself. So I developed a handy class, which takes a DataRow and fills a Business Layer object with that data. So now every one of my business object constructors is as simple as this:
public MyItem(DataRow Row)
{
Converter.Fill(this, Row);
}
The class that does all the conversion is as follows:
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
namespace MyNamespace.Data
{
class Converter
{
public static void Fill(object LogicObject, DataRow Row)
{
Dictionary<string, PropertyInfo> props = new Dictionary<string,PropertyInfo>();
foreach (PropertyInfo p in LogicObject.GetType().GetProperties())
props.Add(p.Name, p);
foreach (DataColumn col in Row.Table.Columns)
{
string name = col.ColumnName;
if (Row[name] != DBNull.Value && props.ContainsKey(name))
{
object item = Row[name];
PropertyInfo p = props[name];
if (p.PropertyType != col.DataType)
item = Convert.ChangeType(item, p.PropertyType);
p.SetValue(LogicObject, item, null);
}
}
}
}
}
The full class for MyItem could look something like this:
using System;
using System.Data;
namespace MyNamespace.Data
{
public class MyItem
{
public int item_id { get; set; }
public string item_name { get; set; }
public DateTime item_expiry { get; set; }
public MyItem(DataRow Row)
{
Converter.Fill(this, Row);
}
public static MyItem Select(int item_id)
{
DataRow row;
// code to perform query and get row
...
return new MyItem(row);
}
}
}
In this implementation of Converter, your business object properties have to have the same names as the column names in the database. However, the Converter could be modified to also accept a Dictionary (or array of KeyValuePair) that provides a mapping from database column names to object property names.
26 March 2009
Why no one should ever again use Internet Explorer
Web pages, which by my reckoning are the core use of the Internet, unfortunately don't magically spring up. A person has to create those pages. A person then has to maintain those pages. If a page feature is difficult to get working or is not supported in all browsers, then that feature gets abandoned. Thus, if a browser lags behind, and a lot of people are using that browser, then developers have to forsake features, or worse hack them in, to target the maximum audience.
This brings us to IE, which is by far the furthest behind the curve, both in terms of standards-compliance and features. Take a simple feature like rounded corners, which have been available in other browsers since IE was at version 6. For a developer to add rounded borders in FireFox, Chrome, and Safari is a couple of simple lines of styling. IE 7 and 8 releases passed by without this simple feature, and Microsoft's recommendations (put out in 2005, and sadly still relevant to IE8) on how to emulate this feature all complicate and bloat site design and maintenance.
Some developers will still choose to implement features like this. And as a result, they will spend a chunk of their time implementing and maintaining the hacked-in-for-IE feature rather than developing other features. The end result is that the users of the site lose out. All the time the developer wasted on adding in an IE-specific hack could have been put to a much more constructive use.
So far I've only mentioned absence of features. IE has a number of rendering problems that cause a developer to spend a lot of time trying to get a site to work in IE. All browsers have rendering issues, but IE is the very worst in my experience.
With the recent release of IE8, some of IE's hackiness will supposedly be eliminated, but it is still very far behind in terms of features.
So, from a developer standpoint, IE is severely limiting. Not only does it not have time-saving features that other popular browsers are supporting, but years will pass before they update the browser, and then they don't add much, or even get anywhere close to catching up to the state-of-the-art, from a developer perspective.
The best way for the web to move forward is for IE to be abandoned wholesale by users. Then developers can turn the time they would ordinarily waste hacking things into their code for IE into more time creating, innovating, and improving the web. If users dropped IE en mass, I believe that web developer productivity would increase by no small amount. Which in turn means that the end user has a better experience.
If you use a PC (IE is currently only available on PC), do yourself and the rest of the Internet a favor and use IE only once: to download some other browser. Firefox is probably the most popular. Safari is great if you like simple interfaces. Chrome is currently my favorite and is produced by Google.
27 January 2009
jGrowl
I started developing a web application that needs a sophisticated notification system. It turns out the actual notification message is the easy part since jGrowl does all the work for me.
Here's all you have to do to get jGrowl to work:
Download jGrowl.
Copy the 3 files into your web site directory:
jquery-1.2.6.js (or your newer or minimized version of jQuery)
jquery.jgrowl.js (or the minimized version)
jquery.jgrowl.css
(I put the 2 .js files in /scripts and the .css file in /styles.)
Link to the 3 files like so:
<link href="styles/jquery.jgrowl.css" rel="Stylesheet" type="text/css" />
<script src="scripts/jquery-1.2.6.js" type="text/javascript"></script>
<script src="scripts/jquery.jgrowl.js" type="text/javascript"></script>
Then within any Javascript file, you should be able to call jGrowl:
$.jGrowl("This is a jGrowl notification.");
Also, the notification text was blue for me, which didn't look to good on a black background. I fixed it by adding the following CSS to my main CSS file:
div.jGrowl div.message
{
color: #fff;
}