Thursday, May 7, 2009

Final Refractoring Thoughts

Refractoring is nice tool to use, I probably won't use it constantly like I would unit tests but it really does help to clean up code.  Like the other day I ended up writing about 30 if statements in a row for one particular attribute that I was working on.  It ended up being about 200 lines for all of it and would only return a single value back.  I then had to do this two more times for 2 different attributes.  It made the code look terrible and I had no idea where one thing started and the other stopped.  So I used extract method on all three of those things and shoved it into a new file to hold it.  Then again I did extract method on them and then put all of the if statements related to one attribute in its own method.   Stuff like this there really isn't a big deal.  It's more of a stylistic thing and it does help make hard to follow code look way better.  Doing stuff like this doesn't really have an performance gains or hurts the performance of the application so it's not a big deal.

On the other hand, performance is a big deal.  I do believe that if you use extract method several times with small amounts of code in it over a large block of code it hurts performance by a small amount.  But when this code is called constantly and the application depends on it running super fast everything slows down significantly.  There are times when OOP is critical to be used but having ugly code that runs in 0.0000003 seconds compared to 0.01 seconds and it is being called over a billion times, I'd much rather prefer the horrifying looking code than something that is amazing looking but takes forever.  I'd much rather have Windows move files in less than a minute compared to an hour.

Job security is one of the other things that comes to mind.  If you write code that no one else can understand, you are less likely to be fired.  If you have something that looks like it is summing up some data but in reality is just sorting that data and the comments make zero sense, then that is job security.  It doesn't mean that if you write horrible looking code constantly, that could easily be written very nicely, is a good idea.  It just means that if there is some function that ties the whole system together and you are the only one who knows how it works and where to add/remove things that is pretty good.

The book on refractoring does have some really useful ideas for one to use after they have written the code or having to make changes to existing code later.  I know for sure I won't be writing code and then spontaneously decide to "Replace Type Code with State/Strategy".  I'd much rather have the code working perfectly first then clean it up.

This is the last CS 373 blog entry I'm going to write.  So to any hardcore followers, you should know where to find me on the internet.

Wednesday, May 6, 2009

Pro/Cons of Python

This is somewhat of a recap of what I have learned about Python this semester and what I like about it and what I hate about it.

Likes:
Generators:  Are super awesome.  They remove some of the trouble of having to keep track of an array or something that is iterable and then keep track of which spot you are at.  Instead with a generator, all you need to do is call next() and you get the next thing.  This is easily one of my most favorite things in python.

List Operations:  with stuff like [0: 5] it makes getting a sub array out of an array easy to do.  With it being able to start at the end and then work backwards is great as well.  Just to get the last element, using arr.length()-1 as the index instead makes it somewhat more readable and easier to do.

Print:  Just saying print "something"  instead of System.out.println("something");  is so much better just because it requires less typing.  And really the whole "System.out" part I hate typing because of its redundancy.

Dynamic Typing:  s="A string" I know s is a string, why should I have to type String s = "A string";  And then if I am done with s being used I could do s=67/3.  

Hates:
Dynamically Typed:  I absolutely hate it how if in a method one of its parameters is an object "A" and what is actually needed is an object "B" and then when it is used DURING RUNTIME we get the error.  This actually makes things more difficult to figure out what is going on  during runtime to pinpoint when "A" is actually being passed in.  And it could be at the end of the program making me retrace every line of code.

Indention:  I hate this.  While it seems nice to do after a while  I lose track of how the code flows and when if statements end or functions end.  I really like the enforced indentation but without nice "{" "}" I can't tell the difference between some lines of code and when to debug things.

Arrays:  I don't know why I can't create an array with a set size.  I hate having to create a while loop and then iterate over it appending useless data to the array just to get the array into a desirable size.  Which makes me hate it when I'm going through the array after finally using it and I hit one of the "dummy data" indexes and then python either: Uses that data and screws things up. Or: Treats it as an object and then throws me an error and then screw things up.

For Loops:  Where are they?  Sometimes I need to be able to iterate over something with a size that changes and using a while loop is just not good enough.  I hate having to create a lcv and setting it to 0 before the execution of the while loop and then in the end I always forget to increment/decrement it.

