Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Monday, November 09, 2009
( Stuff )

After browsing Scott Hanselmans Tools list

http://www.hanselman.com/blog/ScottHanselmans2009UltimateDeveloperAndPowerUsersToolListForWindows.aspx 

I thought I’d try Windows Live Writer.. it worked first time :-)

Ahh.. for those who have no idea what Windows Live Writer is (like myself 15mins ago).. it means you can post blog articles from a windows app on your desktop.  No more messing around with html interface (and worrying about session expiring!)

Comments [0] | | # 
# Thursday, November 05, 2009
I know I've skipped a few chapters.. but hey.. who is perfect?  Sometimes, it is good to get to some concrete results to give some pespective.

After months of playing with code (why do things always take longer than you think..?), and having a blast, I've now forgotton everything I know about asp.net.  So time to do some spikes.

Here is a super simple reminder of asp.net syntax and simple events:

Default.aspx (\code\tddBook\SimpleAspSpike)

<%@ Page Language="C#" AutoEventWireup="true"  CodeBehind="Default.aspx.cs" Inherits="WebSite2testWebProj._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form2" runat="server">
    <div>
    hello world from html<br />
    <%= "Hello from asp.net" %> <br />
    
    This is a label: <asp:Label ID="label1" runat="server" /> <br />
    The time is: <%= System.DateTime.Now.ToLongTimeString()%> <br />
    This is a textbox: <asp:TextBox runat="server" ID="textbox1" /><br />
    A button: <asp:Button runat="server" ID="button1" Text="press me" onclick="button1_Click" /><br />
   Label2 is here: <asp:Label ID="label2" runat="server" /><br />
   asp.net uses viewstate.. so the button is just a submit button, which then goes back to the server, refreshes the page with the new data in the label2 label. <br />    
    </div>
    Autopostback is set in the following DropDownList (server control)... makes contact with the server each time an item is selected.. which we can use to wire up an event..onselectedindexchanged<br />
    <asp:DropDownList runat="server" ID="GreetList" AutoPostBack="true" 
        onselectedindexchanged="GreetList_SelectedIndexChanged">
        <asp:ListItem Value="no one">No one</asp:ListItem>
        <asp:ListItem Value="world">World</asp:ListItem>
        <asp:ListItem Value="universe">Universe</asp:ListItem>
    </asp:DropDownList><br />
    Label3: <asp:Label ID="label3" runat="server" /> <br />
    </form>
</body>
</html>

And the Default.aspx.cs

using System;
using System.Web.UI;

namespace WebSite2testWebProj
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write("Hello from Page_Load in codebehind");
            label1.Text = "Hello from the codebehind into a label";
            textbox1.Text = "Textbox from codebehind";
        }

        protected void button1_Click(object sender, EventArgs e)
        {
            label2.Text = "button pressed";
        }

        protected void GreetList_SelectedIndexChanged(object sender, EventArgs e)
        {
            label3.Text = "Hello, " + GreetList.SelectedValue;
        }
    }
}

Ok, looking good so far.

Difference between CodeBehind and CodeFile

WebSite or Web Application Project?
http://www.dotnetspider.com/resources/1520-Difference-between-web-site-web-application.aspx

WebSite is really simple, with no project file.  Web Application Project has a project file.

Found that remembering how to access databases isn't too easy:

looking at old project:
http://treasuresprint.blogspot.com

Realised I didn't put up the sourcecode at the time, and have managed to find it on my laptop:


Connecting to and displaying data from a DB very easily:

