Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Monday, February 08, 2010

From Uncle Bobs book clean code example on refactoring:

    {
        static void Main()
        {
            int[] result = GeneratePrimes.generatePrimes(30);
            foreach (var i in result)
                Console.Write(i.ToString() + ", ");
        }
    }
 
    /// <summary>
    /// Given an array of integers starting at 2, cross out the multiples of 2.  Fine the next
    /// uncrossed integer, and cross out all of its multiples.
    /// Repeat until you have passed the square root of the maximum value
    /// </summary>
    public class GeneratePrimes
    {
class Program
        public static int[] generatePrimes(int maxValue)
        {
            if (maxValue >= 2) // the only valid case
            {
                // declarations
                int s = maxValue + 1; // size of the array
                bool[] f = new bool[s];
                int i;
 
                // initialize array to be true
                for (i = 0; i < s; i++)
                {
                    f[i] = true;
                }
 
                // get rid of non-primes
                f[0] = f[1] = false;
 
                //sieve
                int j;
                for (i = 2; i < Math.Sqrt(s) + 1; i++)
                {
                    if (f[i]) // if i is uncrossed, cross its multiples
                    {
                        for (j = 2 * i; j < s; j += i)
                            f[j] = false; // multiple is not a prime
                    }
                }
 
                // how many primes are there?
                int count = 0;
                for (i = 0; i < s; i++)
                {
                    if (f[i])
                        count++; // bump count
                }
 
                int[] primes = new int[count];
 
                //move the primes into the result
                for (i = 0, j=0;i<s ; i++)
                {
                    if (f[i])
                        primes[j++] = i;
                }
 
                return primes; // return the primes
            } else // maxvalue < 2
                return new int[0]; // return null array if bad input
        }
    }

This is messy code because:

  • Variable names are cryptic
  • Some comments are unnecessary

Here is Bob’s refactored version:

/// <summary>
    /// Generates prime number up to a user specified maximum
    /// The algorithm used is the Sieve of Eratosthenes.
    /// Given an array of integers starting at 2:
    /// Find the first uncrossed (eg 3 ) integer, and cross out all its multiples (eg 6,9,12,14)
    /// Repeat until there are no more multipes in the array
    /// </summary>
    class PrimeGenerator
    {
        static bool[] crossedOut;
        static int[] result;
 
        public static int[] generatePrimes(int maxValue)
        {
            if (maxValue < 2)
                return new int[0];
            else
            {
                uncrossIntegersUpTo(maxValue);
                crossOutMultiples();
                putUncrossedIntegersIntoResult();
                return result;
            }
        }
 
        static void uncrossIntegersUpTo(int maxValue)
        {
            crossedOut = new bool[maxValue + 1]; // as bool array starts at 0, and if maxvalue = 10, we need an array of length 11
            for (int i = 2; i < crossedOut.Length; i++) // less than as we don't want to reference crossedOut[4] which doesn't exist
                crossedOut[i] = false;
        }
 
        static void crossOutMultiples()
        {
            int limit = determineIterationLimit();
            for (int i = 2; i <= limit; i++)
                if (notCrossed(i))
                    crossOutMultiplesOf(i);
        }
 
        static int determineIterationLimit()
        {
            // Every multiple in the array has a prime factor that
            // is less than or equal to the square root of the array size, 
            // which is the largest number we are trying to find primes in.
            // So we don't have to cross out numbers
            // larger than that square root of the maxnumber, as they will have been crossed out already
            double iterationLimit = Math.Sqrt(crossedOut.Length);
            return (int) iterationLimit;
        }
 
        static void crossOutMultiplesOf(int i)
        {
            for (int multiple = 2 * i; multiple < crossedOut.Length; multiple += i)
                crossedOut[multiple] = true;
        }
 
        static bool notCrossed(int i)
        {
            return crossedOut[i] == false;
        }
 
        static void putUncrossedIntegersIntoResult()
        {
            result = new int[numberOfUncrossedIntegers()];
            for (int j = 0, i = 2; i < crossedOut.Length; i++)
                if (notCrossed(i))
                    result[j++] = i;
        }
 
        static int numberOfUncrossedIntegers()
        {
            int count = 0;
            for (int i = 2; i < crossedOut.Length; i++)
                if (notCrossed(i))
                    count++;
            return count;
        }
    }