So those are some nice rants about how much I have enjoyed Python and how much I despise Python.  I really would not suggest using Python in a large scale project.  It makes a really well developed script but sometimes debugging things in it seems too hard to do in a large project where the complexity in increased 10000x over.

Thursday, April 30, 2009

Explaining MoisUnn

MoisUnn is a groundbreaking programming language that has just recently been launched. So not many people know about it. It is very similar to Java/C++ in some of its syntax and borrows some from Python.

The main features of MoisUnn are the ability to do concurrent assignments, powerfull list operations and multiple returns.

Concurrent Assignments:
Originally to get some thing like:
int a=5; int b=0;
int a_old=a;
a= a+5; b=a_old;
//a=10, b=5

In this better way:
int a=5; int b=0;
a,b=a+5,a;
//a=10, b=5

So the ability to write less code that is more powerful becomes evident.

List Operations:
There are some math operations you should be familiar with: +,-,/,*,%. MoisUnn introduces ^ as the exponent operator.
You can apply a single arithmetic operation on a list, or use a list to do math on another list.
EX:
to add 1 to every element in a list:
int list=[1,2,3,4,5];
for(int i=0; i less than list.size(); i++)
list[i]=list[i] +1;
//list=[2,3,4,5,6]
But in MoisUnn, it is:
array of int x: [1,2,3,4,5];
x=x+1;
//x=[2,3,4,5,6]
Also to use a list on a list:
array of int x: [1,2,3] +[4,5,6];
//x=[5,7,9]

This can be applied to doubles/floats.

Boolean Operators can be applied as well (<,<=, ==,!=,=>,>)
array of boolean x: [1,2,3,4,5] less than 3;
//x=[true,true,false, false,false]

And logical operators can be applied as well (!, &&, )
array of boolean x: [true,false,true] && [false,true,true]
//x = [false, false, true].