Deafult.aspx (\code\tddBook\DBConnectySpike)
<form id="form1" runat="server">
    <div>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TreasureConnectionString %>"
            SelectCommand="SELECT [StuffId], [Description] FROM [Stuff]"></asp:SqlDataSource>
        <br />
        <br />
        this is a gridview&nbsp;<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
            DataKeyNames="StuffId" DataSourceID="SqlDataSource1">
            <Columns>
                <asp:BoundField DataField="StuffId" HeaderText="StuffId" InsertVisible="False" ReadOnly="True"
                    SortExpression="StuffId" />
                <asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
            </Columns>
        </asp:GridView>
        <br />
        this is a datalist<br />
        <br />
        <asp:DataList ID="DataList1" runat="server" DataSourceID="SqlDataSource1" >
            <ItemTemplate>
                <asp:Literal ID="Literal2" runat="server" Text="Description:"></asp:Literal>
                <asp:Literal ID="Literal1" runat="server" Text='<%# Eval("Description") %>'></asp:Literal>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:Literal ID="Literal2" runat="server" Text="Description:"></asp:Literal>
                <asp:TextBox ID="TextBox1" runat="server" Text='<%# Eval("Description") %>' Width="208px"></asp:TextBox>
            </EditItemTemplate>
        </asp:DataList><br />
        <br />
        this is a details view</div>
        <asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" CellPadding="4"
            DataKeyNames="StuffId" DataSourceID="SqlDataSource1" ForeColor="#333333" GridLines="None"
            Height="50px" Width="341px">
            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <CommandRowStyle BackColor="#D1DDF1" Font-Bold="True" />
            <EditRowStyle BackColor="#2461BF" />
            <RowStyle BackColor="#EFF3FB" />
            <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
            <Fields>
                <asp:BoundField DataField="StuffId" HeaderText="StuffId" InsertVisible="False" ReadOnly="True"
                    SortExpression="StuffId" />
                <asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
            </Fields>
            <FieldHeaderStyle BackColor="#DEE8F5" Font-Bold="True" />
            <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <AlternatingRowStyle BackColor="White" />
        </asp:DetailsView>
        <br />
        <br />
    </form>
And in the web.config:
<connectionStrings>
    <add name="TreasureConnectionString" connectionString="Data Source=localhost;Initial Catalog=Treasure;Persist Security Info=True;User ID=dave;Password=letmein" providerName="System.Data.SqlClient"/>
    </connectionStrings>
So it should come out like this:


Thoughts
ASP.NET offers some controls to make life 'easier' such as databinding, edit, deleting, sorting on the gridview:  All pretty powerful for RAD, however for testable apps.. am not sure this is the way.  Or perhaps other Grid controls like Telerik are better.  Maybe best to Keep it Simple.

Ideally we want testable code, with a thin layer of UI code on top.
A gridview with update
        <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:TreasureConnectionString %>" 
        SelectCommand="SELECT [StuffId], [Description] FROM [Stuff]"
        UpdateCommand="UPDATE Stuff SET Description=@Description WHERE StuffID=@StuffID">
        </asp:SqlDataSource>
         <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" DataKeyNames="StuffId" AutoGenerateEditButton="true" DataSourceID="SqlDataSource2">
           <Columns>
                <asp:BoundField DataField="StuffId" HeaderText="StuffId"/>
                <asp:BoundField DataField="Description" HeaderText="Description"/>
            </Columns>
         </asp:GridView>


And DropDownList / TextBox common usage:




This is all in the DB spike source code here:
DBConnectSpike.zip (15.17 KB)

Data Control Summary
http://quickstarts.asp.net/QuickStartv20/aspnet/doc/ctrlref/data/default.aspx

Gridview - the classic Grid..edit, delete, sort, page.  Takes advantage of DataSource controls
DataList - items in a repeating list
DetailsView - typically used.. if a gridview item is selected, the detailsView is displayed to edit.
FormView - same as above but with no built in template.
Repeater - has no built in layout or styles.  No column layout. No Edit/Del

Going through the SearchPage.aspx.. trying to get any of this application to compile.  Have got source from book.. however..  good practise to chop code and and try and work through.  Hmm - sometimes better to revert back to compiling code in source control.

This project is in need of refactoring... too complex currently.  Would like to 'defactor' for simplicity, then put some patterns back in.  Webservice would be first to go, and use POCOs.  XSD definition for DTOs would go as well, with simple objects as definitions.  DAL I'd like to take out Datasets and use a manual DAL.