I like Bobs version because it splits the code into simple manageable chunks eg:

    uncrossIntegersUpTo(maxValue);
    crossOutMultiples();
    putUncrossedIntegersIntoResult();

I paired with a friend over the weekend, and we thought this was better:

  • Initialised crossedOut in generatePrimes method instead of ‘child’ method
  • Pass in crossedOut as a parameter instead of a class scope variable
  • Took out (defactored), the notCrossed(i) method as !crossedOut[i] is very readable inline.
  • Make everything non static
  • Keep in /// summary method so intellisense works in the IDE – am trialling Ghostdoc.
/// <summary>
    /// Generates prime number up to a user specified maximum
    /// The algorithm used is the Sieve of Eratosthenes.
    /// Given an array of integers starting at 2:
    /// Find the first uncrossed (eg 3 ) integer, and cross out all its multiples (eg 6,9,12,14)
    /// Repeat until there are no more multipes in the array
    /// </summary>
    class PrimeGenerator
    {
        public int[] generatePrimes(int maxValue)
        {
            bool[] crossedOut;
 
            if (maxValue < 2)
                return new int[0];
            else
            {
                crossedOut = new bool[maxValue + 1];
                uncrossIntegersUpTo(crossedOut);
                crossOutMultiples(crossedOut);
                return putUncrossedIntegersIntoResult(crossedOut);
            }
        }
 
        void uncrossIntegersUpTo(bool[] crossedOut)
        {
            // as bool array starts at 0, and if maxvalue = 10, we need an array of length 11
            for (int i = 2; i < crossedOut.Length; i++) // less than as we don't want to reference crossedOut[4] which doesn't exist
                crossedOut[i] = false;
        }
 
        void crossOutMultiples(bool[] crossedOut)
        {
            int limit = determineIterationLimit(crossedOut);
            for (int i = 2; i <= limit; i++)
                if (!crossedOut[i])
                    crossOutMultiplesOf(crossedOut, i);
        }
 
        int determineIterationLimit(bool[] crossedOut)
        {
            // Every multiple in the array has a prime factor that
            // is less than or equal to the square root of the array size, 
            // which is the largest number we are trying to find primes in.
            // So we don't have to cross out numbers
            // larger than that square root of the maxnumber, as they will have been crossed out already
            double iterationLimit = Math.Sqrt(crossedOut.Length);
            return (int) iterationLimit;
        }
 
        void crossOutMultiplesOf(bool[] crossedOut, int i)
        {
            for (int multiple = 2*i; multiple < crossedOut.Length; multiple += i)
                crossedOut[multiple] = true;
        }
 
        int[] putUncrossedIntegersIntoResult(bool[] crossedOut)
        {
            int[] result = new int[numberOfUncrossedIntegers(crossedOut)];
            for (int j = 0, i = 2; i < crossedOut.Length; i++)
                if (!crossedOut[i])
                    result[j++] = i;
            return result;
        }
 
        int numberOfUncrossedIntegers(bool[] crossedOut)
        {
            int count = 0;
            for (int i = 2; i < crossedOut.Length; i++)
                if (!crossedOut[i])
                    count++;
            return count;
        }
    }
Comments [0] | | # 

image

http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882

My notes below on Bobs book.. also need next article on refactoring PrimeNumber code.

We need 'Clean Code' because otherwise it can bring a company to its knees
As messy code builds up, productivity decreases

What is clean code?
Elegant, Efficient, Does one thing well, Simple, crisp abstractions, Has Unit Tests, Meaningful Names, minimal dependencies, Clear, no duplication, minimal number of entities, What you expect, beautiful

