Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Friday, February 19, 2010

Pairing with Michael, we did our first spike from here:

http://ericdotnet.wordpress.com/2009/04/09/jquery-search-box-and-aspnet-mvc/

worked fine locally, but then going live getting some issues.  Looked like it was mateerit.co.nz/search

<script src=" <%=Url.Content("~/Scripts/jquery-1.3.2.js") %>" type="text/javascript"></script>

The above seemed to work, however the javascript seemed harder:

<script type="text/javascript">

$(document).ready(function() {
$("#searchTerm").autocomplete("/Home/getAjaxResult/");
});

</script>

so I cheated and went onto a subdomain:  jsearch.mateerit.co.nz

All works now with firebug too.

image

Comments [0] | | # 

I use vimperator, however sometimes I like to have the normal menus back.  The command I have to type is:  set guioption+=mT

Trick is to download autohotkey:

Run Autoscriptwriter (recorder)

save the file, and assign a hotkey.  In this case Windows Key, s

#s::  - set guioptions
Send, {SHIFTDOWN};{SHIFTUP}set{SPACE}guioptions{SHIFTDOWN}={SHIFTUP}=m{SHIFTDOWN}t{SHIFTUP}{ENTER}

#t:: – tv on

#8:: - 85hz

Then put the files in the startup script directory: C:\Documents and Settings\dave\Start Menu\Programs\Startup

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

http://www.mikesdotnetting.com/Article/128/Get-The-Drop-On-ASP.NET-MVC-DropDownLists

1) SelectListItem – Value and Text property assigned

var db = new northwindDataContext();
IEnumerable<SelectListItem> items = db.Categories.Select(c => new SelectListItem {Value = c.CategoryID.ToString(), Text = c.CategoryName});
ViewData["CategoryID"] = items;
 
in the view:
<%= Html.DropDownList("CategoryID") %>

which is the pretty much the same as:
 
<%= Html.DropDownList("CategoryID", (IEnumerable<SelectListItem>)ViewData["Categories"]) %>

2) SelectList is tidier, and gives a couple of overloads including selected (in the case below number 3):
 
var query = db.Categories.Select(c => new {c.CategoryID , c.CategoryName});
ViewData["Categories"] = new SelectList(query.AsEnumerable(), "CategoryID", "CategoryName",3);

image
 

PostBack

On the product view:

<% using (Html.BeginForm(null, null, FormMethod.Post, new { id = "TheForm" })) {%> 
<%=Html.DropDownList("CategoryID", (SelectList)ViewData["Categories"], new { onchange="this.form.submit();"})%>
<%}%>

and the product controller:

public ActionResult Index(int? categoryid)
{
var db = new northwindDataContext();

var query = db.Categories.Select(c => new {c.CategoryID, c.CategoryName});
ViewData["Categories"] = new SelectList(query.AsEnumerable(), "CategoryID", "CategoryName");

List<Product> products;
if (categoryid == null)
products = db.Products.ToList();
else
products = (from p in db.Products
where p.CategoryID == categoryid
select p).ToList();
return View(products);
}

which gives:
 
image 
Used LinqToSQL.
ASP.NET MVC version 1
 

Run Implementation

Found I had to sort a generic list
 
The crowd goes wild:
image
Comments [0] | | # 
# Monday, February 15, 2010

Both my asp.net web hosters advertised they are hosting on Server 2008, which meant IIS7.  This makes things much easier when publishing an MVC site (to do with routing apparently).  As I’d hosted my sites for years with these providers, they were still on Win2003 (IIS6) boxes.  I just had to ask for an upgrade and it was done.

Upload to IIS7 and it just works!

The first step was to see if routing worked on the default website.. it did!

The next step – to publish up the NerdDinner app I’ve been going through on Rob Conery, and get the database connected live.

image

The crowd goes wild  - this is live and connecting to a database :-)

Changing Namespace / Solution Name / Project Names

I had lots of namespace errors.. forgot to change default assembly namespace, which meant linq to sql was in the wrong space.  However it is possible to change everything very quickly – solution, project names, directly.  One gotcha was remembering to delete everything on the live server so there weren’t 2 dll’s with the same object names inside..

Changing Default Page to Activity / upload live trick

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Activity", action = "Index", id = "" } // Parameter defaults
);

Change controller = “Home” to controller = “Acitivity”

I also implemented the copyifnewer.bat trick for easily going from dev to live which is here: http://www.programgood.net/2010/01/28/WebConfigAutomatingDevAndLive.aspx

Run application working live with Create, Read, Update and Delete working.  Also validation, which comes for free in the standard templates.

image

DropDownList and Postbacks – covered in another post on this site.

http://www.mikesdotnetting.com/Article/128/Get-The-Drop-On-ASP.NET-MVC-DropDownLists

Summary Page

I created another link in the master page for menu item:

www.mateerit.co.nz/run

image

For the summary page I’m considering a ViewModel approach.

Lets see if a simple new Summary controller will suffice

Got to a stage.. was going to upload to github, but had db connection strings in there which didn’t want in the history.. so looked at rebase in git.. want to make sure before I play too much :-)

 

Creating a SQL View then Displaying it

Michael came up with an elegant solution which I’m trying.. so creating a SQL View:

SELECT     personid,    
DATEPART(week, date) AS Week,
DATEPART(year, date) AS Year,
SUM(kilometres) AS kilometres,
SUM(hours) AS hours
FROM dbo.Activity
GROUP BY personid, DATEPART(week, date), DATEPART(year, date)

which gives a good summary output:

image

The aim is to be able to see the summary of each week like this (this is the old webforms version)

image

linq to sql generated classes off the view.

Michael did it like this:

image

I’m on this:

image

Passing Complex Data – Lists within Lists

As each person has data associated to them, a list within a list is good.

image

public class WeekSummary
{
public int Personid;
public string Personname;
public List<WeekSummaryData> Persondata;
}

public class WeekSummaryData
{
public double? Hours;
public double? Kilometers;
public int? Week;
public int? Year;
}

Then in the repository:

public IQueryable<WeekSummary> GetWeeklySummary()
{
var weekSummaries = from p in db.Persons
orderby p.personname
let data = GetWeeklySummaryData(p.personid)
select new WeekSummary {Personid = p.personid,
Personname = p.personname,
Persondata = new List<WeekSummaryData>(data)};
return weekSummaries;
}

IQueryable<WeekSummaryData> GetWeeklySummaryData(int personid)
{
var summary = from w in db.weekly_summaries
where w.personid == personid
orderby w.Year , w.Week
select new WeekSummaryData {Hours = w.hours,
Kilometers = w.kilometres,
Week = w.Week,
Year = w.Year};
return summary;
}

** understand this linq

Then in the controller:

public ActionResult Index()
{
var summaries = _repository.GetWeeklySummary();
return View(summaries);
}

and the view:

** understand this rendering

<% foreach (WeekSummary weekSummary in Model) {
%>
<table>
<tr>
<th></th>
<% foreach (WeekSummaryData weekSummaryData in weekSummary.Persondata) { %>
<th><%=Html.Encode(weekSummaryData.Week) + "/" + Html.Encode(weekSummaryData.Year) %></th>
<%}%>
</tr>
<tr>
<td>
<%=Html.Encode(weekSummary.Personname) %>
</td>
<% foreach (WeekSummaryData week in weekSummary.Persondata) { %>
<td><%=Html.Encode(week.Hours) + "hrs" %><br /><%=Html.Encode(week.Kilometers) + "kms" %></td>
<%}%>
</tr>
</table>
<% } %>

 

refactor code with an interface for testing

unit test do

automock

jquery

tooling to help make form crud websites faster…

reproting tooling

mvc2

Comments [0] | | # 
# Friday, February 12, 2010

While pair programming with some great developers I asked the question:  How would you refactor this project (the running project website).

When both of the guys I paired with suggested that it would be smart to move to MVC and to use an ORM, I listened.

After downloading ASP.NET MVC version 1.  I’ve been working through the tutorial from Rob Conery:

http://www.asp.net/learn/mvc-videos/video-8143.aspx (about 80mins)

Creating a New MVC Project

Ctrl Shift N

Linq to SQL

image

going to use Membership for login / users.

In models, add new item: LINQ to SQL

drag on the two tables

image

Original table name was dinners.  The class is called dinner

Renamed NerddinnerDataContect to DB, and context namespace to Nerddinner

however Entity Namespace to Nerddinner.Model – which didn’t work!  I left it blank.

Adding a Controller

The default Index controller

var db = new DB();
var dinners = db.Dinners;
return View(dinners);

Adding a View

right click inside method in controller

Create strongly-typed view

View content – code gen nice.

Tooling figured out which is the primary key (as linq to sql)

 

ModelBinders - Add

When creating a new Dinner, we use ModelBinders.. mvc looks at the Object and sees if it can bind to the linqtosql.

Could have used the existing FormCollection, but this is easier!

If ModelState.IsValid   .. nice.

image

And by changing the Html.ValidationMessage

image

Editing Data

In the controller:

public ActionResult Edit(int id)
{
var db = new DB();
var dinner = db.Dinners.SingleOrDefault(x => x.DinnerID == id);
return View(dinner);
}

This is another way of expressing the above:

public ActionResult Edit(int id)
{
var db = new DB();
//var dinner = db.Dinners.SingleOrDefault(x => x.DinnerID == id);
var dinner = (from a in db.Dinners
where a.DinnerID == id
select a).SingleOrDefault();

return View(dinner);
}

<% gator tags

Other view engines – Spark or nHaml

image