Now the fun stuff with lists begins:
The operator ".:" will append an element to the beginning of a list. The operator "`" will pop off the first element of a list. The operator ":." will append an element to the end of a list. The operator "++" will combine two lists. The operator $ returns the size of a list.
EX:
array of int x: [1,2,3,4]; int y;
y=`x;
//y=1, x=[2,3,4]
x=x :. y;
//y=1, x=[2,3,4,1]
x= 5 .: x;
//x=[5,2,3,4,1]
x= x ++ [34,4];
//x= [5,2,3,4,1,34,4]
int b= $x;
//b=7

You can also access individual elements of a list and get values from it or put values in it.
It also allows list operations like in python.
array of int x: [1,2,3,4,5]
array of int y: x[0:2]
//y=[1,2]

There are no lists of Chars available in MoisUnn because then that would be a string. And a list of chars is just stupid in general.

Also the operator "in" can be applied to lists or strings like in python to see if something is in a list or a string.

Multiple Returns:

Normally do find the min and max of two elements you would have to do:
int max(int x, int y)
{ if (x greater than y) return x;
return y;
}

int min(int x, int y)
{ if (x less than y) return x;
return y;
}

int mi=min(5,2);
int ma=max(5,2);
//mi=2, ma=5

In MoisUnn:
int, int MM(int x , int y)
{ if (x greater than y)
return x,y;
return y,x;
}
int max, min;
max,min=MM(5,2);
//max=5,min = 2

Of course, multiple returns can make code far more powerfull and far more complex.
int ba()
int, int, fool(int x, int)
int,bool foo()
float, bool, int, int foo2(int, bool, int, int)

And then :
foo2(foo(),fool(ba(),5))

Is completely runnable.

So far that's all that has been accomplished with MoisUnn in the past few weeks. It is set to rapidly expand with it's usability and flexibility and revolutionize(hopefully) programming languages.



MoisUnn is copyrighted by Stephen Moist and Varun Unnikrishnan.

Thursday, April 23, 2009

DON'T DO THIS

SERIOUSLY DONT.

When you write unit tests don't ever use loops to check things.  EVER.
As an example:

for (int i=0; i is less than 512; i++)
{
ASSERT(something);
}

Why?  Because when one of the asserts fail, then what happens is that you get the line number of the assert failing.  Which is in the example above, 3.  Which is completely useless.  It won't tell you on which iteration it failed.  And if you are using an ASSERT_FAIL, then it is even more useless.   This is horrible.  This should never be used unless your unit tests test the ability of a generator to test whether or not it can consistently generate good values.  See the example of how to do this that isn't retarded.
A better version to do is:
int numberofFailures=0;

for (int i=0; i is less than 512; i++)
{
if( the same logic of the assert)
else:
numberofFailures++;
}
AssertEquals(numberofFailures, 512);

Another thing:
Don't have output that you have to check manually.  This really is bad.  And I don't mean printing out some number and then checking by hand if that number is the right output.  What I mean is printing out :
-----------------------------------
Test 21: Passed: Good values of tacos.
-----------------------------------
***************************
Test 22: Failed: Too much tacos.
***************************

This is not helpful since you are not using asserts which can then print standardly out to a file which then can be easily parsed and integrated in a report for all the unit tests ran. 

I am not against printing things out, but USE ASSERTS not prints and if's instead.

Also:
If you use a counter to keep track of the current test case being ran, this is stupid.  Use fixed numbers.  It makes things very hard to figure out which test is being ran when everything looks the same!

Thursday, April 9, 2009

Making my Own Unit Test Suite

Yea I'm going to do that.

I hope to do something more flexible than Python's unit testing framework where if something fails it stops everything.  I won't be using asserts to do this because I don't wanting it to stop stuff, I want it to continue on!  It will will probably be an object.  I hope for it to somehow be compatible with the google app engine and also independent of it.  So I hope to let the user specify if they want it to be part of the google app or just write the output directly to the terminal.

Yea, it's gonna have to be an object for that to work.  So far I've come up with the methods that you can use:

Unit.assertTrue(boolean value)
Unit.assertFalse(boolean)
Unit.assertTrueFAIL(boolean)
Unit.assertFalseFAIL(boolean)
Unit.assertEqual(thing 1, thing 2)
Unit.assertNotEqual(thing 1, thing 2)
Unit.assertEqualFAIL(thing 1, thing2)
Unit.assertNotEqualFAIL(thing 1, thing 2)

The functions with "FAIL" in them will instead of using a nice if statement they will use an assert, so if the assert fails, it will stop everything. This allows things to where the code after it is absolutely DEPENDENT on the code above working correctly.  This is great for when if something should stop at that point could perhaps, say, delete your whole database or enter a profoundly awesome loop that will not end.

If I have enough time, I will add to it:
Unit.assertTrueGIVE(boolean) 
where the GIVE will return the value of what happened.  So if you make a function call in it, it will return that function call's return value.
So it will be possible to do:
x=Unit.assertEqualGIVE(5,65) and will set x = to 5.

So theoretically, there will be no statements other than unit test calls in the unit test file.  Nifty eh?

Any comments or feedback would be nice.

Wednesday, April 1, 2009

Selenium Part 2

So hopefully by now you have gotten adjusted to Selenium or completely abandoned it.  A quick note on how Selenium works.  It works by looking for a field and when it finds that field, it will insert text into it or selected it.  So if you name your phone number field in TA "phone" and then change it, Selenium won't find it.  But if you move it around on the page, or change the validators and code that gets run from it, Selenium will run it fine.  So keep that in mind if you start changing the names of fields.

So open up the IDE.  Load in a test and then click the tab called "Source" on the window bar (or where ever) under "Options" go to "Format" and then "Python".  It will take your nice GUI test and convert it all to python code.  More specifically, a unit test built around the Selenium framework.  And the best part is that it is easily runnable, you just copy and paste it into a new file.py and then run it from python.  You can easily link many together.   So if you have multiple tests, just make a "UIUnitTest.py" file, copy all of one into it and then just grab the "def test_new(self):   " part and paste it in.   Python will run it all as one big unit test automatically.  Isn't it wonderfull!

However......   For this to run, you must install the Selenium RC package (it is on the same download page).   And you must use Unix, Linux or the terminal in OS X.   So download it,  unzip it and shove it into a directory.  The next part you need to visit here  on how to set environment variables and point Selenium to the right spot.   So go into the folder selenium-remote-control-1.0-beta-2/ and then into selenium-server-1.0-beta-2   .   Now run the jar there by java -jar selenium-server.jar  .   This must be running for you to remote execute things.  Make a new terminal and put your UIUnitTest.py file under the one python branch in the selenium-remote-control-1.0-beta-2 folder and then run it.   It will automatically launch firefox (remember to have X windows on...) and then run it.  And please make sure that it runs correctly before doing this!

Now the great part about running it in the RC version is that you can inject Python code into the unit test file.  So if you need to create tables for a database, you can easily do that.  Run some script?  Go ahead!  What ever Python can do, you can put it in and then automate it.

So if you think Selenium will help you in whatever, use it.  If not, don't.   Oh and remember, the documentation for Selenium is horrible.  So if you have a question, ask here I may be able to help.

Tuesday, March 31, 2009

Selenium (not the Element)

Today's topic is selenium.   Selenium is this pretty nifty tool that helps for GUI "unit testing".  What it does is records all of your actions and then will play it back for you.  It's perfect when you make changes to the UI under the hood and want to make sure stuff works right.  So basically, it is a unit test of your UI.

I've already confirmed that it does work with the group projects (at least with my group's project).  So you can totally use it to help automate filling in forms over and over by a simple click of the mouse.

Selenium is basically another class to use in python.  (It also runs with Java, PHP, Perl, Ruby, JavaScript and many more natively).  So you can just make a new instance of a window and tell it to start clicking on things and filling in forms.  

But there is the best way, go get the Selenium IDE from seleniumhq.org/download.  The IDE is  firefox plugin.  Go ahead and install it.  Then go under tools and select it.  There will be a path name on the front, paste the google app engine link into it.   Click the red button off to the right and start filling in forms and navigating through pages and clicking on stuff.  When you are done, hit that red button again and then hit the play button.   It will start to play back exactly (or nearly exactly, Selenium is sometimes wonky when recording things but you can easily insert some commands to fix it) what you did.  Play with it for a while and see what happens.  You might like it or you might hate it.  Either way, I don't really care.

Any way there is a convert script to python tab menu thing and it will do that and generate a python script where you can add system calls and other functions you write (such as creating a table) and then run it as the Selenium script starts running.  Next time, I will go more in depth about this to give you time to play with Selenium because the next part is a pain to get to work and requires you to know how to do Selenium well.

Tuesday, March 24, 2009

Better version of what I've said.

Since we're working in teams now with many people.  It is a good idea to start using branches.  The reason behind this is if you check out the trunk, some one else does as well, and then your 2 other team members and you all start commiting changes.  Horrible horrible collisions will occur.  So if someone modifies something and then commits it and you are using an older version and make your changes to something else, everything goes to hell and it becomes a nightmare.  With branches, you will always get a good working copy of the code.  And once you are finally done, then your changes can be merged with the trunk so the trunk stays at a constant working condition with no horrifying problems.  Trust me, this is much better than it sounds, it creates less headaches and easier to manage.  It is also a good way to fix bugs without messing everyone else up.  So here's the method to use:

Branch the trunk to start your work
Remember, this is not actually copying all the files in the repository, its mostly a database change, very little space consumed. This operation should be considered consuming almost no disk space, and you should feel free to make branches anytime. The alternative would be messed up merges, miscellaneously copied files and lost SVN commits which is unacceptable.
# svn copy -m "[Issue number] Branching to develop a fix for Issue number." http:/google/trunk http://google/branches/Issue number

Checkout your new branch
# svn co http://google/branches/Issue Number

Fix your bug
# cd Issue Number/
# svn status
# vi ..
# make
# cd source/
# svn status -q

Commit your changes to your branch
# svn commit -m "[Issue Number] Committing changes for review to my branch"
Adds/remove files and junk.
Transmitting file data ...........


Review
Damnit man, someone should check your code by easily checking out your branch.

Merging your branch back to the trunk
Change into your branch directory
# cd Issue Number/

Switch your branch to point to the trunk
# svn switch http://google/trunk
The only thing here should ONLY ONLY ONLY BE IS FILES BEING UPDATED. NOT ADDED.
Updated to revision 29242.

Find the r number from when the branch was created
# svn log --stop-on-copy http://google/branches/Issue Number
------------------------------------------------------------------------
r29130 | not this crap but bellow.

[TL-1788] Committing changes for review to my branch
------------------------------------------------------------------------
r29129 | stuff here.

[Issue Number] Branching to develop a fix for Issue number
------------------------------------------------------------------------

Find the r number of the trunk
# svn info
Path: .
URL: http://google/trunk
Repository Root: http://google/storage
Repository UUID: 0e262ef1-e203-0410-bf88-cba8cc7d4a2f
Revision: 29242
Node Kind: directory
Schedule: normal


Merge the branch to the trunk
# svn merge -r29129:29242 http://google/branches/Issue Number

Look at your changes, now merged into the trunk
# svn status -q
# cd source

Commit those changes, if no conflicts, to the trunk
# svn commit -m "[Issue Number] Checking in fix for blah... to trunk"
...
Transmitting file data ...........
Committed revision 28953.



Remove your old branch
# svn delete -m "[Issue Number] Removing development branch" http://google/branches/Issue Number


Thursday, March 5, 2009

Something about SVN, Jira and Trac

So at work we use all of that.

We use Jira to create bugs that should be fixed, Svn to get all the code and roll it all together and Trac to see who did what and messed everything up and view all previous versions.

Typically some one finds a bug or thinks of a good idea to add.  They will go into Jira and create a new issue with a great description of what happens that will get assigned to someone to fix it.  Jira will create a new page for this issue and give it a bug number.  The bug number [TL-XXXX] where X's are a number is then used to create a branch from the trunk where all work to implement this change will take place.  In Jira you can make comments on what was changed and specifically why.

Trac merges all of this together in a great way.  When ever you commit changes to a branch and give it a message, that message will show up on the bug page in "SVN commits" to let everyone know what you did and list all modified/added/deleted files.  Jira does this automatically. 

When you are ready for it to be integrated into the trunk on the bug page you have to change its status to "Fixed" and wait for some one to verify it to be correct.  Then you can commit this branch to the trunk and fix any conflicts.  And then you can change its status to "Integrated" and the bug is then taken off of the list of work in progess list.  Then delete your branch and Jira will track that message you give it.

Trac keeps track of all the changes and you can run diffs on multiple versions and see any conflicts or what was changed.  You can also view the files online as well.  Trac is a pretty good GUI system.

While Subversion is nice by itself, integrating it with Trac and Jira is great.  It makes it more complete.  It is a great combination for large scale projects that makes dealing with things much easier.

No one reads this thing.

Here is some nice Subversion info.

To better explain things, let us assume Downing has given us a project to do in which it has the first 4 projects in it somehow linked together.  The next steps are rough and you should figure out the commands properly.

Suppose there is a bug with Primes.py.  The proper way to fix this issue is to create a new tag in svn.  This allows multiple branches so while you are working on the problem, another person can come in and branch off and do something like implementing a nice GUI.  To do this do:
svn copy -m "Describing what you are doing"  
Where is of the form .../svn/project/branches/this new branch.

Then check out the branch and start working on it.  You should commit to this.  If you make changes to this branch, the trunk does not change until you merge it at the end.

So make your changes and a final commit.

Do: svn --stop-on-copy "your copy" to get the revision number (preceded by r)
do svn switch
Do: svn status -q and get the revision number of the trunk.
Do a svn switch branchR:trunkR       and this will point you to the trunk.
Do a merge.
Then now commit.

Congratulations your changes are now reflected in the trunk.

Now here is something you don't want to do.
In your branch do a svn add .  Then switch and do svn add to the trunk.  When you try to commit at this stage you will get an error saying that some file X is already in the trunk.

I got this error at work and took my a while to fix.  Since you are at the trunk any svn delete command will mess things up and actually delete files.  If you mess it up you can always revert it.

Do a svn delete  
Then do a commit again.  If get the same error with a different file  go back a line.  Else go to the next line.
Copy the files that were giving you trouble on your local machine (preferably good ones that work right before you messed things up) to a spot not in a branch on your local machine.
Delete the branch from svn.  Make a new branch and checkout the newest code (your missing stuff).  
Paste in the missing files/files that were giving errors.  Do a svn add to those files.  then commit and merge it back together. (Hopefully after making sure everything works again properly)

This should get rid of that error.  If you ever get this error, you now know what to do.

Making branches makes it very easy to add features or fix "defects" with out possibly messing up the code that everyone checksout.  Think about it, do you really want to checkout code that works horribly more or is incomplete and breaks alot of things.  Or would you rather get a good working copy and modify it.

Next post: SVN, JIRA, TRAC all rolled together.

Monday, February 23, 2009

A sidestep into Meetings

I was going to continue on about unit testing but have decided to make this quick little detour about how much meetings suck.

Meetings suck.  That's pretty much the whole post. You will hate meetings with a passion.  Most of the times you get things done and effectively collaborate as a group.  The rest of the time involves people arguing over inane details that do not concern them.

The meetings I am forced to go to typically have nothing to do what I've done or what my project is doing.  They area  a waste of time.  No one pays attention, they either email at their computer or continue working on what they were doing before.  When there is collaboration it can be good but sometimes it is just people not saying anything useful.  They have to voice their opinions about things.

For example I was in a meeting from hell recently.  It was over the discussion over caching all the files I make for my tests or creating them on the fly from a  script.  My point was that I've already made the tests, I don't want to make them again.  Creating a script to create all the necessary files would be some what difficult as I must insure that it is 100% correct to make the existing tests run correctly.  I modify lots of those files in such a manner that takes far too long to do.  Creating all those files takes far too long and increases the wait time before execution of testing can begin.  The files might get messed up as they are created.
The other side claimed that pulling down large files when using "svn checkout blah de blah de blah" will take too long and it clutters up the repository.  And how are we ensuring the existing files are correct.

Well, the test group had to chime in about it wanting to know when their tests would be ready (missing the point completely) and how it will mess up their testing by creating files they would have to test.  The development team (my team) was split over the two ideas and argued with test over something that was interrupting my work.  They never reached a consensus and eventually I will have to rewrite a lot of code.

So while sharing code with the team and everyone has input is a good thing, when it comes down to issues that don't really matter everyone still has input over things that are of no concern to them.

Meetings suck but you still get paid.

Thursday, February 12, 2009

Why Unit Tests Are Awesome

Some background information about me.  I work for a IT company called Crossroads and my job is to write Unit Test in C and perl.  So I theoretically should know something about this topic.

There is a very good reason why the book stresses writing unit tests,  because they do help.  I work on a product called VTS and have to deal with poorly written code that was never intended to ever be unit tested.  The code was written 10 years ago by Electrical Engineers and System administrators who had no idea what they were doing.  Most parts of the code are nearly incomprehensible.  The way it was designed was terrible.  Now you might think that it would be a good idea to rewrite the code.  This doesn't work in the real world.  The team tries to maintain the code while implementing new features.  There isn't time to make the code better and it costs far too much money to do so.  While rewriting parts of the code will destroy functionality of it and break the product and also create new bugs.

So what I do is try to create tests that effectively cover every part of a subprogram, hitting all executable parts, all the branches, take every possible branch and try to return all possibilities.  Like most products, it has calls to outside functions and requires specific data and files.  It is not like the one call to the outside calls a little nice function  that does some small print statements or compute some primes.  No, it runs a 3000 line program, that requires other programs to run first, specific variables set correctly as a result, specific objects to be continuously built before and during execution.  And an large amount of global variables that extend through nearly 16 other programs make it not fun to test effectively.  Then it can run the utility that I'm testing after doing all of that.

This creates a problem.  I don't really care what the thing is doing outside of the utility, or waiting 15 minutes to generate usable data before I can run a test.  So it was decided to stub out or redefine any calls to the outside and falsify them and return false data.  This is the only real way for me to test anything.  Because if I don't, I'm creating functional tests.  I really only want to test the logic of the utility.

So, inside of a the Unit test file, I do a #include of the file I'm wanting to test.  Do a #define on all outside methods and main().  Now I can test.  I create false data (data that I wrote to test the utility, which can be good, bad or just wrong) and feed it through, hoping to hit all statements and hope to get a return code that is expected.  What is important to do first is to try to hit all the returns and get good data back, ensuring that it works as specified.  Then I want to destroy it.  Make it break, make it fail, make it not work.  Only until I do that I can find all of the bugs, increase preconditions and make it more stable.   

I use CUnit to drive the tests, create a suite for each method I test, a Test case for each return expected.  The do the same for trying to fail tests.   The easiest methods to test are the ones that return a boolean value.  Because of this you don't care specifically what it returns and have to match it to an expected value in the asserts.  You can just use Assert() for when it is true, and Assert_False() when it is false.  It defines what you want to return, true or false and no real thinking of what it is returning, just how to break it.

You want to obviously test the functions to ensure they work, but you also want to use Unit Testing to make it fail and identify bugs that you won't think about.  Give your ints a wide variety from the min to the max.  Make your if's fail.  Control how the program works to break it to make it more robust.  It is difficult to test all conditions, you will probably create tests that never intended the thing to run like that, create bugs that won't ever run due to weird data.  But if you are working on code that is low enough, this must be done because the programmers working on the high level stuff can easily pass in bad things continuously unknowing.

Next week: More in depth discussion of Unit Testing.

Thursday, February 5, 2009

Project 2 Primes

Todays Topic:  How to do project 2.

So the current project due in CS 373 is Primes.  It has to deal with how to compute a number from 4 prime numbers by adding them all together.  As discussed in class there are some pretty good ways to do this.  If you took CS 315 with Downing then you might have had to do this problem in java.  The only difference is that now we're not being timed, it has to be used in python and use subversion.  The best way is to start out with a list of prime numbers.

There is a few different ways to get a list of prime numbers.  You could google it  (link: http://tinyurl.com/deehyp) and copy paste that into emacs (or your choice of text editor) then set it up as an array called primes and manually insert commas and remove whitespaces and newlines (\n).  There is another way and that involves computing the primes yourself.  I chose this method since we would need all of the prime numbers slightly past 2500000 since the max number N is 10000000 and can be made up of 4 different numbers.   
Another way to get the primes is to write a loop that will take a number and try to divide it by all numbers that are smaller than it to n/2.  If it can't be divided wholey with integers then it must be prime and then add it to the list.  [Use 2 nested loops to accomplish this]   The other better/faster way is to do the Sieve of Eratosthenes.  (I actually did this in High School yay for me?).  Also wikipedia

Now that you have gotten a list of primes in python (hopefully) the easiest way to get them all out is to do this:  "print primes"   [where primes is you list of primes].  Then just copy all of that printed out stuff and make a global array and paste it in.

To compute the primes Downing suggested this idea.  If the number is even then pick two of the primes are to be even.  If it is odd then pick an odd and then an even prime.  Of course the only even prime out there is 2.

I suggest 4 nest for loops and use the idea above to set the two outer loops to start at those numbers (2 and 2 if even, 2 and 3 if odd). Then just run through the for loops grabbing prime numbers from the list of primes.  You should create a boolean flag for when you find the numbers to easily break out of the loops.  Then print them out. 

However there are exceptions to the summation of 4 primes being the desired number.  If the number is ≤ 7 then the program should print "Impossible.".  Also there might be a few numbers that are not able to compute from a list of prime numbers and should also print "Impossible.".

A few suggestions:
Get a list of all the primes up to 10000000.  It really can't hurt.
Make a big list of unit tests and use high numbers.
Find your list of primes and then submit to subversion.
Ask questions if you need help.

Next week's topic: Unit testing and why it's not annoying.

This is a test do not fear it

Welcome to another Blog for CS 373.   Today's post will be about stuff.  Because stuff is good.  Except when it is free, then it is awesome.






Test Unsuccessful.
ABORT Y/N ?