Make code easy to read

Boy Scout Rule:  Leave the campground cleaner than you found it... same for code.. leave it cleaner than you found it

Dave's Simplest Refactoring List
** change one variable name for the better
** break up a function thats a bit too large
** eliminate one small bit of duplication
** clean up a composite if statement

SRP - Single Responsibility Principle
OCP - Open Closed Principle
L
I
DIP - Dependency Inversion Principle

DRY - Don't repeat yourself

2. Meaningful Names

intention revealing names
// this is bad!
int d; // elapsed time in days

**// better....What is being measured, and the units
int elapsedTimeInDays;

see c:\development\ch2 Intentional Names.
and ch2 Statistics Message


**Class names - nouns (things), or noun phrases eg PrimeGenerator, WikiPage, Customer, Account, AddressParser.... not a verb (doing) eg manager, data, info

**Method names - verb or very phrases eg GeneratePrimes, postPayment, deletePage

3. Functions

**First rule:  they should be small
Second rule: they should be smaller than that!

Do one thing!

** shrink function down.. so one level of abstration per function

TO test..
TO RenderPageWithSetupsAndTeardown, we check to see whether the page is a test page and if so, we include the setups and teardown.  In either case we render the page in HTML.

One level of abstraction per function.

4. Comments

Comments are to compensate for our failure to express ourselves in code

eg
// Check to see if the employee is eligible for full benefits
if ((employee.flag && HOURLY_FLAG) && (employee.age > 65))

or
if (employee.isEligibleForFullBenefits())

Dont comment out code :-)

ch4Primes - great to understand at a higher level of abstraction

5. Formatting
important

6. Objects and Data Abstraction

A class does not push its variables out through getters and setters
Rather it exposes abstract interfaces that allow its users to manipulate the essence of the data,
without having to know its implementation.

** am here.. would be good to type in the code again looking at procedural stuff from page 96.
Objects expose behaviour and hide data.
Data Structures expose data and have no significant behaviour.

DTO's - public variables and no functions
Active Records are special forms of DTO's...with public variables... and naviagtaional methods like save and find.

7. Error Handling

8. Boundaries

9. Unit Tests
Very important to keep clean

10. Classes
SRP
Good prime generator example
Open Closed principle

11. Systems
Seperation of main
Factories
Dependency Injection

12. Emergent Design

13. Concurrency

14. Successive Refinement - Case Study - command line parser

15. JUnit internals - Case study (smaller)

16. Refactoring SerialDate

17. Smells and Heuristics
Comments
Environment
Functions
General
Java
Names

Comments [0] | | # 
# Thursday, February 04, 2010

When using a shared hosting provider, and only have access to 1 MSSQL database, it is possible to have 2 different web applications hanging off the same database.

The users seem to be different, however the roles are across all applications.

In VS2008, press the hammer and world icon:  as long as the web.config is pointing to the live database, you can change the live data.

image

And if you’ve a different project eg

image

You can do the same thing and connect to the same live database.

image

Here are roles from 2 different webapps.  Coach and runner;  then administrators, power users, and users.

App_Data Database

This was useful when sending the code to others, so they don’t have to manually make a new database.

<add name="LocalSqlServer" connectionString="Data Source=.\SQLEXPRESS;Integrated Security=True;AttachDbFilename=|DataDirectory|\ASPNETDB.MDF;User Instance=True"  providerName="System.Data.SqlClient" />

Comments [0] | | # 
# Tuesday, February 02, 2010

This helped me a lot understanding how various components worked in my application:

DSCN1364_small

Some obvious omissions included no regex validation on time edit/add.

Comments [0] | | # 

Great video tutorial on: http://download.microsoft.com/download/3/6/0/3604c3d2-0db9-4726-910d-b3b8f93a86e4/hilo_membership-roles_final.wmv

Nice look and feel, however can’t find the source for the graphics.

