Friday, December 28, 2007

The altnetconf news group on yahoo

It's too bad it was renamed to cli_dev. To people that are not connected yet, searching out for a discussion group on alt.net has become a bit harder. I prefer Google Groups and set up a group for discussing alternates to MS's tool stack while still being ".NET".

The cli_dev group description makes a very broad and ambitious brush stroke. What the google group does is focus in on people helping each other with the tools in one place. One can ask a question about Subversion, ActiveRecord, Resharper, Cruise Control in one group instead of having to go to the specific mailing list for that particular project.

The link and subscription is in the left hand margin.

DSL Books

It seems Oren Eini (Ayende.com) is writing a book at the same time that Martin Fowler is writing a book. It should be nice to read both at once and cross reference. Both guys are getting feedback from the community.

Can't wait!

Thursday, December 27, 2007

TDD Challenge

TDD Challenge

See if you can solve it.. post how far you got with your solution....

.... wow. This is the start of a really deep rabbit hole... google around to see what this was designed to do...

Resharper 3.1 is out!

I'm a big fan of Resharper. In fact, I'm not half as productive with out it.

With this little upgrade, you get solution wide real-time code analysis! Not just the file you are working on, but if anything else is not going to compile, you can get there without having to try recompiling first.

I'm in the process of installing it now and will post more when I finally get to use it.

Team City from JetBrains

It's free and it's really good. From what others have been saying about the previous versions, 3.0 is excellent.

It takes a few moments to setup. Compared to CruiseControl.NET, it's a breeze. No xml to swim through - just simple configuration through a web page!

Take a look here.

Thursday, December 6, 2007

Now You Don't Need To Deal With SQL

Imagine this: You want to create some new functionality that involves a new entity. You write your test and your entity in 30 seconds using active record and some Resharper templates. When you run your test, a new table is there for you to store your new entity and your test passes.

How is that possible? Code generators do this. More importantly, how is it maintainable? Most code generators start with the DB. I don't even want to look at the db when I'm flying through my solution with Resharper. Here's how to roll your own "maintainable db generation".

Dealing with the database is a pain when you're trying to develop something really fast. Active Record goes a long way for getting rid of 80% of the pain.

There are 3 things to consider in automating this:

1. What tables and columns exist in your schema right now?
2. What entities do you have in your domain right now?
3. How will this change to the db rolled out and then persisted?

1. The answer is obvious by running this query:

select table_name, column_name from INFORMATION_SCHEMA.Columns

This will give you all the columns and the tables they belong to in your schema. For dbs without the ability to query their own schemas, you can parse the version script or another artifact that reflects the schema.

2. The entities in your assembly that you are interested in derive from ActiveRecordBase. You can use reflection to find all of them:

Type[] types = type.Assembly.GetTypes();
foreach(Type type1 in types) {
object[] attributes = type1.GetCustomAttributes(false);
foreach(object attribute in attributes) {
if (attribute is ActiveRecordAttribute) {
Console.Out.WriteLine(type1.Name);
PropertyInfo[] properties = type1.GetProperties();
foreach(PropertyInfo propertyInfo in properties) {
object[] propertyAttributes = propertyInfo.GetCustomAttributes(false);
foreach(object propertyAttribute in propertyAttributes) {
if (propertyAttribute is PropertyAttribute) {
Console.Out.WriteLine("--" + propertyInfo.Name);
break;
} } } } } }


The above code is missing a lot, but it will get you started. You will need to check the types, nullability, BelongsTo, HasMany, many-to-many, nested and others.

3. Comparing the information from 1 and 2 you will get the additions to the entities that don't yet exist in the db yet. The differences can be mapped to the following addition to the version script - which may look something like this:

IF EXISTS (SELECT version from [dbo].[version] where version = 39)
BEGIN

