Oct/080
Database Edition now available from msdn
Just noticed that Database Edition is available to download with my msdn subscription.
Before it was about $3000 to buy, I wonder why there are just giving it away now?
I supect it has to do with the fact that currect dbas are heavily entrenched in their tools and practices, and don't want to change. By giving it away for free, they can get the developers on board and get them to show the dbas how nice the tool works.
Sep/080
Conveying Complexity with Simple examples or analogies
Google just released there new browser Google Chrome
It is beatifully simple piece of coding, in which each tab is broken into its own process.
Each process can then spawn child process which correspond to various plugins, such as shockwave flash, etc.
This is a great way to isolate your processes from other errors, essentially it is a mini-os wrapped in a browser.
This can be a difficult concept to wrap your head around and the cartoon that was produced is an excellent way to understand the nuts and bolts.
Some cartoons that convey difficult concepts.
SOA is something that is often defined using analogies such as Legos, Transportation, or the post office.
It pays to think of things at their simplest level, it will really be helpful for you when attempting to convince others or your brilliance:)
Aug/080
Isle Royale Photographs
Travis Novitsky has taken some really beautiful photographs of Isle Royale and Northern Minnesota.
Aug/080
Isle Royale Vacation Log
Recently I took a backpacking trip out to Isle Royale National Park
Day One - August 16th 2008 6.9 Miles
Left from Grand Portage MN at 8:00am on the Voyageur II.
The boat blew a head on the way to Windigo so we had to change our plans and leave from there. Hiked 6.9 miles to Island Mine where we camped. Everyone was pretty sore and the water source was pretty scarce.
Day Two -- 5.5 Miles
Hiked to South Lake Desor. The forest was mostly sugar maple when we started and as we got to Lake Desor the scenery started to change to a Birch forest. The lake was nice, there was a nice beach over by the group camp area where we could cool off. There was a pretty good wind that day and Bryan and our neighbors witnessed a big dead birch tree fall over. It kind of spooked us. Later in the night, after we had convinced ourselves it would not happen again, we heard another tree fall in the distance. We were a little nervous when we went to bed, but we made it:)
Day Three -- 8.1 Miles
On the way out we say a Cow Moose grazing. Pretty Cool.
By this time we were pretty well acclimated to the hiking. I think the soreness was all gone by day two.
The Green Ridge Trail started to open up into some really some nice views of the island. There was lots of great views of the mountains in Canada. It was much more impressive than I had ever imagined. That day Bryan rigged up a berry pickin' container, so we spent most of the day gathering Thimble berries. After pickin' berries all day we got to Hatchet lake late and got the last campsite. It really sucked. The lake did not have much access to it, so we went to bed pretty early.
Day Four -- 3.9 Miles
After seeing the beautiful views of the Canadian mountains we decided to hike over to Todd Harbor which is on the north side. We got there early enough to get a shelter. The spot was pretty close to the lake. I hiked over to a small waterfall about a half a mile from camp. We laid around until the sunset. The sunset over lake superior was amazing.
Day Five -- 8.9 Miles
We hiked through McCargoe Cove to East Chickenbone. McCargoe Cove was pretty exposed and busy. There was a nice dock and place to swim. We had our sights set on East Chickbone to put us closer to Daisy Farm. The east chickenbone campsite was ok, it was pretty open and in the middle of birch valley. The lake was about 1/4 mile away. Three people from Tennessee joined us because the campground was full. Pretty interesting group, it was nice to hear about Smoky mountain national park. At sundown we went down and fished. I caught a good size walleye. I think Bryan did too, but his snapped the swivel before he could get it up to shore.
Day Six -- 7.4 Miles
Hiked to Daisy Farm. There was a real nice beach there. It was pretty busy. It seemed to keep getting busier as we approached Rock Harbor.
Day Seven -- 4.2 Miles
Three Mile. We got a shelter that had access to an awesome rock to just sit on and read. The last couple of days our hikes were pretty short so we had plenty of time to just sit around read, and play hour long games of crazy eights.
Day Eight -- 3.6 Miles
Rock Harbor. Ahh Civilization. After craving burgers for eight days it was finally real. Admittedly I had imagined it would taste so phenomenal, but it fell really short.
Day Nine
Woke up at 7:00am for the boat ride. Pulled into Windigo about 1:00pm. Asked the boat people how long the stop would be. They said about 30 minutes. Bryan and I sprinted up to store and ordered a pizza. Twelve minutes later we had our pizza. The lady said once the boat blew its horn we would have 10 minutes. The boat blew its horn and we started cramming the pizza down. We ran down and found the boat was leaving. We had to sit there as the boat turned around. After we went through the embarrasment of missing the boat, we sat through the remainder of our 10 hour boat ride.
When you are away from modern amenities for any period of time it is amazing how much you crave them. You gain a new appreciation for a little while, but once you satisfy the craving you immediately begin to take it for granted.
Aug/080
Mac Heat Problem and the Print Queue
For a few days now, I have noticed that my mac has been running very very hot. Around 160 Degrees fahrenheit.
I noticed that the cpu is pegged.
I think since it is dual core the system doesn't hang so it was not noticeable in regards to performance.
The culprit was the print queue. I killed it a few times and it came right back. I looked at the print queue and there were a couple of jobs stuck in there.
I deleted them and cpu went back down to normal.
I am already noticing a big difference in both temperature and battery life.
Aug/080
Creating File Paths in C#
Path.Combine is an easy and reliable way to combine path and file information.
Before
DataFile = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + "samplefile.xml"
After
DataFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"samplefile.xml");
When using Special Folders you need to call Environment.GetFolderPath to return the actual path.
Jul/080
ObservableCollection Namespace
Don't forget to add a reference to WindowsBase when you need to work with ObservableCollection in WPF.
I am a big fan of naming assemblies according to the contained namespace. That is why it always takes me a second to realize that System.Collection.ObjectModel.ObservableCollection<T> is in the WindowsBase namespace assembly.
Jul/080
Linq to Xsd
Linq to Xsd is one of microsofts many incubating projects.
Sounds like a great technology.
The question I am always faced with, is it worth it.
Time is limited and there are plenty of technologies out there that are in production that I know almost nothing about.
The ablility to access Xml in a strongly typed manner.
Man that sounds like a no brainer.
I understand that Microsoft is overcome with projects.
Jeff Atwood wrote a great article on why Microsoft Can't Go Open Source
I think this dove tails perfectly into the point that MS just spends too much time reinventing the wheel and not enough time introducing full featured development products.
Linq is a great product. But why not release it with oracle support out of the box.
I would love to pick up Linq to Xsd and run with it, but it seems like it just going to be another dead end.
Jul/080
Click Detection in a WPF Listview
Once you have the event wired up, getting the current row only takes a couple lines of code.
private void listPictures_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
Shern.PhotoManager.Common.ImageProperty value = (Shern.PhotoManager.Common.ImageProperty)listPictures.SelectedValue;
PictureViewer pictureViewer = new PictureViewer(value.FileName);
pictureViewer.Show();
}In this example ImageProperty is the type that is bound to the ListView control.
May/084
Getting started with the Google App Engine.
The tutorial goes over some basic concepts surrounding Google's App Engine Framework, demonstrates using the Google App Engine to store data, and using Django templates to create a GeoRss feed that is consumed by Google maps.
Setup your environment
I chose eclipse as my ide.
The nice thing about eclipse is if you add the lib directories of whatever you are using (including the Google App Engine) you will get some intellisense.
Download the necessary components.
Google app engine
Eclipse
Installing Pydev
The documentation helped, but the link was bad. I used http://pydev.sf.net/updates/.
The guts of the python file
import cgi import os import wsgiref.handlers from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.ext import db from google.appengine.ext.webapp import template _DEBUG=True class Business(db.Model): ...... def main(): application = webapp.WSGIApplication([ ('/',MainPage), ('/createbusiness.do',BusinessSignup), ('/georssfeed.xml',GeoRssFeed) ],debug=_DEBUG) wsgiref.handlers.CGIHandler().run(application) if __name__ == "__main__": main()
The main method is where we map our urls to the classes we have defined within the python file.
Each class that handles requests should have a get or a post method.
When a get or a post occurs it will be routed automagically to the appropriate method.
Creating the table
class Business(db.Model): name = db.StringProperty() description = db.StringProperty(multiline=True) url = db.URLProperty() location = db.StringProperty() latitude = db.StringProperty() longitude = db.StringProperty() address = db.StringProperty() created = db.DateTimeProperty(auto_now_add=True)
Description can contain line breaks so we specify multiline=True
Created is of type DateTime and has the property auto_now_add set to true
created is set to the current time the first time the model instance is stored in the datastore, unless the property has already been assigned a value.
There is also an auto_now property that can be used to set the current time each time the record is created or updated. Useful for modified dates.
Handling the request
In one of googles examples(Task List) they used a base class for the request.
Here is my modified version.
class BaseRequestHandler(webapp.RequestHandler): """Supplies a common template generation function""" def generate(self,template_name,template_values={}): values = { 'request': self.request, 'debug': self.request.get('deb'), 'application_name': 'Local Business Directory' } values.update(template_values) directory = os.path.dirname(__file__) path = os.path.join(directory,os.path.join('templates',template_name)) self.response.out.write(template.render(path,values,debug=_DEBUG))
This does a few nice things.
values = { 'request': self.request, 'debug': self.request.get('deb'), 'application_name': 'Local Business Directory' } values.update(template_values)
This sets up an array of base values that will be passed into the template.
In other methods that use base request, we will add other objects to this array. So our html templates can process data.
The last line values.update is where the two arrays gets merged.
path = os.path.join(directory,os.path.join('templates',template_name))
In this application I created a templates folder to separate the html from the code. This line just adds the template_name to the /templates path.
self.response.out.write(template.render(path,values,debug=_DEBUG))
And finally
Write the request out.
Using the BaseRequestHandler
class MainPage(BaseRequestHandler): def get(self): #Get all of the businesses businesses = Business.all().order('-created') self.generate('index.html', { 'businesses': businesses })
Here is a simple example of querying all of the businesses ordered by created date.
We then call the generate method on the BaseRequestHandler, passing in our additional objects, along with the template name.
Using Templates
The Google App Engine uses the Django templating engine. W00t
The for loop
{% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %}
The if statement(there are several varieties)
{% if athlete_list %} Number of athletes: {{ athlete_list|length }} {% else %} No athletes. {% endif %} {% ifequal user.id comment.user_id %} ... {% endifequal %}
In the spirit of python, there are a lot of functions that Django gives you.
Examples:
timesince: Formats a date as the time since that date (e.g., “4 days, 6 hours”).
phone2numeric: Converts a phone number (possibly containing letters) to its numerical equivalent. For example, '800-COLLECT' will be converted to '800-2655328'.
More Information on Django templates
In order to display a list of businesses I am just using a simple for loop and creating a row each time.
<div class="table">
<table>
<tr>
<th>Business Name</th>
<th>Address(Address, City, State)</th>
<th>Description</th>
<th>Url</th>
<th>Location</th>
<th>Latitude</th>
<th>Longitude</th>
</tr>
</tr>
{% for business in businesses %}
<tr id="row{{ forloop.counter}}">
<td class="main"
<div class="name">{{ business.name }}</div>
</td>
<td class="members">
{{ business.address }}
</td>
<td class="members">
{{ business.description }}
</td>
<td class="members">
{{ business.url }}
</td>
<td class="members">
{{ business.location }}
</td>
<td class="members">
{{ business.latitude }}
</td>
<td class="members">
{{ business.longitude }}
</td>
</tr>
{% endfor %}
</table>
</div>Entering Data
Two pieces of code were necessary for this
Plumbing in the python file
class BusinessSignup(webapp.RequestHandler): def post(self): business = Business() business.name = self.request.get("txtBusinessName") business.address = self.request.get('txtAddress') business.description = self.request.get('txtDescription') business.url = self.request.get('txtUrl') business.location = self.request.get('txtLocation') business.latitude = self.request.get('txtLatitude') business.longitude = self.request.get('txtLongitude') business.put() self.redirect('/')
This just grabs from the data from the request and sets each property on our business object.
Then calls put.
put is an instance method that saves the data to the database.
delete, to_xml, is_saved, are a couple of other useful instance methods.
<form action="/createbusiness.do" method="post" id="businessform">
Tells the form to post to the specified address.
Bringing it all together
application: yourapplication version: 1 runtime: python api_version: 1 handlers: - url: /static static_dir: static - url: /.* script: localbusinesslocator.py
The app.yaml is where your external url mapping occurs.
If you wanted to use several python files, this is where that would happen.
More Info can be found here
Testing the application
usr/local/google_appengine/dev_appserver.py /sourcedirectory/
Hopefully this fills in some gaps left by Googles tutorial.
The next installment of the series will go over displaying the data in the GeoRss format and displaying it on google maps.