Click the little hammer and world to bring up the Web Site Administration Tool.

Click show all to view the ASPNETDB.MDF

By Default it puts it in an MDF file in App_Data which is a SQL Express powered db.

image

Use Forms Authentication:

image

Enable Roles (groups of users):

image

Add some roles:

image

On Default.aspx, Anonymous Template:

image

Forgot password:

image

Mail:

image

Protecting a directory:

image

My spike showed exactly how all this works.

image

To get this to work live however (my hosting company doesn’t like me uploading MDF files!).. I need to put the tables into my database.  So, can use Database Publishing Wizard, or now it is included in VS2008.

From http://weblogs.asp.net/scottgu/archive/2005/08/25/423703.aspx

aspnet_regsql.exe

image

So this just created tables/views/SP’s in a new db – I used Membership1 as a test db.

Upload the tables after dumping out the SQL to a text file and got the following errors:

Msg 468, Level 16, State 9, Procedure aspnet_UsersInRoles_AddUsersToRoles, Line 45
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AS" in the equal to operation.

Easiest way was to look at the script and search for all occurrences of:

COLLATE SQL_Latin1_General_CP1_CI_AS

and replace with nothing.

Web.Config

Need to tell the current membership provider where the data store is.

<connectionStrings>

       <remove name=”LocalSqlServer”/>

        <add name="LocalSqlServer" connectionString="Data Source=DAVEXPLAPTOP;Initial Catalog=membership1;Persist Security Info=True;User ID=runuser1;Password=runuser1" providerName="System.Data.SqlClient" />

   </connectionStrings>

Comments [0] | | # 
# Friday, January 29, 2010

Am using publish web.. and automated build script so web.config is correct for dev and live.  Needs to be a Web Application, and not a Web Site.

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

Differences between Web Sites and Web Applications http://www.codersbarn.com/post/2008/06/ASPNET-Web-Site-versus-Web-Application-Project.aspx

Also if doing more than one pre-build call need to do this:

call "$(ProjectDir)copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config"
call "$(ProjectDir)copyifnewer.bat" "$(ProjectDir)LoggedIn\web.config.$(ConfigurationName)" "$(ProjectDir)LoggedIn\web.config"

Also I got an error in dev, where my debugging wasn’t working properly.  Had to tick debug info to full here.

image

to do – possibly abstract out the connection string settings (and anything else dev/live specific) into another file, so the actual Web.config can be changed by VS easily.

In Visual Basic the interface is slightly different however it is in there!

Comments [0] | | # 
# Thursday, January 28, 2010

Spikes are great.. aim to try things very fast to prove things work. KISS!  These are all on http://www.mateerit.co.nz/HelloWorld/

Hello World

Web Application, view it locally, view it on live server.

Locally is fine.  For live I’m on a shared server, and have to remember to create a new virtual directory (clicking Web Directory below)

image

Setup VS to publish the site (in Build menu).. use this syntax:  ftp://myuser%3Amypass@myftpsite.com:21/my/path/to/web/root/

to avoid having to type in password each time!

image

Alt B H enter, to publish to live site quickly.

Connect to the Database

print something on the screen from the SQL Server..locally:

Aim is to print off a list of Persons:

image

Simplest way to do this is:

image

Put on a grid and wire it up:

Publish live, and it wont be able to find the correct connection string:

image

Went into web.config and commented out the local one, and put in another for the live server.

<!--<add name="RunConnectionString" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=Run;Persist Security Info=True;User ID=runuser1;Password=runuser1"  providerName="System.Data.SqlClient" />—>


    <add name="RunConnectionString" connectionString="Data Source=mssql1.openhost.net.nz;Initial Catalog=mateer;Persist Security Info=True;User ID=mateeruser;Password=secret"  providerName="System.Data.SqlClient" />

Its also useful to be able to connect to the remote database directly:  My host makes you open its firewall rules a week at a time from here: https://winplesk6.openhost.net.nz/sql.php or mateerit.co.nz:85/sql.php