ALTER TABLE [distributors] ADD [accountID] nvarchar(50) NULL
CREATE TABLE [dbo].[config](
[id] [int] IDENTITY(1,1) NOT NULL,
[configName] [varchar](50) NOT NULL,
[configDescription] [varchar](100) NOT NULL,
[configValue] [varchar](100) NOT NULL,
CONSTRAINT [PK_config] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

UPDATE [dbo].[version] SET version = 40 where version = 39
END
GO



The version script runs anytime the test project recompiles (the post compile event in the project properties).

I will have a working prototype in the next couple of days. I want to hit the low hanging fruit first. This will take care of basic additions for now. The alterations and other concerns will have to wait. I'll add them as the needs arise.

Let me know if you have done anything like this or have any comments or suggestions.

ALT.NET Google Maps

Scott Reynolds has started a google map of where all the ALT.NET folks are located. This is a great resource for if you are wanting to make a regular local tech talk happen, or if you would want to collaborate on a project together. Put yourself on the map!

PS. To add yourself on the map, click edit once you zoomed on your area. In the top left corner of the map you will see the pin.

Joshua Kerievsky's 10 Terrific Transition Tips Presentation

Here is the link to the presentation slides that Joshua showed last night.

Some highlights are:

Perils of Solo-Programming:
– Tunnel Vision (Frog-In-A-Well) Syndrome
– Less Productivity
– Less Knowledge Transfer
– Longer Times Fixing Defects
– Less Code Re-Use
– Poorer testing








XP/Agile Productivity Improvement

Previous PerformanceCurrent PerformancePercentage Improvement
Staffing181139%
Defects2,27038183%
Schedule18 Months13.5 Months24%
Cost$2.8 Million$1.1 Million61%

Active Record and Many to Many Update

Ok. I've cleaned it up now. In the continuing journey of learning Active Record and NHibernate, the static FindAll method can be overridden and the client code is as clean as you would expect it to be:

Distributor[] all = Distributor.FindAll();
foreach(Distributor distributor in all) {
Console.WriteLine(distributor.Name);
foreach(DeliveryMethod deliveryMethod in distributor.DeliveryMethods)
Console.WriteLine("--" + deliveryMethod.Description);
}


Here is what was added to the Distributor class:

public new static Distributor[] FindAll() { return FindAll(DetachedCriteria.For(typeof(Distributor)).SetResultTransformer(CriteriaUtil.DistinctRootEntity).SetFetchMode("DeliveryMethods", FetchMode.Eager)); }

I'm sure there's a way to include the same attribute on the DeliveryMethod and still get the results you want - I just haven't learned enough of the API yet to know how to do that. Tips are welcome..

Wednesday, December 5, 2007

Active Record and Many to Many

I tried to get the following to work:

Distributor[] all = Distributor.FindAll();
foreach(Distributor distributor in all) {
Console.WriteLine(distributor.Name);
foreach(DeliveryMethod deliveryMethod in distributor.DeliveryMethods)
Console.WriteLine("--" + deliveryMethod.Description);
}

The result was multiple queries to the db and multiples of Distributor objects.
It had to be changed to this to actually get what a non-AR user would expect:

Distributor[] all = Distributor.FindAll(DetachedCriteria.For(typeof(Distributor)).SetResultTransformer(CriteriaUtil.DistinctRootEntity).SetFetchMode("DeliveryMethods", FetchMode.Eager));
foreach(Distributor distributor in all) {
Console.WriteLine(distributor.Name);
foreach(DeliveryMethod deliveryMethod in distributor.DeliveryMethods)
Console.WriteLine("--" + deliveryMethod.Description);
}



The attribute on the Distributor class' DeliveryMethods property is as follows:

[HasAndBelongsToMany(typeof(DeliveryMethod), Table="distributorDeliveryMethod", ColumnKey="distributorId", ColumnRef = "deliveryMethodId")]
public ICollection DeliveryMethods { get { return distributorDeliveryMethods; } set { distributorDeliveryMethods = value; } }


While no collection of Distributors exists on the DeliveryMethod class.

Is there an easier way to do the above find? What happens if you want 3 or more joins chained?

Joshua Kerievsky's 10 Terrific Transition Tips

I attended Joshua's presentation today at Sophos. This was put on by Agile Vancouver. Joshua is the author of Refactoring to Patterns. Here are the points he made:

1. Management and Development Process is Important.

Scrum alone does not work. Eventually it will be frequent releases of buggy code. Saw that one before.

Pair programming can't be sold. From my experience many object to it as they are very anti-social. Their programming skills have been honed by spending late nights in front of the computer alone. It's certainly what I remember doing since I was a kid.

What works better is selling the risks of Solo Programming. Joshua's list was more comprehensive. If anyone has anything to add to this, please feel free to comment.

Frog-in-a-well: The developer has a very small view on what is being worked on. There is no one around to rescue the direction of the code to be in line with what is being worked on. The risk of throwing away what you've written and starting over is real and will happen often.

Productivity not as high: Developer is sitting alone. Goes off on a coding tangent (related to above). Or goes over and above of just enough to work. Or reads a blog, gets entrenched in an email thread, etc. No one there to ensure focus is on building the software.

Low code reuse: Without anyone there to suggest that this was already done somewhere else in the code base, a similar solution is coded. Because it was reinvented, it's harder to refactor the duplication.

There are way more.

2. Removing Risks:
A company goes to agile to mitigate risks better. There was more to this, but I think I was busy finding a plug for my dying laptop at the time. I managed to capture the following:

Technical Debt: It is very hard for business to understand technical debt. At one of the companies that Joshua was consulted to introduce Agile at, there was a method that was 28 printed pages long. He taped them together and rolled the method out on the floor of the hotel lobby. He showed us the video of that. If I get it from him, I'll post it on this blog. The use of endless analogies is needed for them to grasp what the developers have to face.

- credit card: Ask the executives how often they make a payment on their credit card. What would happen if they stopped making payment? This is what developers are faced with.

- driving instructions: Joshua wrote really bad driving directions from a patchwork of old English, pig Latin, etc. He asked the execs if they could use those instructions.

3. Business Trumps Process
Should not happen all the time. See above. Business tends to add features in the fashion of a drug pusher: "Just have another feature..." It is important to be a good debt manager and push back on features before the machine grinds to a halt. "Version 5" software is where this happens. By this time, you are only fixing bugs to the product and don't have enough cycles to push out more features and stay competitive. Like having a maxed out credit card.

4. Engage the Entire Organization
Management, Support, Customers and Development must be involved. The concept of a project community is important. It is usually larger than one would expect.

HR is really important as they usually make dire mistakes such as rewarding cowboy coding. HR should be on board as soon as possible.

A major, big project should be chosen to introduce agile on. A one-off project will always be dismissed as a fluke, or didn't have the high standards that the rest of the company works against.

5. Handle Scaling Problems
Joshua's company's sales pitch. They do eLearing for Agile. DRY on the meta level. It was not productive to repeat themselves over and over because the company is too large to get everyone trained within a reasonable amount of time.

6. Fail fast
Tests will do this nicely. The #1 success factor in agile is automated testing. HTTPParser is an OSS project with tests. They are bad tests as changing one line in the production code will make a slew of tests fail. But this has contributors from all walks of life - should be happy that it's fully regression tested.

7. Gather Metrics
How will you know that the agile practices have helped? Five Core Metrics is a book that outlines how to measure the productivity on your project and other indicators. Agile/XP has proven to eliminate 83% of the defects that are found on large projects.

8. Readiness
This was actually the first point. I'm just remembering it now. The company can have the money, the time, etc. But if the db architects group is a rock that won't budge, agile won't get very far. If that does not change, walk away. Joshua's example was one where the db architects group would take 3-4 weeks to consider adding an extra column in a table.

My question at the end was what specifically was important to report regularly to management - at the end of an itteration. Reporting of risks to management was the number one thing.

I know there was 10 points, but in my notes I may have dropped one or two, or mixed them in with the other points. The Agile Vancouver folks say the power point will be available tomorrow. I'll post a link and update then.