Most important thing is to get it working.  Good thing about this project so far, is that it is testable at every level.
Comments [0] | | # 
# Wednesday, October 21, 2009
Customer tests confirm how the feature is supposed to work as experienced by the end user.

Because customers generally don't want to use nUnit.. we're going to use Fitnesse, which is more user friendly:

The goal is to have the customer write their own tests.

To setup Fitnesse.  Download the .jar and run it like this:

c:\apps\fitnesse -jar fitness.jar -p 8080

Then go and get slim for .net.  I installed it to c:\apps\slim



Here is how it works for the Divider example:

!define TEST_SYSTEM {slim}
!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,c:\apps\slim\fitsharp.dll %p}
!define TEST_RUNNER {c:\apps\slim\Runner.exe}
 
!path C:\code\slimexample\slimexample\bin\Debug\slimexample.dll

|import      |
|slim_example|

!|Divider|
|Numerator|Denominator|Quotient?|
|10       |2          |5      |
|12.6     |3          |4.2      |
|22       |7          |~=3.14   |
|9        |3          |<5       |
|11       |2          |4<_<6    |
|100      |4          |33       |

Here is the C# code, I compiled to slimexample.dll
using System;

namespace slim_example
{
    public class Divider
    {
        public double  Numerator { get; set; }
        public double Denominator { get; set; }
        double _quotient;

        public void Execute()
        {
            _quotient = Numerator / Denominator;
        }

        public double Quotient()
        {
            return _quotient;
        }
    }
}
Run the tests.. and we'll see that when 2 numbers are sent... then then ? in the Fitnesse means that something should be checked.


Then we wire up to our code and test CatalogAdapter:

From this test we can see that I've a bug.. something wrong with the Duration.



Debugging

Have been working through why we are not getting the duration through.  The unit tests on the DAL are passing fine.. in CatalogFixture, have added in 2 tracks of different lengths.  They get pushed into the db, then pulled out using Catalog.. looks ok.



The next step is to look at the Service layer and see if the Duration is being written.  Interestingly, the webservice is passing back all the correct tracks, but nothing to do with reviewers etc..




Very interesting bug.. if I didn't specify this in my RecordingAssembler.WriteTotalRunTime:

dto.totalRunTimeSpecified = true;

then nothing would be passing back.  Same for WriteAverageRating.


Came across another issue with the webservice, and couldn't get it to autogen.. easiest way was to create it again.  Using source control so it if all went to custard, could go back.

Been getting bogged down in detail, so have decided to push to the end of the project, and get a front end up and running asap.



Comments [0] | | # 
# Tuesday, October 20, 2009
Task:  create a WebService that returns a recording and all its entities when specifying the id of the recording. Return type of XML (ie not a .net dataset).

The DAL.Catalog returns a RecordingDataSet.Recording.

We need to write a DTO that takes an input and transforms(munges) it into something else

Using a Service Interface Pattern.

Build a stub, map it into a DTO, and verify each field.
First thing I did was to create a stub, to hide how the RecordingDataSet is retrieved..so am not relying on the DAL at this point.