image

SqlDataSource

The SqlDataSource data source control represents data in an SQL relational database to data-bound controls. You can use the SqlDataSource control in conjunction with a data-bound control to retrieve data from a relational database and to display, edit, and sort data on a Web page with little or no code.

However this bypassing the tiered approach, and is essentially putting all logic in the webpage!

In Project Run I ended up using ObjectDataSource (to connect to the underlying architecture allowing me to use data Web controls such as GridView, DetailsView or DataList).  Picture from: http://www.asp.net/learn/data-access/tutorial-47-cs.aspx

image

<asp:SqlDataSource ID="PersonsDataSource" runat="server" 
        ConnectionString="<%$ ConnectionStrings:RunConnectionString %>" 
        SelectCommand="SELECT [personid], [personname] FROM [Person]">
    </asp:SqlDataSource>

GridView

Changing the header titles, colours

Sorting and paging work as data is into a loosely-typed DataSet.

Could use a DataReader (instead of a DataSet on the SqlDataSource) which is simpler, but no sorting, paging.

Add / Edit / Delete – Need to add those into the SqlDataSource.  Very easy to make Edit and Delete.

image

Harder to make an insert.. see here for ‘workaround’ and discussion: http://www.codeproject.com/KB/aspnet/InsertSqlDataSource.aspx

DataList

Provides greater flexibility – render using templates.  This will emit a <table><tr><td> syntax.

image

Repeater

Renders nothing other than what you tell it.

image

DetailsView

View one record at a time, and very easy to get a new record.  Built in paging.

image

FormView

Same as details but less rigid layout.

ListView

3.5.. provides more control over markup.  Easy insert

image

 

DataPager

new in 3.5 too.  The First, Previous, Next, Last control.

 

Enabling split view vertically.. very cool.

http://weblogs.asp.net/scottgu/archive/2007/07/30/enabling-vertical-split-view-in-vs-2008.aspx

image

 

Comments [0] | | # 

This is a series of posts about an existing fun project of mine which I’ve decided to refactor,to see how

  • Elegant I can make the code
  • Example of the ‘journey’ of refactoring
  • Working with other great programmers.

Project Run started a few years ago when myself and Pete were training for the St James Race.  This is all real, and we completed the race!

Elevator Pitch

Runners can record their training online. The coach can easily see their recorded training, and can make notes. It will be motivational and competitive for the runners to see what they have done. It will show how long to go before the event they are training for.

image

image

Stories / Requirements

Star * means most important stories that will be developed in version 1.

1) *Dave is a runner. He goes to the website logs in, and enters in the run he has just done. Twice round Hagley Park. 13kms. Took 1:20. Perceived effort - Steady

2) *Pete is a runner. He has just done a Port Hills run. 1:30. Uphill sections were Moderate to Mod Hard. Flat and downhill were Steady.

3) *Chris is the coach. He goes to the website, logs in. Then looks at Dave and Petes past weeks activity. He makes overall notes for both of them. He makes specific notes for Dave.

4) *Dave logs in and is proud to see he has completed this weeks training goals of 40km and 10 hours.

5) *Pete logs in and sees that his progress has improved because 4 weeks ago he did 40kms and was ‘Tired’ at the end of the week. Yet this week he has done 60kms and is feeling good.

6) *Dave logs in and puts in that he did 2 hours of mountain biking covering 30kms.

7) *Pete logs in and puts in 1 hour of Yoga.

8) *Dave logs in and adds in the 10mins of stretching he did to the run he just entered

9) *Dave logs in and makes a mess of things, and wants to delete todays run, which he puts in as 2009.

10) *Dave adds in a note to a previous day about running with food. He likes leppin and is going to try other stuff.

11) *edit

12) *Chris goes to website and has forgotten his password. The system sends a new one to his email account.

13) Chris logs in and easily alters the training plan for Pete and Dave.

