tags:

views:

435

answers:

14

I'm teaching/helping a student to program.

I remember the following process always helped me when I started; It looks pretty intuitive and I wonder if someone else have had a similar approach.

  1. Read the problem and understand it ( of course ) .
  2. Identify possible "functions" and variables.
  3. Write how would I do it step by step ( algorithm )
  4. Translate it into code, if there is something you cannot do, create a function that does it for you and keep moving.

With the time and practice I seem to have forgotten how hard it was to pass from problem description to a coding solution, but, by applying this method I managed to learn how to program.

So for a project description like:

A system has to calculate the price of an Item based on the following rules ( a description of the rules... client, discounts, availability etc.. etc.etc. )

I first step is to understand what the problem is.

Then identify the item, the rules the variables etc.

pseudo code something like:

function getPrice( itemPrice, quantity , clientAge, hourOfDay ) : int 
   if( hourOfDay > 18 ) then
      discount = 5%

   if( quantity > 10 ) then
      discount = 5%

   if( clientAge > 60 or < 18 ) then
      discount = 5%


        return item_price - discounts...
end

And then pass it to the programming language..

public class Problem1{
    public int getPrice( int itemPrice, int quantity,hourOdDay ) {
        int discount = 0;
        if( hourOfDay > 10 ) {
             // uh uh.. U don't know how to calculate percentage... 
             // create a function and move on.
            discount += percentOf( 5, itemPriece );
            .
            .
            .
            you get the idea..

        }
     }
    public int percentOf( int percent, int i ) {
             // .... 
    }


}