Here is the test the Stub code:
[TestFixture]
  public class CatalogServiceStubFixture
     {
         RecordingDataSet.Recording recording;
         RecordingDataSet.Recording actual;
         CatalogServiceStub service;
 
         [SetUp]
         public void SetUp()
         {
             // create a test recording in memory
             recording = CreateRecording();
             service = new CatalogServiceStub(recording);
             actual = service.FindByRecordingId(recording.Id);
         }
 
         private RecordingDataSet.Recording CreateRecording() 
         {
             RecordingDataSet dataSet = new RecordingDataSet();
             RecordingDataSet.Recording recording = dataSet.Recordings.NewRecording();
             recording.Id = 1;
            // more code needed here to fill in the rest of the recording.
             return recording;
         }
 
         [Test]
         public void CheckId()
         {
             Assert.AreEqual(recording.Id, actual.Id);
         }

Next we want a dto to transform our dataset, into something else:



To specify in platform independant, we use XML.  This is still quite bulky, perhaps JSON would be lighter now.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://nunit.org/webservices" elementFormDefault="qualified" targetNamespace="http://nunit.org/webservices" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Recording" type="tns:RecordingDto" />
  <xs:complexType name="RecordingDto">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="id" type="xs:long" />
      <xs:element minOccurs="1" maxOccurs="1" name="title" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="artistName" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="releaseDate" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="labelName" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="unbounded" name="tracks" type="tns:TrackDto" />
      <xs:element minOccurs="0" maxOccurs="unbounded" name="reviews" type="tns:ReviewDto" />
      <xs:element minOccurs="0" maxOccurs="1" name="totalRunTime" type="xs:int" />
      <xs:element minOccurs="0" maxOccurs="1" name="averageRating" type="xs:int" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="TrackDto">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="id" type="xs:long" />
      <xs:element minOccurs="1" maxOccurs="1" name="title" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="artistName" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="duration" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="genreName" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ReviewDto">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="id" type="xs:long" />
      <xs:element minOccurs="1" maxOccurs="1" name="reviewerName" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="rating" type="xs:int" />
      <xs:element minOccurs="1" maxOccurs="1" name="reviewContent" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>


A benefit is that we can create C# from this:.. but really just getters and setters.  See below.. this led to an interesting bug.

http://www.codingday.com/xml-c-class-generator-for-c-using-xsd-for-deserialization/

xsd asdf.xml - create an xsd
xsd asdf.xsd /CLASSES  - creates a .cs

Then just creating an 'Assembler', which writes out the DTO...(from http://martinfowler.com/eaaCatalog/dataTransferObject.html)

The Assembler has business logic in it to flatten the structure (as in the similar example above)

The webservice is setup by adding it into IISAdmin.

As the default ASP.NET user does not have access to my local database
connection = new SqlConnection("Data Source=DAVEXPLAPTOP;Initial Catalog=catalog;Integrated Security=True");

The easiest way to get running on dev was to add the DAVEXPLAPTOP\ASPNET user into my SQL database.  This didn't show up under objects when adding, but I went ahead anyway and it worked.







So this is what we have so far:


Comments [0] | | # 
From the nbdn course, I had some interesting code I'd like to test.  Just the business logic really, no DAL nor UI.  As I wanted to make a full application, the first though was to make a DAL which talked to a text file, or just some dummy data.  How to do this well?  De-coupled.  Tried to use poor mans dependency injection, and got confused.  So I had a coffee, and bought this book.  Because it had an end to end example of a testable application.  It uses .net1.1 mostly (which is good as there are no language constructs to learn)



Some good introduction to refactorings, and unit testing.  The main meat of the book is an example called MediaLibrary (music recordings).  Chapter 5 started with testing the DAL.

Here are the first tests.  Am showing nunit test runner.. mostly I use testdriven.net, and have setup ctrl alt shft t to run tests.



for source control I'm using  git, and have coupled up with gvim as text editor.  And linked in beyond compare for a merge tool.

The book uses Strongly Typed Datasets, which were the 'star of the show' in the .net1.0 release.  By writing the sql, and having intellisense have autoproperties, this saves writing boiler plate code.

I learned about DataSets.. here is my edit (from wikipedia)..http://en.wikipedia.org/wiki/ADO.NET#DataSets

ADO.NET consists of two primary parts:

Data provider

These classes provide access to a data source, such as a Microsoft SQL Server.  Each data source has its own set of provider objects, but they each have a common set of utility classes:

  • Connection: Provides a connection used to communicate with the data source.
  • Command: Used to perform some action on the data source, such as reading, updating, or deleting relational data.
  • Parameter: Describes a single parameter to a command. A common example is a parameter to a stored procedure.
  • DataAdapter: A bridge used to transfer data between a Data source and a DataSet object (see below).
  • DataReader: Used to efficiently process a large list of results one record at a time. It allows records to be accessed in a read-only, forward-only mode, i.e., records have to be accessed in sequential order; they can neither be randomly accessed nor can a record which has been processed previously be accessed again.

DataSets

DataSet objects, a group of classes describing a simple in-memory relational database,

  • A DataSet object represents a schema (either an entire database or a subset of one). It can contain tables and relationships between those tables.
    • A DataTable object represents a single table in the database. It has a name, rows, and columns.
      • A DataView object overlays a DataTable and sorts the data (much like an SQL "order by" clause) and filters the records (much like an SQL "where" clause) if a filter is set. An in-memory index is used to facilitate these operations. All DataTables have a default filter, while any number of additional DataViews can be defined, reducing interaction with the underlying database and thus improving performance.
        • A DataColumn represents a column of the table, including its name and type.
        • A DataRow object represents a single row in the table; it allows reading and updating of values in that row, likewise retrieving any rows that are related to it through a primary-key foreign-key relationship.
VS has a nice editor:



Once I spiked up what datasets were (in simpleDatabaseTests.cs).. used this for reference: http://www.csharp-station.com/Tutorials/AdoDotNet/Lesson05.asp
 [Test]
        public void put_data_into_a_dataset()
        {
            DataSet dataset = new DataSet();
            SqlDataAdapter data_adapter = new SqlDataAdapter("select id, name from Artist", connection);
            SqlCommandBuilder sql_command_builder = new SqlCommandBuilder(data_adapter);
            data_adapter.Fill(dataset, "Artist");
            Assert.IsNotNull(dataset);

            DataTable data_table = dataset.Tables[0];
            for (int i = 0; i < data_table.Rows.Count; i++)
            {
                DataRow data_row = data_table.Rows[i];
                Console.Out.Write(data_row["id"] + " ");
                Console.Out.WriteLine(data_row["name"]);
            }
        }

The example I'm working through uses a Table Data Gateway Pattern for the DAL. 

http://martinfowler.com/eaaCatalog/tableDataGateway.html
"A Table Data Gateway holds all the SQL for accessing a single table or view: selects, inserts, updates, and deletes. Other code calls its methods for all interaction with the database."

Lets take an example of ArtistFixture.cs which tests ArtistGateway.cs

[TestFixture]
    public class ArtistFixture
    {
        static readonly string artistName = "Artist";
        SqlConnection connection;
        ArtistGateway gateway;
        RecordingDataSet recordingDataSet;
        long artistId;

        [SetUp]
        public void setup_and_open_connection_pass_to_gateway_setup_data_set()
        {
            connection = new SqlConnection(ConfigurationSettings.AppSettings.Get("Catalog.Connection"));
            connection.Open();

            recordingDataSet = new RecordingDataSet();
            gateway = new ArtistGateway(connection);
            // insert a new artist getting its ID from the database
            artistId = gateway.Insert(recordingDataSet, artistName);
        }

        [Test]
        public void RetrieveArtistFromDatabase()
        {
            // create new RDS, use same gateway.
            RecordingDataSet loadedFromDB = new RecordingDataSet();
            RecordingDataSet.Artist loadedArtist = gateway.FindById(artistId, loadedFromDB);

            Assert.AreEqual(artistId, loadedArtist.Id);
            Assert.AreEqual(artistName, loadedArtist.Name);
        }
Here is part of ArtistGateway.cs.. gateway is newed up with a connection passed in.. then only in Insert is it passed in a strongly typed RecordingDataSet, which has all the SQL in it which has been auto-genned.
public class ArtistGateway
{
SqlDataAdapter adapter;
SqlConnection connection;
SqlCommand command;
SqlCommandBuilder builder;

public ArtistGateway(SqlConnection connection)
{
this.connection = connection;

command = new SqlCommand("select id, name from artist where id = @id",connection);
command.Parameters.Add("@id", SqlDbType.BigInt);

adapter = new SqlDataAdapter(command);
builder = new SqlCommandBuilder(adapter);
}


public RecordingDataSet.Artist FindById(long artistId, RecordingDataSet recordingDataSet)
{
command.Parameters["@id"].Value = artistId;
adapter.Fill(recordingDataSet, recordingDataSet.Artists.TableName);
DataRow[] rows = recordingDataSet.Artists.Select(String.Format("id={0}", artistId));

if (rows.Length < 1) return null;
return (RecordingDataSet.Artist) rows[0];
}
Class Diagram done in VS2008 with the Class Designer Powertoy http://www.codeplex.com/modeling
To get the blue lines go to Class Diagram, Filter Lines, Show All Associations.

Sequence diagram done in Visio: (hmm - this is a bit complex... I prefer the class diagram above with notes)


Genre was next, then the rest.  Then relationships between objects eg ReviewReviewer.. just testing the test data we create comes back:  Have abstracted out some of the setup code into ConnectionFixture.
 [TestFixture]
 public class ReviewReviewerFixture : ConnectionFixture
 {
     [Test]
     public void ReviewerId()
     {
         RecordingDataSet recordingDataSet = new RecordingDataSet();

         ReviewGateway reviewGateway = new ReviewGateway(Connection);
         long reviewId = reviewGateway.Insert(recordingDataSet, 1, "Review Content");

         ReviewerGateway reviewerGateway = new ReviewerGateway(Connection);
         long reviewerId = reviewerGateway.Insert(recordingDataSet, "Reviewer Name");

         RecordingDataSet.Review review = reviewGateway.FindById(reviewId, recordingDataSet);

         review.ReviewerId = reviewerId;
         reviewGateway.Update(recordingDataSet);

         Assert.AreEqual(reviewerId, review.Reviewer.Id);

         reviewGateway.Delete(recordingDataSet, reviewId);
         reviewerGateway.Delete(recordingDataSet, reviewerId);
     }
 }
The hardest test is RecordingGateway, as it depends on all the other 'tables'.  To simplify, we abstract out the insert/del of test data to RecordingBuilder.cs.

The last class is Catalog, which is the only class that will be called from the Service layer.  In Catalog we have FindByRecordingId, which returns a RecordingDataSet.Recording (so all the data associated with this recordingId).




In summary we have done this of the overall structure of the APP:

Comments [0] | | # 
# Friday, October 09, 2009
JP Boodhoo's Nothing But Dot Net Bootcamp (Sydney)


A mindblowing (melting) experience.  The overall summary of what I learned, is that I know where I want to go now.  Can see how I'd like to develop.

A great series of articles on what we did:
http://www.davesquared.net/2009/08/nothin-but-net-sydney-2009-day-1.html

Xerxes video discussing the camp:
http://ozalt.net/blog/virtual-alt-net-aug-17-jp-boodhoo-s-bootcamp/

Over the last year I've started using:

gvim - text editor (still getting used to it!)
git - source control
gmail - learned the keyboard shortcuts which has been amazing
launchy - quick launcher
vs2008 - black colour of fonts, class diagram
resharper - auto formatting of doc, easily navigate large codebases, refactorings, moving code, create classes quickly
console2 with powershell - use it for git, navigating between projects
windows - keyboard shortcuts like windows file exploring tabbing around
firefox 3.5 with vimperator extensions
beyond compare - easily put stuff live
alt tab replacement
balsamiq - for mocking up UI's
sdedit  - for doing sequence diagrams


Goal over the next 2 months is to write an application in a well architected manner. 

Am starting with the MovieLibrary example (it could be used to catalog your home movies) we worked on at nbdn.  Basically putting a front end, and a DAL on the existing code..

Biggest lessons I've learned this year are:

- have fun!
- to become a great develop you need to code, code, code <grin>



Comments [0] | | # 
# Saturday, August 01, 2009
Interesting..added in C#2.0

using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        // enumerates through the IEnumerable
        // every time call GetInt() we receive a new incremented integer
        foreach (int i in GetInt())
            Console.WriteLine("Got " + i.ToString());
    }

    public static IEnumerable<int> GetInt()
    {
        // this method remembers its' state, so every time it is called, 
        // the next int is returned
        for (int i = 0; i < 5; i++)
            yield return i;
    }
}
thanks to: http://www.c-sharpcorner.com/UploadFile/rmcochran/yieldreturn04022006113850AM/yieldreturn.aspx?ArticleID=4617984b-2209-4211-9d08-8f06e0fe2da5

Comments [0] | | # 

From: http://msdn.microsoft.com/en-us/library/bb383977.aspx

Extension methods enable you to "add" methods to existing types without creating a new derived type,

Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.

For client code, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "hello extension methods are good";
            Console.WriteLine(s);
            int i = s.WordCount();
            Console.WriteLine("number of words is {0}", i.ToString());
        }
    }

    public static class MyExtensions
    {
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }
}