So we’ve built scaffolding.

Routing

We want /dinners to the be root of the site.

Routing is the thing that listens for URL’s and passes them to a controller.

eg Dinner / Edit /5

eg { controller} / {action} / {id}

To change to be /dinners as the route in global.asax

static public void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Dinner", action = "Index", id = ""} // Parameter defaults
);
}

We changed from Home to Dinner above.

Deleting

image

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int id)
{
var db = new DB();
var dinner = (from a in db.Dinners
where a.DinnerID == id
select a).SingleOrDefault();
db.Dinners.DeleteOnSubmit(dinner);
db.SubmitChanges();

return RedirectToAction("Index");
}

are wired up on the view:

<% using (Html.BeginForm("delete", "dinner")) {%>
<%=Html.Hidden("id",Model.DinnerID) %>
<input id="Submit1" type="submit" value="delete" />
<% } %>

We are not using any authentication to stop people doing this at the moment. For that we need:

[AcceptVerbs(HttpVerbs.Post)]
[Authorize(Roles="Administrator")]
public ActionResult Delete(int id)
{
var db = new DB();

Testing / Repository Pattern

Because the controller has database connection inside of it, this isn’t good from a testing point of view, so we’re going to refactor this out.

Speed would be a problem with lots of tests, as would not knowing what is in the database.

Created an IDinnerRepository interface:

public interface IDinnerRepository
{
IQueryable<Dinner> FindAllDinners();
Dinner GetDinner(int id);
void Add(Dinner dinner);
void Update(Dinner dinner);
void Delete(Dinner dinner);
void Save();
}

Then a SqlDinnerRepository that implements this, where the constructors calls the DB:

public class SqlDinnerRepository : IDinnerRepository
{
DB db;

public SqlDinnerRepository()
{
db = new DB();
}

public IQueryable<Dinner> FindAllDinners()
{
return db.Dinners;
}

public Dinner GetDinner(int id)
{
var dinner = (from a in db.Dinners
where a.DinnerID == id
select a).SingleOrDefault();

return dinner;
}

Then in the Dinner Controller:

public class DinnerController : Controller
{
IDinnerRepository _repository;

public DinnerController()
{
_repository = new SqlDinnerRepository();
}

// this will be the one that the test uses
public DinnerController(IDinnerRepository repository)
{
_repository = repository;
}

//
// GET: /Dinner/
public ActionResult Index()
{
//var db = new DB();
//var dinners = db.Dinners;
var dinners = _repository.FindAllDinners();
return View(dinners);
}

The plan is that we will make up something that implements IDinnerRepository when testing to make our life easier.

DSCN1379_dave

Made: FadinnerkeDinnerRepository

Made: DinnerControllerTests

Ctrl R T – Run tests

Found error in test code:

 //var data = result.ViewData.Model as IList<Dinner>; // this didn't work.. hmmmmmmm.
var data = result.ViewData.Model as IEnumerable<Dinner>;

TDD

Made a test that dinners should only return dates that are today or later:

[TestMethod]
public void Index_Should_Return_Dinners_For_Today_Or_Later() {
// Arrange
var controller = new DinnerController(new Fakes.FakeDinnerRepository());

// Act
//ViewResult result = (ViewResult) controller.Index();
var result = controller.Index() as ViewResult;

// Assert
var data = result.ViewData.Model as IEnumerable<Dinner>;
Assert.IsFalse(data.Where(x=>x.EventDate<DateTime.Now).Count()>0);
}

Failed the test, then wrote the code which was in the DinnerController:

var dinners = _repository.FindAllDinners().Where(x=>x.EventDate >= DateTime.Now);

 

Lambda expressions

var dinners = _repository.FindAllDinners().Where(x=>x.EventDate >= DateTime.Now);

 

Presentation Model Pattern or View Model

45min into Rob’s video.

Comments [0] | | # 

No error.  Just closes when using ASP.NET MVC

http://stackoverflow.com/questions/1361291/resharper-r-4-5-and-mvc-1-0-solutions-cause-visual-studio-2008-sp1-to-crash

then onto:

http://stackoverflow.com/questions/500696/why-does-visual-studio-crash-opening-aspx-with-mvc-rc1

Have tried the one above, which seems to work so far.

[Edit] it didn’t.. so now I’m trying this:

https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=16827&wa=wsignin1.0

Something still weird as locking up when loading assemblies (looks like resharper)  am trying resharper5 beta2 to see if that helps (haven’t got correct license).  I can get around lockup by deleting dlls from bin and obj.

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

Static classes are usually used as ‘utility’ classes

You don’t need an instance

 

class Program
{
static void Main()
{
double result = thing.daveSubtract(10);
Console.WriteLine(result);
}
}

static class thing
{
static public double daveSubtract(double number)
{
return (number - 2);
}
}

Extension Methods

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, 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] | | #