Jeff Atwood published the Programmer Bill Of Rights, which I like.
Of the list, I currently don't have is #3 (mouse & keyboard that I want) and that is because I have a laptop, and I refuse to increase the time it takes to set it up for work.
Jeff Atwood published the Programmer Bill Of Rights, which I like.
Of the list, I currently don't have is #3 (mouse & keyboard that I want) and that is because I have a laptop, and I refuse to increase the time it takes to set it up for work.
This keeps popping up, take a look at the times I have been hitting the snooze button.
And those are just the things that I keep track of in Outlook...
I'm browsing through the Shared Source CLI at the moment, for no good reasons...
I found the following comment in the System.String implementation...
Good to show a sense of humer in the code, I always says.
Did you know that the CLR has a week reference hashtable? (Marked internal, of course, so you will not be able to use that ("Why, you horrible little man, why would you want to use a weak hashtable? Infidel")
You just love Clipboard Inheritance, don't you?
(To be fair, I can't think of another way to do it)
I like this quote too:
Nothing like making a refactoring that goes through 140 compiler errors that I need to handle manually. Right now my least favoriate class in the framework is System.DateTime.
Nothing like adding a forth dimention to your application to make you realize how much you hate time.
On the other hand, I did get to create an OutOfTimeException which are going to provide me with hours of fun...
I was writing a comment and suddenly noticed this, I liked it so much that I had to post about it;
Logging is fairly critical to many applications, and it is especially critical when you are trying to understand in a complex application. I'm using log4net for logging, because it is so simple to start with and it can scale up to very complex needs.
The problem that I had was watching the logs. Specifically, watching the logs run in real time. The application is heavily mutli threaded, and run as a windows service. It is pretty hard to get what is going on there unless you watch the progress of the logs. At first, I simply logged to a file, and read it in notepad. This approach doesn't really scale well.
Next, I tried log4net viewer, which is really simple to get working. Just start the application, and put the following in your log4net config:
<appender name="UdpAppender"
type="log4net.Appender.UdpAppender">
<param name="RemoteAddress"
value="127.0.0.1" />
<param name="RemotePort"
value="8080" />
<layout type="log4net.Layout.XmlLayout">
<param name="Prefix"
value="" />
</layout>
</appender>
Here is what it looks like:
The problem is that it is very simple, and it has several bugs that I couldn't live with (specifically, it doesn't display the information correctly if you are using sorting or filtering).
I then turned to log4j's chainsaw client, which is far more impressive feature wise. This is a java UI client, but it is very sophisticated. Almost to the point of being of no use to me, actually.
First, you need to put this in your log4net config:
<appender name="UdpAppender"
type="log4net.Appender.UdpAppender">
<param name="RemoteAddress"
value="127.0.0.1" />
<param name="RemotePort"
value="8080" />
<layout type="log4net.Layout.XmlLayoutSchemaLog4j, log4net" />
</appender>
Then, create a file called log4net.config.xml with the following content:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration
xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<plugin name="UDPReceiver"
class="org.apache.log4j.net.UDPReceiver">
<param name="Port"
value="8080" />
</plugin>
</log4j:configuration>
On startup, the chainsaw will request a configuration file:
Specify the location of the log4net.config.xml file that you creted previous, select don't show me this again, and click OK.
Then, you get the main UI, you need to click on the chainsawl-log tab:
You should get a screen similar to this:
The part marked in red is the loggers tree, which will become important in just a minute. Right now it displays just chainsaw' own internal logs.
Now, start an application that will log to the UDP Appender, and watch the tree on the right, here is how it looks like after I run a bit of NHibernate's tests:
Right click on the part of the tree that interests you and select focus on '...'
You can double click on the tab header to get the tab in a seperate window (useful for utilizing screen real estate):
Chainsaw how powerful filterring and coloring features, and it is pretty good in allow me to check what my application is doing in real time.
This post hit a really sensitive point with me, Eber is showing some of the more complex forms of generics. Here is how he hold all the files in all the directories in all the computers
Dictionary<string, Dictionary<string, List<string>>> list =
new Dictionary<string, Dictionary<string, List<string>>>();
I can't read code like this. I have a dictionary of a dictoary of a list. That is all fine and dandy, so far. The using code looks like this:
The problem is that without knowing what this mean, I have no idea how to work with this. What is the first string, what is the second one, and what is the third one, for crying out loud?
Code like the above is opaque, is doesn't tell me what it is. A far better alternative would be something likes:
public class Domain
{
public IDictionary<string,Computer> Computers { get; }
}
public class Computer
{
public IDictionary<string, Directory> Directories { get; }
}
public class Directory
{
public IList<string> Files { get; }
}
This is a data structure that has a meaning. The client code looks like this:
Now I can read it without knowing having to know what the original author meant.
Yes, having generics can save us a bit of time in creating a new class, but you should ask yourself if this is worth losing the clarity of the code.
I run into this bit of code today:
public enum OriginalFromMainFrame
{
Ten = 10,
Twelve = 12,
TwentyFive = 25
}
Some certainly heard about good software practices, but there is something left to be desired in the implementation...
The fastest way to get data from the database is not getting it from the database.
I talked about NHibernate's caches in the past, but I was mostly focused on entities and collection caching. Those are fairly easy to grasp. You load an entity once, and the second time, it doesn't get loaded.
Collections are slightly more complicated, since they require you to know what is going on (otherwise, you may get into a bit of problem, like I did), but they really reduce the amount of work the database has to do, since even the links between the objects are cached.
The problem is that very few applications can be structured so you can always ask for an object by its primary key. This brings us to the next (and probably final) cache.
Let us check an example:
session.CreateQuery(typeof(Post))
.Add(Expression.Like("Content", "User",MatchMode.Anywhere))
.List();
This is a fairly expensive query, and it can't make use of the already existing cache. Even though the data may be on the cache already, NHibernate is not going to use the caches for querying, that is what databases are good at, after all. The query about will hit the database each and every time.
What can we do about it? Well, there is always the...
Query Cache
The query cache can hold the results of both types on NHibernate's queries (Criteria queries, and HQL queries)
(Very partial view of those interfaces)
Let us take the above query and add caching to it:
session.CreateQuery(typeof(Post))
.Add(Expression.Like("Content", "User",MatchMode.Anywhere))
.SetCachable(true)
.List();
Now, NHibernate will cache the results of the query, and next time that you execute the query, you will get it without the expensive hop to the database.
An important note is remembering to add hibernate.cache.use_query_cache = true to the configuration.
Of course, there are quite a bit of issues with caching querying, mostly about the freshness of the data. Which is why you need to make cached queries explictly in the code.
Use with care.
There are posts all the way to May 14, 2025