Comments [0] | | # 
# Monday, July 27, 2009
Thanks to:
http://davidhayden.com/blog/dave/archive/2006/05/28/2974.aspx

Anon methods, delegates, predicates.  Anon methods are simple shortcuts so don't have to declare a predicate method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAnonymousMethods
{
    public class Program
    {
        // using an anon method
        static void Mainx(string[] args)
        {
            int[] _integers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            int[] evenIntegers = Array.FindAll(_integers,
                                        // this is the anonymous method below
                                       delegate(int integer)
                                       {
                                           return (integer % 2 == 0);
                                       }
                );

            foreach (int integer in _integers) 
                Console.WriteLine(integer);

            foreach (int integer in evenIntegers)
                Console.WriteLine(integer);
        }

        // not using anon method
        static void Mainy(string[] args)
        {
            int[] _integers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            // passing in IsEven..a delegate which represents the IsEven method
            int[] evenIntegers = Array.FindAll(_integers, IsEven);

            foreach (int integer in _integers)
                Console.WriteLine(integer);

            foreach (int integer in evenIntegers)
                Console.WriteLine(integer);
        }

        static bool IsEven(int integer)
        {
            return (integer % 2 == 0);
        }


       
        // not using anon method and looking at predicate / delegate of Array.FindAll
        static void Main(string[] args)
        {
            int[] _integers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            // a predicate is expected
            // passing in IsEven..a delegate which represents the IsEven method
            int[] whatIsInBoth = Array.FindAll(_integers, IsDaveSequence);

            foreach (int integer in whatIsInBoth)
                Console.WriteLine(integer);

        }

        static bool IsDaveSequence(int integer)
        {
            bool returnState = false;
            if ((integer == 1) || (integer == 3) || (integer ==4))
                returnState = true;
            return returnState;
        }



    }
}