Did you went on a similar approach?.. Did some one teach you a similar approach or did you discovered your self ( as I did :( )

+2  A: 

I did something similar.

  • Figure out the rules/logic.
  • Figure out the math.
  • Then try and code it.

After doing that for a couple of months it just gets internalized. You don't realize your doing it until you come up against a complex problem that requires you to break it down.

J.J.
Did someone teach you, or did you discover it by your self?
OscarRyz
No one explicitly said it like that. But it was implied or layed out when they tried to teach us pseudo code in our C++ 101 class. I say "tried" because many students immediately saw pseudo code as the same thing as real code, and discarded it as useless.
J.J.
+1  A: 

Wishful thinking is probably the most important tool to solve complex problems. When in doubt, assume that a function exists to solve your problem (create a stub, at first). You'll come back to it later to expand it.

Martin Cote
OscarRyz
+8  A: 

I go via the test-driven approach.

1. I write down (on paper or plain text editor) a list of tests or specification that would satisfy the needs of the problem.

- simple calculations (no discounts and concessions) with:
 - single item
 - two items
 - maximum number of items that doesn't have a discount
- calculate for discounts based on number of items
 - buying 10 items gives you a 5% discount
 - buying 15 items gives you a 7% discount
 - etc.
- calculate based on hourly rates
 - calculate morning rates
 - calculate afternoon rates
 - calculate evening rates
 - calculate midnight rates
- calculate based on buyer's age
 - children
 - adults
 - seniors
- calculate based on combinations
 - buying 10 items in the afternoon

2. Look for the items that I think would be the easiest to implement and write a test for it. E.g single items looks easy

The sample using Nunit and C#.

[Test] public void SingleItems()
{
    Assert.AreEqual(5, GetPrice(5, 1));
}

Implement that using:

public decimal GetPrice(decimal amount, int quantity)
{
    return amount * quantity; // easy!
}

Then move on to the two items.

[Test]
public void TwoItemsItems()
{
    Assert.AreEqual(10, GetPrice(5, 2));
}

The implementation still passes the test so move on to the next test.

3. Be always on the lookout for duplication and remove it. You are done when all the tests pass and you can no longer think of any test.

This doesn't guarantee that you will create the most efficient algorithm, but as long as you know what to test for and it all passes, it will guarantee that you are getting the right answers.

jop
Wow!.. did you learn all that from the very beginning ?
OscarRyz
Oh, I wish I had! Someone thought me the basics (list the inputs and outputs and implement it one by one) but never mentioned the most important 3rd part - refactor.
jop
Excellent TDD example. Are there any good resources you've used to further this type of style?
Gavin Miller
YAGNI would have said to ignore quantity in the initial implementation - because the simplest thing that could possibly work would be just to return amount - then the second test would have failed, driving the design of GetPrice() instead of just confirming it.
Carl Manaster
Thanks Carl, but I would have to disagree with YAGNI in this case as the code is just too simple. I reserve YAGNI to paralyzying problems or more complicated situations.
jop
A: 

Keep in mind, if you get 5% off then another 5% off, you don't get 10% off. Rather, you pay 95% of 95%, which is 90.25%, or 9.75% off. So, you shouldn't add the percentage.

stalepretzel
Well this is just an example, but.. no. Actually if you get 10%. Say Item value is 100, (5% of 100 = 5) + (5% of 100 = 5) thus 5 + 5 = 10. The function would return the percent of the unmodified prices.How did you started from problem description to code anyway?...
OscarRyz
Yes, but things usually don't work like that. If you take 5% off, you'd get 95, and if you took another 5% off, you'd get 90.25.
stalepretzel
+1  A: 

A good book for beginners looking for a process: Test Driven Development: By Example

Nescio
A: 

Yes.. well TDD did't existed ( or was not that popular ) when I began. Would be TDD the way to go to pass from problem description to code?... Is not that a little bit advanced? I mean, when a "future" developer hardly understand what a programming language is, wouldn't it be counterproductive?

What about hamcrest the make the transition from algorithm to code.

OscarRyz
+4  A: 

the old-school OO way:

  • write down a description of the problem and its solution
  • circle the nouns, these are candidate objects
  • draw boxes around the verbs, these are candidate messages
  • group the verbs with the nouns that would 'do' the action; list any other nouns that would be required to help
  • see if you can restate the solution using the form noun.verb(other nouns)
  • code it

[this method preceeds CRC cards, but its been so long (over 20 years) that I don't remember where i learned it]

Steven A. Lowe
+2  A: 

I start at the top and work my way down. Basically, I'll start by writing a high level procedure, sketch out the details inside of it, and then start filling in the details.

Say I had this problem (yoinked from project euler)

The sum of the squares of the first ten natural numbers is, 1^2 + 2^2 + ... + 10^2 = 385

The square of the sum of the first ten natural numbers is, (1 + 2 + ... + 10)^2 = 55^2 = 3025

Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 385 = 2640.

Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

So I start like this:

(display (- (sum-of-squares (list-to 10))
            (square-of-sums (list-to 10))))

Now, in Scheme, there is no sum-of-squares, square-of-sums or list-to functions. So the next step would be to build each of those. In building each of those functions, I may find I need to abstract out more. I try to keep things simple so that each function only really does one thing. When I build some piece of functionality that is testable, I write a unit test for it. When I start noticing a logical grouping for some data, and the functions that act on them, I may push it into an object.

Jonathan Arkell
Interesting ? .. Where do you do that? I mean, at work, school? ..
OscarRyz
My method i use in any of my programming projects, be it for work, fun, or whatever.
Jonathan Arkell
+3  A: 

when learning programming I don't think TDD is helpful. TDD is good later on when you have some concept of what programming is about, but for starters, having an environment where you write code and see the results in the quickest possible turn around time is the most important thing.

I'd go from problem statement to code instantly. Hack it around. Help the student see different ways of composing software / structuring algorithms. Teach the student to change their minds and rework the code. Try and teach a little bit about code aesthetics.

Once they can hack around code.... then introduce the idea of formal restructuring in terms of refactoring. Then introduce the idea of TDD as a way to make the process a bit more robust. But only once they are feeling comfortable in manipulating code to do what they want. Being able to specify tests is then somewhat easier at that stage. The reason is that TDD is about Design. When learning you don't really care so much about design but about what you can do, what toys do you have to play with, how do they work, how do you combine them together. Once you have a sense of that, then you want to think about design and thats when TDD really kicks in.

From there I'd start introducing micro patterns leading into design patterns

Keith Nicholas
Yeah.. I think this would be definitely the 2nd step.
OscarRyz
"having an environment where you write code and see the results in the quickest possible turn around time is the most important thing" - That's TDD. Write test, run it and see it fail. Implement the code and see it succeed.
jop
Likewise, "go from problem statement to code instantly" is TDD: code the _problem_ because it's a more direct mapping. Once the _problem_ is expressed in code, its solution can be verified.
Carl Manaster
+1  A: 

My dad had a bunch of flow chart stencils that he used to make me use when he was first teaching me about programming. to this day I draw squares and diamonds to build out a logical process of how to analyze a problem.

Nathan Feger
Just like rinding in bicycle. Once you learn it, you don't forget it.
OscarRyz
+2  A: 

I've enjoyed TDD every since it was introduced to me. Helps me plan out my code, and it just puts me at ease having all my tests return with "success" every time I modify my code, letting me know I'm going home on time today!

Shahin
+1  A: 

I think there are about a dozen different heuristics I know of when it comes to programming and so I tend to go through the list at times with what I'm trying to do. At the start, it is important to know what is the desired end result and then try to work backwards to find it.

I remember an Algorithms class covering some of these ways like:

  • Reduce it to a known problem or trivial problem
  • Divide and conquer (MergeSort being a classic example here)
  • Use Data Structures that have the right functions (HeapSort being an example here)
  • Recursion (Knowing trivial solutions and being able to reduce to those)
  • Dynamic programming

Organizing a solution as well as testing it for odd situations, e.g. if someone thinks L should be a number, are what I'd usually use to test out the idea in pseudo code before writing it up.

Design patterns can be a handy set of tools to use for specific cases like where an Adapter is needed or organizing things into a state or strategy solution.

JB King
A: 

wat s the formula for discount rate? in pseudo code (java)

jean-Ronald
A: 

I think there's a better way to state your problem.

Instead of defining it as 'a system,' define what is expected in terms of user inputs and outputs.

"On a window, a user should select an item from a list, and a box should show him how much it costs."

Then, you can give him some of the factors determining the costs, including sample items and what their costs should end up being.

(this is also very much a TDD-like idea)

kyoryu