14) Dave logs in and puts his max heart rate in, average, max speed, average and time in each training zone.

15) Dave uploads data using his watch to the website.

Timeline

Was 2 weeks.  This included working with a great designer (Nora).

UI Design

Working from paper sketches, where the design goal was simplicity, therefore only 2 real pages to the site.  Nora does Photoshop mockups..

Web

Architecture / Methodology

.NET2 Webforms hosted on a shared cheap hosting solution.

SQL Server2005

TDD Test first then write code - nUnit.

Controls used (I wanted to know how much comes out of the box in .NET, and how much I could leverage).. used these as a  result of successful spikes (see below)

  • Membership
  • Login / Password recovery
  • Master Pages
  • Data Grid
  • Repeater
  • Validation
  • Menu builder
  • Themes

2 Tiers:

image

Source control was Subversion, now I’ve moved to GIT.

Spikes (UI)

Here is a snapshot of the code right now before I do any more refactoring:

To remind myself how these front end UI controls work… going to create new blog post for these spikes.

Spikes (BLL/DAL)

Used TDD as much as possible to drive features

Development Process

Project timeline – used a word document

Bug tracking – word document.

Got code live as soon as possible, and to ‘clients’ as soon as possible for feedback.

Comments [0] | | # 
# Thursday, December 24, 2009

Symbolic constants vs Enumerated Types'

These constants are handy when cheking on the setter (as can use an int range)

    public const int APARTMENT = 1;
    public const int COMMERCIAL = 2;
    public const int HOME = 3;
 
    public int BuildingType
    {
        get { return buildingType; }
        set
        {
            if (value >= APARTMENT && value <= HOME)
                buildingType = value;
        }
    }
This keyword
public clsBuilding()
    {
        address = "Not closed yet";
    }
 
    public clsBuilding(string addr, decimal price, decimal payment, decimal tax, decimal insur, DateTime date, int type)
        : this() // good practise to call initial constructor first..second constructor will overwrite address = "Not closed yet"
    {
        if (addr.Equals("") == false)
            address = addr;
        purchasePrice = price;
        monthlyPayment = payment;
        taxes = tax;
        insurance = insur;
        datePurchased = date;
        buildingType = type;
    }
Base keyword
    public clsCommercial(string addr, decimal price, decimal payment,
                        decimal tax, decimal insur, DateTime date, int type) :
                        base(addr, price, payment, tax, insur, date, type)
    {
        buildingType = type;   // Commercial type from base
    }

this is calling the bases’ constructor.

can also call base methods from the derived (child) class.

Polymorphism

essentially this means we can send the same message to a group of different classes and each class will know how to respond correctly. eg

image

        lstMessages.Items.Add(myApt.RemoveSnow());
        lstMessages.Items.Add(myComm.RemoveSnow());
        lstMessages.Items.Add(myHome.RemoveSnow());

clsApt and clsComm have overridden methods and respond with different phone numbers.  clsHome doesn’t have a RemoveSnow method and responds as above.

Abstract Classes

To prevent instantiation of the base class ie if it makes no sense.

public abstract class clsDeciduous
{
 
Virtual and Override
The method may be overridden in a derived class.
 
    public virtual string RemoveSnow()
    {
        return whichType[buildingType] + ": No snow removal service available.";
    }

And in the derived class:

public override string RemoveSnow()
    {
        return "Commercial: Call Acme Snow Plowing: 803.234.5566";
    }

To prevent further inheritence use public sealed class.

Comments [0] | | # 

From msdn.

        // i is compiled as an int
        var i = 5;
 
        // s is compiled as a string
        var s = "Hello";
 
        // a is compiled as int[]
        var a = new[] { 0, 1, 2 };
 
        // person is compiled as an anonymous type
        var person = new { Name = "Terry", Age = 34 }; 
Anonymous types:
 
var v = new { Amount = 108, Message = "Hello" };

Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to first explicitly define a type

Comments [0] | | #