Comments [0] | | # 
# Thursday, July 23, 2009
Delegates, delegate to another method.  In this example, depending on which person is wired up - Suzanne or Amy.. depends on which method is called when the Get the ingredient button is called.


source code here..delegateIngredients.zip (91.58 KB)






    // can be used to create a variable that can point to any method that takes an int parameter and returns a string
    public delegate string GetSecretIngredient(int amount);

On the form:
        // so variable ingredientMethod of type delegate GetSecretIngredient currently points to a null method
        GetSecretIngredient ingredientMethod = null;
        private void getSuzanne_Click(object sender, EventArgs e)
        {
            // suzanne.MySecretIngredientMethod property returns a new instance of the the GetSecretIngredient delegate thats
            // pointing to her secret ingredient method.
            ingredientMethod = new GetSecretIngredient(suzanne.MySecretIngredientMethod);
        }
When button is pressed it will go to either the suzanne.MySecretIngredientMethod or the amy.AmySecretIngredientMethod
        private void useIngredient_Click(object sender, EventArgs e)
        {
            if (ingredientMethod != null)
                Console.WriteLine("I'll add " + ingredientMethod((int)amount.Value));
            else
                Console.WriteLine("I dont have a secret ingredient");
        }
Good duck example here:
http://stackoverflow.com/questions/687626/the-purpose-of-delegates



Comments [0] | | #