Monday, December 20, 2010

Object Oriented Programming (OOP) 1 - some resources

Object Oriented Programming is a way of bundling up large amounts of code into something that is easier to understand, and hopefully use. The code is called "classes" and when you create an "instance" of that class, it becomes an "object".

The examples I used in our class work at college, I referred to classes as "cookie cutters" that give us the "shape". Each time we press the cookie cutter into the cookie dough, we create a cookie "object" which we can decorate with sprinkles and candy.

In it's simplest form, classes are the "templates" of our objects. Classes can contain "properties" (the values we can read and/or change), "methods" (actions than can be performed), and in VisualBasic.NET there are also "events" that can be raised with event handlers (but to be honest, this is really only useful for User Controls).

Here's an example.

Say we have a "Car" class. We can create an "instance" (or a single car) from this class. Like this, and do things with it:

Dim myCar as Car
myCar = new Car()
myCar.Brand = "Toyota"
myCar.Model = "Camry"
Console.WriteLine(myCar.Wheels()) 'COMMENT: this displays "4"
myCar.Drive(10) 'COMMENT: the speed is "10"
myCar.ChangeDirection("left", 45) 'COMMENT: turn left at 45 degrees
myCar.Stop()

Lets look at that more closely:

Dim myCar as Car

just tells VB.NET to reserve enough RAM (memory) to put a "Car" object inside it. NOTE: this does not (yet) create the object. This also gives a name within the code to call our car ("myCar").

myCar = new Car()

This creates the object - the instance of our class. The word "new" is important because this is the "constructor" - the special Function or Sub that will be run to start our object. It is the perfect place to set values to create our object (like read a database to get values). NOTE: you don't have to create your own Sub called NEW - VB.NET will create an empty one for you and use that instead. This is called an "implied constructor". If you create your own "New()" sub that is an "Explicit constructor".

REMEMBER: a constructor is simply a function or sub that is run when you create your new object for the first time.

You can also write those two lines of code as one line like this:

Dim myCar as Car = new Car()

The next two lines are setting some property values:

myCar.Brand = "Toyota"
myCar.Model = "Camry"

This sets the "Brand" property to "Toyota" and the "Model" property to "Camry".

You can also read property values:

Console.WriteLine(myCar.Wheels()) 'COMMENT: this displays "4"

where "Wheels()" is a property and in this case is used to get how many wheels the car has and displays it to the screen.

REMEMBER: Properties are just values for our objects that we can "set" (write) and "get" (read). For a "Person" class, some properties could be "FirstName" or "LastName".

The next three lines are some of our classes "methods"

myCar.Drive(10) 'COMMENT: the speed is "10"
myCar.ChangeDirection("left", 45) 'COMMENT: turn left at 45 degrees
myCar.Stop()

Methods are just Functions or Subs that are run when used in code like this. Just like normal functions and Subs you can pass in values for them to use. Here there are three Subs within our class called:

Drive(speed) which takes in "speed" as an integer to use as a parameter (argument)
ChangeDirection(direction, angle) which takes in two parameters (arguments) to successfully run this sub ("direction" as a string and "angle" as an integer)
Stop() which takes no arguments to run

REMEMBER: Methods are simply Subs that allow our object to do things. Another example could be a "Person" class which has a method called "Login(username, password) which takes two values ("username" and "password") to correctly work.

What Now?

This is just how to use Objects within our code. I will explain how to write classes later but meanwhile have a read of this:


Start here at Chapter 6 and work through until the first part of Chapter 7 where it talks about inheritance. I do not expect students to be experts at using Classes and Objects yet, but you should be able to understand what classes, objects, methods and properties are, and be able to write the "code stubs" (the starting code) when given a specification.

I will write another blog entry about inheritance later but to get you thinking, imagine our "Car" class being derived from a "Vehicle" base class. A "Motorcycle" class could also be derived from the "Vehicle" class, as could a "Truck".

A "base class" is simply a starting point that you can use to create more complex classes later (you "inherit" the base class and add to it). Not all classes need to come from base classes, and inheritance is not something you do all the time, but there are important programming ideas here that you need to understand.

REMEMBER: the whole point about Object Oriented Programming (OOP) and creating classes is to write code once and test it to make sure it is working the way you want, then you can put it aside and forget about how it works. Then you can write really simple code that uses your classes.

Be lazy: write code once and test it well: don't repeat yourself (in other words, don't rewrite your code). Try to keep your code simple in small bite-sized pieces that is easy to understand ... and use.















Saturday, December 18, 2010

IF/ELSE statements: 1

Here's an exercise on IF/ELSE, modified to pseudocode from one of the exercises in the textbook (http://visual-basic-dox.net/Prentice.Hall.PTR-An.Introduct/tindex.htm Chapter 5.2, exercise 1). It might not make sense to do If statements like this, but ignore than and just try to work out what would be displayed with different values.

What would be display with each of these numbers entered?

0
4
5
9
10

As usual, don't answer here, go to the "Pseudocode Help" forum (http://groups.google.com/group/pseudocodehelp) to answer.

Here's the pseudocode:


prompt user for a number
get number
if (number less than or equal to 9)
display ("Less than 10")
else
if (number equals 4) then
display ("Equal To Four")
end if
end if


Here is what it should code up as (NOTE: I'm guessing that is the correct code -I'm using an Apple laptop at the moment and it can't run Visual Studio)


Module Module1
Sub Main()
Console.WriteLine("Please Enter a number")
Dim num As Double = CDbl(Console.ReadLine)
If num <= 9 Then
               Console.WriteLine("Less than ten.")
       Else
              If num = 4 Then
                  Console.WriteLine("Equal to four.")
               End If
          End If
      End Sub
 End Module 

Tuesday, December 14, 2010

Test Question 1 Review 6 - Loops: what not to do

I noticed in the test some people were using a Do While (condition) with a strange condition. It's actually a bit of a worry


prompt user: "please enter a start year for the leap year range calculator"
(get startYear from the user)
prompt user: "please enter an end year for the leap year range calculator"
(get endYear from the user)
Do while (startYear <> endYear)
COMMENT: leap year logic goes here
startYear = startYear + 1
end loop


It's the startYear <> endYear part that is a concern.

Because it is a range of years it will be increasing by one every loop iteration. Yes, that's what is happening in the above pseudocode. But with the startYear "not equals to" endYear (instead looping until it no longer is "less than or equals to"), you run the risk of the loop never ending.

Imagine the test data of startYear being 1894 and endYear of 1795.

Do while (1894 <> 1795)
COMMENT: leap year logic goes here
startYear = startYear + 1
end loop

The loop will start because the condition will let it (1894 does not equal 1795) but 1894 will increase by one every time the loop is run and will never reach 1795

If you try that with "less than or equal to" (instead of "not equal to") then it won't enter the loop at all (condition not met for the first time)

Do while (1894 <= 1795)
COMMENT: leap year logic goes here
startYear = startYear + 1
end loop

which may (or may not) be acceptable (depending on the spec: the test question didn't mention anything about handling endYear being less than startYear)

REVISON WORK

Take the working code from
http://pseudocodehelp.blogspot.com/2010/12/test-question-1-review-5-final-vbnet.html
and modify the FOR NEXT loop to be a DO WHILE loop. Then change the conditions to the two different versions I have talked about here. Try it with lots of test data and see what you get. Look for "Edge cases" and try to break it (why try to break it? Because your users will try).

Post your results over on the
http://groups.google.com/group/pseudocodehelp
discussion group.

Monday, December 13, 2010

Test Question 1 Review 5 - final VB.NET and C# code

NOTE: there are many variations to solving this problem, provided they all work. This is just one way that meets the specification, and met my own criteria of not wanting to spend more than 10 minutes thinking about it. If you have other ways to do the same thing, that's great. Try it with test data of

startDate: 1495
endDate: 1605

which should show leap years every 4 years (starting with 1496 and ending with 1604) with the exception of 1500 (century non-leap) but includes 1600 (century leap).

VB.NET code:

Module Module1

Sub Main()
Console.WriteLine("please enter a start year for the leap year range calculator")
Dim startYear As Integer = CInt(Console.ReadLine())
Console.WriteLine("please enter an end year for the leap year range calculator")
Dim finishYear As Integer = CInt(Console.ReadLine())
Dim foundNotCenturyLeap As Boolean = False
Dim notCenturyLeap As String = ""

Console.WriteLine("The following years are leap years:")
For thisYear As Integer = startYear To finishYear
If (thisYear Mod 100 = 0) Then
If (thisYear Mod 400 = 0) Then
' leap year Century year
Console.WriteLine(thisYear)
Else
notCenturyLeap &= thisYear & ", "
foundNotCenturyLeap = True
End If
Else
If (thisYear Mod 4 = 0) Then
Console.WriteLine(thisYear)
End If
End If
Next
If foundNotCenturyLeap Then
Console.WriteLine("The following century years that fall within the date range and are NOT leap years are:")
Console.WriteLine(notCenturyLeap)
Else
Console.WriteLine("there are no century years that are not leap years within the range you have specified")
End If
Console.ReadLine()
End Sub

End Module


REVISION WORK:

See if you can re-write this VB.NET code into C#. You have a working prototype in another language and the pseudocode. Apart from some reference materials (hello Google), that should be all you would need. Put your answer up on the companion GoogleGroups site:

http://groups.google.com/group/pseudocodehelp

Test Question 1 Review 4 - Alternative displays of data

For thisYear = startYear to finishYear
if (thisYear divided by 100 has no remainder) then
' Century year
if (thisYear divided by 400 has no remainder) then
' leap year Century year

else
' Century but not Leap

end if
else
' all non-century years
if (divided by 4 has no remainder) then
' non-century leap years

end if
end if
Next

Now that the logic for looping through the range of years and finding century/non-century and leap/non-leap years was sorted out, it was time to work out how to display leap years before century non-leap years (since they could be all jumbled up together, depending on what year was being processed in the loop).

This means I could display leap years (normal ones and century ones) as the loop ran over each year (and worked out if it was a leap) but I needed to wait until the loop finished with all the leap years before then displaying the non-leap century years. I needed to delay those years.

The easiest thing I could think of was to create a list of these century non-leap years as a string, and, when I found one of those years, append it onto the list (concatentate that year at the end) with a simple comma "," to seperate them (eg: 1700, 1800, 1900)

add thisYear to NotCenturyLeap list
which can be written in VisualBasic.NET as

NotCenturyLeap &= thisYear & ", "
where "NotCenturyLeap" is a simple string
For thisYear = startYear to finishYear
if (thisYear divided by 100 has no remainder) then
' Century year
if (thisYear divided by 400 has no remainder) then
' leap year Century year
displayLine(thisYear)
else
NotCenturyLeap.StringAdd (thisYear & ", ")

end if
else
' all non-century years
if (divided by 100 has no remainder) then
' display only non-century leap years
displayLine(thisYear)
end if
end if
Next
I didn't bother in this case, but to do the job properly, I would have removed the last comma from that list before display (using something like VisualBasic's "left()" function or similar)

NOTE: there are many ways to do this: appending (adding to) lists, arrays, etc or even using the StringBuilder class (look it up if you want to learn more), but I wanted to keep it really simple.

The only thing left to do now was to display the alternative message if there were no non-leap century years within the rage of years. The easiest thing I could think of was a simple flag (boolean value) that was set to "FALSE" and if a non-leap century year was found, set it to true.


set found_a_nonCentuaryLeapYear to false
For thisYear = startYear to finishYear
if (thisYear divided by 100 has no remainder) then
if (thisYear divided by 400 has no remainder) then
' leap year Century year

else
set found_a_nonCentuaryLeapYear to true
end if
else
...
end if
Next


The flag could then be used to show those years or the alternative message.

if found_a_nonCentuaryLeapYear is true then
displayLine("The following century years that fall within the date range and are NOT leap years are:")
displayLine(NotCenturyLeap)
else
displayLine("there are no century years that are not leap years within the range you have specified")
end if
so the final pseudocode ended up as:
prompt "please enter a start year for the leap year range calculator"
(get startYear)
prompt "please enter an end year for the leap year range calculator"
(get finishYear)

' display the first message to the screen
displayLine("The following years are leap years:")

' now loop through all the years looking for
' - century years that are leap years (and display them)
' - century years that are NOT leap years (and add them to a string to display later)
' - non-century years that are leap years (and display them)

set found_a_nonCentuaryLeapYear to false
For thisYear = startYear to finishYear
if (thisYear divided by 100 has no remainder) then
' Century year
if (thisYear divided by 400 has no remainder) then
' leap year Century year
displayLine(thisYear)
else
NotCenturyLeap.StringAdd (thisYear & ", ")
set found_a_nonCentuaryLeapYear to true
end if
else
' all non-century years
if (divided by 100 has no remainder) then
' display only non-century leap years
displayLine(thisYear)
end if
end if
Next

if found_a_nonCentuaryLeapYear is true then
displayLine("The following century years that fall within the date range and are NOT leap years are:")
displayLine(NotCenturyLeap)
else
displayLine("there are no century years that are not leap years within the range you have specified")
end if
The next step would be to turn that into VisualBasic.NET code then into C# code (see next post).

Test Question 1 Review 3 - The processing within the loop

As most people realised, the "meat in the sandwich" of the question was based on some class work, it's just that it had a loop around it to find many leap years.

The specification says:

The current calendar, called the Gregorian calendar, was introduced in 1582.
Every year divisible by four was declared to be a leap year, with the exception
of the years ending in 00 (that is, those divisible by 100) and not divisible by
400. For instance, the years 1600 and 2000 are leap years, but 1700, 1800, and
1900 are not.
So this should be enough to calculate
  • which years are leap years
  • which years are leap years that are also century years (eg: 1600, 2000)
  • which years are century years that are NOT leap years.

The test question asks for all three to be displayed, although the leap century years are part of the leap year display.

The test question also asks for two different sections to be displayed, one after the other: first the list of leap years, then the non-leap century years. Since the processing of each year will find each jumbled up next to the other it either means running the loop twice (first for leap years, then for non-leap century years) or displaying the leap years to the screen while noting and saving the non-leap century years for display after that (but more of this later in another blog post).

The tricky part of the processing is not the leap year part (which is easy: most are divisible by 4). It is whether it is a century year that is also a leap year (or a century year that isn't a leap year).

I decided (in the 10 minutes I allocated myself to answer the question: I actually didn't have it work out when I modified the class work question) to find the century years first:

For thisYear = startYear to finishYear
if (thisYear divided by 100 has no remainder) then
' Century year

else
' all non-century years

end if
Next

This gave me the difference between century years (both leap and non-leap) and all the other years (also both leap and non-leap).

Keeping with the century years (until it was worked out), the next step was to find out which century years were leap years and which weren't:


if (thisYear divided by 100 has no remainder) then
' Century year
if (thisYear divided by 400 has no remainder) then
' leap year Century year

else
' Century year but not Leap

end if
else

With the century years all taken care of, it was time to move on to all non-century years and work out which were leap years and which ones were not:


else
' all non-century years
if (divided by 4 has no remainder) then
' non-century leap years

end if
end if

so, the resulting logic for the three types of years I was looking for (leap years, century leap years and century non-leap years) ends up as

For thisYear = startYear to finishYear
if (thisYear divided by 100 has no remainder) then
' Century year
if (thisYear divided by 400 has no remainder) then
' leap year Century year

else
' Century but not Leap

end if
else
' all non-century years
if (divided by 4 has no remainder) then
' non-century leap years

end if
end if
Next

The next blog post will deal with the two different sections that need to be displayed

Test Question 1 Review 2 - The Loop

As mentioned in the previous post, the test question asked for a program for the user to enter a range of years and it would list the leap years as well as the century years that are not leap years.

What can be worked out from the specification is that "startYear" and "endYear" are values entered by the user for processing (and will be variables in the code), and a "range of years" which means going from "startYear" to "endYear" by one year at a time. All the variables will be integers.

This means a loop.

There are a couple of choices. One obvious choice is a "Do While(condition)" loop that has a variable set at the "startYear" and with a "startYear = startYear + 1" within the loop, with the loop finishing when it reaches the "endYear". Something like this:

prompt user: "please enter a start year for the leap year range calculator"
(get startYear from the user)
prompt user: "please enter an end year for the leap year range calculator"
(get endYear from the user)

Do while (startYear <= endYear)
COMMENT: leap year logic goes here
startYear = startYear + 1
end loop
But that's not the only choice available. Because the loop is increasing the years by one every time, a simple FOR NEXT loop will work just as well.

prompt user: "please enter a start year for the leap year range calculator"
(get startYear from the user)
prompt user: "please enter an end year for the leap year range calculator"
(get endYear from the user)

FOR thisYear = startYear to endYear
COMMENT: leap year logic goes here (using thisYear to process)
NEXT
FOR NEXT loops don't have to start from zero (or even one for that matter). They just need some continous range of values and they will automatically loop and increase until the end condition is met.

Test Question 1 Review 1 - reading specifications.


The current calendar, called the Gregorian calendar, was introduced in 1582. Every year divisible by four was declared to be a leap year, with the exception of the years ending in 00 (that is, those divisible by 100) and not divisible by 400. For instance, the years 1600 and 2000 are leap years, but 1700, 1800, and 1900 are not.

Write a program that requests a range of years as input and displays that year to the screen if it is a leap year, as well as list of years that are "century years" (those divisible by 100) but are NOT leap years

Please follow this specification exactly:

the first message to the user to prompt for the first of the two inputs is:

"please enter a start year for the leap year range calculator"

the second message to the user to prompt for the second of the two inputs is:

"please enter an end year for the leap year range calculator"

the display for the date range needs to be in this format:

"The following years are leap years:"
1596
1600
1604
1608


the display for the list of years that fall within the year range that are NOT leap years needs to be in this format:

"The following century years that fall within the date range and are NOT leap years are:"
1500, 1700, 1800

if there are no century years that are not leap years to be displayed, the following message needs to be displayed instead:

"there are no century years that are not leap years within the range you have specified".

NOTE: there are two sections to display: the list of leap years within the specified year range with the years listed vertically (down the screen) and a list of century years within the specified year range that are NOT leap years, listed horizontally (across the screen).



During the recent exam, many people were strugging with this question. This blog entry will cover the reading of a specification and how to interpret it to start to solve the problem and provide a solution.

Later blog entries will explain further how to come up with the pseudocode to then create the program.

Here is one way of interpreting the specification to get going.

1: Read carefully to understand what is being asked: don't assume.

The question is an adaptation (modification) of one of the questions from the textbook. Some students assumed it was exactly the same question and simply submitted their class work as a solution: sorry, but it wasn't the same question so that wasn't going to be the answer.

2: Look for inputs and outputs.

The question says that there are two inputs and even provides the text (the words) to use to display a message to the user to ask for their input.

the first message to the user to prompt for the first of the two inputs is:

"please enter a start year for the leap year range calculator"

the second message to the user to prompt for the second of the two
inputs is:

"please enter an end year for the leap year range calculator"

So, since this is a Console application, that means two prompts (Console.WriteLine()) and two inputs from the user (Console.ReadlLine()).

What the specification also says is that the input is "a range of years" and mentions a "start year" and an "end year". This is important to what is required for processing: a range is (in this case) a continous group of years starting from the "start year" and finishing at the "end year". This could mean some processing within a loop, starting from the "start year" and finishing at the "end year". NOTE: condition to end exactly on the "end year" (and not the year before) is implied because it didn't mention anything about it finishing the year before the end year (but more about this loop in a later blog post).

There are two sections to display but three messages, so this should alert you to the need that there is an "IF" statement needed somewhere in the output, and that may influence the processing needed for the solution.

NOTE: there are two sections to display: the list of leap years within the
specified year range with the years listed vertically (down the screen) and a
list of century years within the specified year range that are NOT leap years,
listed horizontally (across the screen).

The first section has the format provided for you to make sure your program does what the specification asks:

"The following years are leap years:"
1596
1600
1604
1608

which also says what the text to display should say.

The specification states that the second section has a particular display as well:

the display for the list of years that fall within the year range that are NOT
leap years needs to be in this format:

"The following century years that
fall within the date range and are NOT leap years are:"
1500, 1700, 1800

and it says that there is an alternative display under certain conditions (which means an "IF" statement based on some condition):

if there are no century years that are not leap years to be displayed, the
following message needs to be displayed instead:

"there are no century
years that are not leap years within the range you have specified".

3: Look for the "Meat in the sandwich"

The expression "Meat in the sandwich" means "the tasty part" or main section of the processing, which is the logic to work out which years are leap years and which ones are not. There are leap years to be found, and "century years" that are not leap years.

4: Put all the bits together

So, by carefully reading the specification, you can find out the following things to start to come up with a solution:

  • There are two prompts to the user, and two pieces of data to use ("start year" and "end year").
  • There are leap years to be found, and "centuryYears" that are not leap years.
  • There is logic provided to work out what is a leap year.
  • there is a range of years, which could mean a loop with processing within it. The loop will go from "startYear" to "endYear" continously, checking each year to see if it is what is needed for the output.
  • there are two sections as part of the output, which means two different processing of the range of years (or at least two different parts of processing, perhaps with an "IF" within the loop)
  • there is some "either this one or that one" to do with the second part of the display ("there are no century years ...")

and that should be enough to get going with the pseudocode.

Welcome

Hello.

Chances are you are here because you have been one of my programming students. Chances are you have been struggling to understand programming.

This blog site will help, but it won't do everything for you. Only you can spend the effort to understand how to program. All I can do is provide some guidance.

I will be posting up some pseudocode and programming exercises for you to work through, analyise and attempt in your own time.

Remember, the basic role of programming is solving problems. Using simple pseudocode will capture or record your ideas so you can then turn it into code.

I still maintain that basic programming is easy. It's just a way of thinking to solve problems. Once the programming logic is correct then it can be converted to real code using reference books and other code syntax help. The hard part is to think in a logical way that will help you solve those problems.

Barry Beattie.

P.S: there is a discussion group set up for you to ask programming topics and questions. It can be found at

https://groups.google.com/group/pseudocodehelp