Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Tots
Sep 3, 2007

:frogout:

Look Around You posted:

Well, why not pull the method out of the switch statement so that you're only using it at one point? Also, if you print a generic error on 99 and return it, when will your program halt? Is there another specific code to terminate?

Was going to put the switch in a while statement and end at -1, as it is in my original program.

If I only use it once, wouldn't I then have to put all the output associated with each case, as well as the incrementer that will keep track of how many time they are used, inside this new method?

Adbot
ADBOT LOVES YOU

Look Around You
Jan 19, 2009

Tots posted:

Was going to put the switch in a while statement and end at -1, as it is in my original program.

If I only use it once, wouldn't I then have to put all the output associated with each case, as well as the incrementer that will keep track of how many time they are used, inside this new method?

Oh, it looks like the cases are significantly different. One way to break it apart (and probably the best way for larger applications) would be to take each case and turn it into it's own function. That way you can just do case 1: calcManagerSalary(); break; case 2: calcBlahWages(); break; and move the actual logic for calculating the wages into their own functions. This has the side effect of being a lot easier to debug too. But yes, you would have to figure out a place to store the incrementers and increment it when you calculate that specific type of wage.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





Plorkyeran posted:

I've actually seen co-op hirability used as an argument for teaching Scheme in the intro classes - the logic being that they'd had 100% placement for a few years, so the school should be focusing on getting the students good jobs rather than any job at all, and companies that like to see Scheme on a resume are probably better places to work.

At my school the beginning programming class was DrScheme. I think it was more to weed out than anything else really.

Tots
Sep 3, 2007

:frogout:

Look Around You posted:

Oh, it looks like the cases are significantly different. One way to break it apart (and probably the best way for larger applications) would be to take each case and turn it into it's own function. That way you can just do case 1: calcManagerSalary(); break; case 2: calcBlahWages(); break; and move the actual logic for calculating the wages into their own functions. This has the side effect of being a lot easier to debug too. But yes, you would have to figure out a place to store the incrementers and increment it when you calculate that specific type of wage.

I am really tired right now, but I can't make sense of how this would work unless a method could return a string

E: Okay, yah I need to go to bed. They wouldn't need to return anything.

Good night.

Look Around You
Jan 19, 2009

Tots posted:

I am really tired right now, but I can't make sense of how this would work unless a method could return a string

E: Okay, yah I need to go to bed. They wouldn't need to return anything.

Good night.

I know you went to bed and figured it out (you're right, they don't need to return anything), methods can in fact return String objects... in fact, they can basically return any type you want.

For example:
code:
public class Thing {
  private String name;
  
  // makes a new Thing
  // with this objects name
  // and the other Thing's name together
  public Thing concatNames(Thing other) {
    Thing ret = new Thing();
    ret.name = this.name + other.name;
    return ret;
  }

  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

// Example usage
// Class BigBear does thangs with Things
public class BigBear {
  public static void main(String[] args) {
    Thing thing1 = new Thing();
    thing1.setName("Big");
    System.out.println(thing1.getName()); // prints "Big"
    
    Thing thing2 = new Thing();
    thing2.setName("Bear");
    System.out.println(thing2.getName()); // prints "Bear"

    
    Thing thing3 = thing1.concatNames(thing2);
    System.out.println(thing3.getName()); // prints "BigBear"
  }
}
edit: fixed typo in the last println; shoudl have been thing3.getName not thing1.getName

Look Around You fucked around with this message at 07:45 on Feb 22, 2012

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Internet Janitor posted:

pokeyman: I was mainly reacting to the assertion that Java syntax is onerously arcane and confusing. What would you consider a good language for beginning programmers?

I have no idea. Scheme seems like a decent fit, but I get the impression that it needs to be very well taught or you'll lose your students in the weeds. I'm surprised I've never heard of an intro programming course doing stuff in the browser, maybe using something like Processing. It (anything in the browser) is shareable, it's the best REPL you can get, it can do graphics without dickery, and it should score high marks in co-op interviews. Or try Ruby, which you can sometimes make it read like English so the syntax isn't so bad, using something like Hackety Hack or Shoes. The first language I ever started learning was PHP, because I wanted to "make the <form> work", and despite the well-deserved scorn it gets you can do a lot with it and it's everywhere.

I guess my answer is: if I was teaching a programming class in two weeks, I'd base it entirely on Processing.js. If I was teaching it tomorrow, we'd follow Learn Python the Hard Way and I'd be the question answerer guy.

oRenj9
Aug 3, 2004

Who loves oRenj soda?!?
College Slice

Tots posted:

If I wanted to abstract the input and error handling, would this be the right track?

Others have given you great advice about your idea. But, I wanted to single this statement out and commend you for saying it. This tells me that you are developing a true understanding of how to use software as a tool to solve problems.

You started out with the same giant mess of code that everyone creates when they first start learning to program. This is to be expected though; because you're learning, you are focusing on solving a dozen or so problems in relative independence of each other, then grouping them together to form a solution to a larger problem. The important thing is that you evaluated your solution, noticed emerging patterns and refactored your code around those patterns to make it more simple and robust.

I'd venture to say that, out of your class of 20 or so people, you're one of maybe four people to both notice those patterns and try to generalize your solutions around them. So, good job. You still have a lot to learn, but if you continue to put this kind of effort into your education, then you will certainly succeed.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
At the risk of becoming unpopular, if I was teaching 6-12 year olds programming, I'd start with Flash (AS1/AS2, not AS3), just because there's a little bit of fluff before you get to start building something fun to play around with. It's an animation tool and it's universally hated, but it gives you good primitives and it's very easy to get something graphical up and running without effort, and then make it interactive.

For those unaware of how Flash works, you have a timeline of frames, since it started as an animation tool. The playhead advances a customizable frames per second, and you can start/stop the playhead and jump to any frame number in the scene. If the playhead is moving, it will loop back to the start of the scene when advancing past the end of a scene. You can also put actions on a frame, to be executed when the playhead reaches that frame. The script context is global, so variables defined in one frame are global across all frames.

With this you can already start to build interesting systems:

If you want something to happen every second, you build a timeline that's FPS frames long, and put the action on the start of the timeline or the end of the timeline depending on when you want the action to happen.

By using a variable, you can make it loop a specified number of times. Frame 1 has the init: count = 5;, and Frame FPS+1 has the loop: count --; if (count > 0) gotoAndPlay(2); else stop();.

This started out in the Flash development community at first, until everyone settled on what I call the "3-frame game loop" pattern. Frame 1 is an init, Frame 2 is the Game Logic, and Frame 3 is gotoAndPlay(2);, which keeps Frame 2 executing every frame. Of course, this is lost on everybody now that we have AS3, but since it's so simple and easy to build interesting patterns.

Once you get to a high enough level, you can also look at it as a very simplified machine: the playhead is the instruction pointer, frame numbers are the code addresses, and gotoAndPlay a jump instruction. With those basic primitives, we built do...while and while loops without even thinking of it.

And if I was teaching the same set of students over time, I'd guide them into figuring out these concepts, and I'd let them now I'd tricked them into inventing these sorts of loops, and show them at a low level that, yes, loops are just basic patterns for jumps that so common that we have special cases for them in most programming languages. Language evolution is a neat thing.

Nippashish
Nov 2, 2005

Let me see you dance!

Suspicious Dish posted:

At the risk of becoming unpopular, if I was teaching 6-12 year olds programming, I'd start with Flash (AS1/AS2, not AS3), just because there's a little bit of fluff before you get to start building something fun to play around with. It's an animation tool and it's universally hated, but it gives you good primitives and it's very easy to get something graphical up and running without effort, and then make it interactive.

I taught myself to code in middle school using Flash (AS1 because that's all there was then) and I can confirm that it's actually pretty awesome for exactly this reason.

Sub Par
Jul 18, 2001


Dinosaur Gum
This is probably more of a math question, but I feel like this is the best place to ask it. I'm looking to determine whether a given customer is a "seasonal" one, i.e. they tend to only make transactions during a certain time of year. I don't (initially) care what time of year it is, I more want to just have some kind of metric for example a number between 0 and 1 where 0 represents customers where all transactions are in the same month and 1 is customers with a more evenly-spread transaction history or something.

The problem I'm having is coming up with a way to structure the data so that month 1 (Jan) and month 12 (Dec) are treated as "next" to each other. I don't care that a person who transacted in January 2011 and again in December 2011 had 10 months without a transaction in there, I care that the months were proximate to each other in a seasonal sense.

I'm really not sure what to even google for here, any thoughts or help would be appreciated. Thanks.

baquerd
Jul 2, 2007

by FactsAreUseless

Sub Par posted:

This is probably more of a math question, but I feel like this is the best place to ask it. I'm looking to determine whether a given customer is a "seasonal" one, i.e. they tend to only make transactions during a certain time of year. I don't (initially) care what time of year it is, I more want to just have some kind of metric for example a number between 0 and 1 where 0 represents customers where all transactions are in the same month and 1 is customers with a more evenly-spread transaction history or something.

The problem I'm having is coming up with a way to structure the data so that month 1 (Jan) and month 12 (Dec) are treated as "next" to each other. I don't care that a person who transacted in January 2011 and again in December 2011 had 10 months without a transaction in there, I care that the months were proximate to each other in a seasonal sense.

This isn't a trivial problem. You could have all sorts of distributions of purchases that would skew simplistic attempts to calculate this metric. Suppose you have a customer that purchases only in June (a birthday perhaps) and December (holidays). Should they be seasonal or not?

One simplistic approach would be to bucket sort the months into seasonal purchases and then calculate the maximum difference between seasons. The higher the difference, the more seasonal they are.

If you already have a method of determining the seasonality of a customer and your only problem is how to wrap the months, post some code.

code:
//bucket sorting
if (month > 11 || month < 3) {
   customer.addSeasonalPurchase(Season.Winter);
} else if (month > 8) {
   customer.addSeasonalPurchase(Season.Fall);
} else if (month > 5) {
   customer.addSeasonalPurchase(Season.Summer);
} else {
   customer.addSeasonalPurchase(Season.Spring);
}

Sub Par
Jul 18, 2001


Dinosaur Gum
I don't have any code just yet, and maybe seasonal was the wrong word to use because I don't want to hard code months into seasons and then determine if their transactions all fall within those seasons. I am looking to be able to say "this person makes all their transactions in the same month" which is easy but then contrast that with "this other customer transacts in different months but they tend to be closely clumped i.e. mostly in June/July or Dec/Jan/Feb" and then "this customer seems to transact randomly or across many different months i.e. Jan/Mar/Aug/Nov".

This would be irrespective of any traditional definition of what constitutes a "season" - I want to see if certain customers cluster their transactions thus forming their own "season".

modig
Aug 20, 2002
code:
purchases # an array from 0-11 with purchase totals from each month

one_month_seasonalness = max(purchases)/sum(purchases)

# 2 month seasonalness
n=2
for start_month = 0:11
    end_month = start_month+n
    if end_month<11:
        seasonalness(start_month) = sum(purchases(start_month:end_month))/sum(purchases)
    else:
        seasonalness(start_month) = (sum(purchases(start_month:11))+(purchases(0:end_month-11)))/sum(purchases)
2monthseasonalness = max(seasonalness)

Sub Par
Jul 18, 2001


Dinosaur Gum
That's a very good idea, like a rolling X month window. Thanks a bunch, I can go from here with that.

ToxicFrog
Apr 26, 2008


Suspicious Dish posted:

At the risk of becoming unpopular, if I was teaching 6-12 year olds programming, I'd start with Flash (AS1/AS2, not AS3), just because there's a little bit of fluff before you get to start building something fun to play around with. It's an animation tool and it's universally hated, but it gives you good primitives and it's very easy to get something graphical up and running without effort, and then make it interactive.

There's no shortage of other, better languages that let you quickly get something shiny and fun to play with going, though. When I was 6 I was using LOGO, whose entire reason for existence is basically this (and it turns out it's a Lisp dialect). My high school used Turing, which is good for this (as long as you avoid the networking library). Lua and Python aren't designed around this capability but have libraries that add it.

Notably, none of these languages will send your students spiraling into the depths of madness when they write a += 1 by evaluating a twice.

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


There's a thread over here about how to teach intro programming classes that might be worth reading for those of you who are interested in the topic.

Sub Par posted:

I don't have any code just yet, and maybe seasonal was the wrong word to use because I don't want to hard code months into seasons and then determine if their transactions all fall within those seasons. I am looking to be able to say "this person makes all their transactions in the same month" which is easy but then contrast that with "this other customer transacts in different months but they tend to be closely clumped i.e. mostly in June/July or Dec/Jan/Feb" and then "this customer seems to transact randomly or across many different months i.e. Jan/Mar/Aug/Nov".

This would be irrespective of any traditional definition of what constitutes a "season" - I want to see if certain customers cluster their transactions thus forming their own "season".

For each customer, compute the proportion of their purchases that fall in each month, and compute the KL divergence between that and a uniform distribution. The lower the result, the less "seasonal" they are.

ultrafilter fucked around with this message at 17:41 on Feb 22, 2012

Computer viking
May 30, 2011
Now with less breakage.

I just found something neat and relevant here (pdf : "The use of a Kolmogorov-Smirnov type statistic in testing hypotheses about seasonal variation", L.S. Freedman 1979, Journal of Epidemiology and Community Health). I'll try to summarize it, but beware that I'm very definitely not a statistician.

First, calculate what fraction of sales for a customer happened each month, then, calculate the cumulative sums for that list (That is, make a new list where the value for a month is the sum of that month plus all earlier months). December ought to get 1.

Now, make another list of how large a fraction of sales you'd expect to have happened if sales were perfectly even (and for the sake of simplicity, the months equally long) : 1/12 at the end of jan, 2/12 at the end of feb, up to 12/12 at the end of dec. Subtract one list from the other, so difference = actual-expected.

If the data had not been seasonal, you could then find the largest absolute value in that list of differences, and use that as a score: Larger means more different. However, since these are months and wrap around, a small bit of compensation is needed.

Find the largest number in the list of differences, and call it Dmax. Find the smallest (quite possibly negative) number, take the absolute of it, and call it Dmin. The interesting score is Dmin+Dmax - which stays constant if you rotate the months around.


To illustrate, consider these distributions:
code:
Raw numbers:
random:    26  6  6 17 12 24 28 19 25 13 29 25
christmas:  1  1  1  1  1  1  1  1  1  1 10 20
sales:     20  1  1  1  1  1  1  1  1  1  1 10

Fractions:
random    : 0.11 0.03 0.03 0.07 0.05 0.10 0.12 0.08 0.11 0.06 0.13 0.11
christmas : 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.25 0.50
sales     : 0.50 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.25

Cumulative:
random    : 0.11 0.14 0.17 0.24 0.29 0.40 0.52 0.60 0.71 0.77 0.89 1.00
christmas : 0.03 0.05 0.08 0.10 0.12 0.15 0.18 0.20 0.23 0.25 0.50 1.00
sales     : 0.50 0.53 0.55 0.57 0.60 0.62 0.65 0.68 0.70 0.72 0.75 1.00
If I plot them, they look like this:




The blue line is the cumulative sales fraction for the theoretical "every month is identical"-case, the red line is the actual cumulative sales, and the green dots the difference each month. The score in the simple non-seasonal case is the maximum of the green dots. Dmin is the green value where the red is the furthest below (or least above) the blue, and Dmax is the green value where the red is the furthest above the blue.

As for the scores:
code:
random:    0.1550725
christmas: 0.5833333
sales:     0.5833333
As for how to interpret those numbers, uuuhm. Let me read a bit further.

edit: Aha, there's a simple enough lookup table (calculated from 10000 random tests, which I guess was a bit of work in 1979). Take the score, multiply it with sqrt(12), and look up here:
code:
10%  :  0.58
20%  :  0.67
30%  :  0.75
40%  :  0.82
50%  :  0.89
60%  :  0.96
70%  :  1.03
80%  :  1.14
90%  :  1.21
95%  :  1.41
99%  :  1.66
In my test numbers, that means:
code:
christmas : 0.5833333 * sqrt(12) = 2.021 : >99%
random    : 0.1550725 * sqrt(12) = 0.537 : <10%
The percentages are something like "how often will a result like this not be because of random chance".

Computer viking fucked around with this message at 20:45 on Feb 22, 2012

etcetera08
Sep 11, 2008

Otto Skorzeny posted:

I don't think anything is, although there are varying degrees of unreadability and bewilderment. I think that python would make a reasonably good first programming language for non-CS majors, and a poor one for CS and related majors.

This is the exact position my school's CS program takes. They teach Python for the non-CS major intro classes (math majors (and maybe some other majors too?) have to take an intro CS class and they can take the non-major intro) and Ada for the CS majors' intro. The professors I've talked to give a few reasons for this, but the biggest one is that Python hides a lot of concepts that are relatively important to CS majors but are pretty unimportant for people just dabbling (for example, the concept of an independent compiler can be completely lost if you only use Python).

Of course, their decision sort of leads into the question of "why Ada for CS majors" but I think that can and should be a different topic altogether. In short, you should pick a first language to teach based on the end goal, just like one often chooses a language to use for a project based on the end goal.

Computer viking
May 30, 2011
Now with less breakage.

I'm not entirely sure if I agree with that line of thought. If we make the (flawed, but I suspect less so each year) assumption that CS students and non-CS students start off with the same understanding (or lack of such), why should their introductions be different? If we also assume (I know...) that the introduction a non-CS student gets is a subset of what a CS student is supposed to learn the first year ... wouldn't the best language for that subset be the same for the two?

In other words. Teach the basic concepts (splitting problems into implementable chunks, statements/functions/variables/flow, debugging, maybe a small bit of OO) in whatever language makes that the simplest, then move the CS students over to another language in their next, more advanced, course. Besides, the training in jumping between languages is useful in itself. :D

Computer viking fucked around with this message at 21:01 on Feb 22, 2012

etcetera08
Sep 11, 2008

Computer viking posted:

I'm not entirely sure if I agree with that line of thought. If we make the (flawed, but I suspect less so each year) assumption that CS students and non-CS students start off with the same understanding (or lack of such), why should their introductions be different? If we also assume (I know...) that the introduction a non-CS student gets is a subset of what a CS student is supposed to learn the first year ... wouldn't the best language for that subset be the same for the two?

In other words. Teach the basic concepts (splitting problems into implementable chunks, statements/functions/variables/flow, debugging, maybe a small bit of OO) in whatever language makes that the simplest, then move the CS students over to another language in their next, more advanced, course. Besides, the training in jumping between languages is useful in itself. :D

I really do think that's a pretty valid way to think about it too. The point at which I differ, however, is that there are some things that are necessary to spend time talking about when you teach, for example, Ada as a first language as opposed to Python (to use the example of my program). Those things, while almost always very important if you are going to be spending 3+ years studying CS, probably don't matter to people that are going to be spending the rest of their lives studying other things or working in unrelated fields. Teaching Python allows these latter people to be exposed to the very basics of CS and gives them an idea of what kinds of concepts are important to the field without forcing them to get too specific. CS majors, on the other hand, get exposed to these same things but also get a head start into the specifics and more advanced topics.

Also, this discussion began in regards to Java's relatively more difficult syntax being a barrier of entry. I do think that also can come into play in this discussion. I don't think many (any) people would argue that Python's syntax is more difficult than Java or Ada. You can make things happen with a Python program (or even with the REPL) with much less of a time investment. The problem is that the simpler syntax generally means you're being sheltered from some concepts that may or may not be incredibly important.

Computer viking
May 30, 2011
Now with less breakage.

etcetera08 posted:

I really do think that's a pretty valid way to think about it too. The point at which I differ, however, is that there are some things that are necessary to spend time talking about when you teach, for example, Ada as a first language as opposed to Python (to use the example of my program). Those things, while almost always very important if you are going to be spending 3+ years studying CS, probably don't matter to people that are going to be spending the rest of their lives studying other things or working in unrelated fields. Teaching Python allows these latter people to be exposed to the very basics of CS and gives them an idea of what kinds of concepts are important to the field without forcing them to get too specific. CS majors, on the other hand, get exposed to these same things but also get a head start into the specifics and more advanced topics.

Also, this discussion began in regards to Java's relatively more difficult syntax being a barrier of entry. I do think that also can come into play in this discussion. I don't think many (any) people would argue that Python's syntax is more difficult than Java or Ada. You can make things happen with a Python program (or even with the REPL) with much less of a time investment. The problem is that the simpler syntax generally means you're being sheltered from some concepts that may or may not be incredibly important.

The question is then if it's harmful or time-wasting in the long term to start out with a language where you can ignore those things (only to bring them up later), compared to plowing straight into them from the beginning. Personally, I don't think it's a bad idea to start out by easing them into programming as an activity first, and moving into the complications and underpinnings later. It's easier to add more details later than to absorb everything at once, in my experience - even if the "details" are large and fundamental.

I don't teach programming or CS, though; maybe it would lead to annoying habits and weird misunderstandings that had to be polished out later.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Look Around You posted:

code:
x = int(raw_input())
while x != -1:
    print(x)
    x = int(raw_input())
print("done!")

I'm just going to comment on this, because this is bad practice in the Python community. One of my biggest dislikes of Python is that yes, you can do something like this, but it's a terrible idea. This is what it should be:

code:
if __name__ == "__main__":
     x = int(raw_input())
     ...
And most tutorials start with "Just ignore that, it's to check that you actually ran the file a script", or maybe they'll give a "we'll get to that later when we introduce imports and moudules". This __name__ == "__main__" thing is ingrained in every Python programmer that I've met people using Python for 5-6 years that know what's actually happening, and the twisted perversion that you can actually run the file twice - once as an import (when __name__ is the name of the module in sys.modules), and once as a script (when __name__ is "__main__").

(Rant: this is, of course, a terrible design decision that just screwed me over the other day in a large system - I put a main block in one of my modules so I could easily test it by running it, and I was wondering my system was "desynced", so to speak)

Computer viking
May 30, 2011
Now with less breakage.

It's only a terrible idea if there's a remote chance that you'll use the file as a module, though. (In other words, skipping it is fine if you know that you are doing it, and why).

Admittedly, my day-to-day python tends to be ugly little once-off scripts.

Look Around You
Jan 19, 2009

Suspicious Dish posted:

I'm just going to comment on this, because this is bad practice in the Python community. One of my biggest dislikes of Python is that yes, you can do something like this, but it's a terrible idea. This is what it should be:

code:
if __name__ == "__main__":
     x = int(raw_input())
     ...
And most tutorials start with "Just ignore that, it's to check that you actually ran the file a script", or maybe they'll give a "we'll get to that later when we introduce imports and moudules". This __name__ == "__main__" thing is ingrained in every Python programmer that I've met people using Python for 5-6 years that know what's actually happening, and the twisted perversion that you can actually run the file twice - once as an import (when __name__ is the name of the module in sys.modules), and once as a script (when __name__ is "__main__").

(Rant: this is, of course, a terrible design decision that just screwed me over the other day in a large system - I put a main block in one of my modules so I could easily test it by running it, and I was wondering my system was "desynced", so to speak)

Yeah, I knew there was something like that in Python... I haven't really used python all that much but I figured there was something like that in it at least.

The thing I'm saying though is that in (the first part of) an intro course you probably should be focusing more on things like loops, functions, stuff like that. For that stuff, single file scripts are probably the right way to go, and so you don't need to teach them that. I'd introduce the if __name__ == __main__: stuff when you introduce modules, because it's not necessary to know when you're literally just writing single file scripts.

e: what I'm saying is basically don't include more "magic words" than you need to for introducing basic concepts. If you can write a single file script without that (which afaik you can), then you don't need to tell them to use it until you get to the point where you are actually going to be using multiple files/modules.

Look Around You fucked around with this message at 23:48 on Feb 22, 2012

Tots
Sep 3, 2007

:frogout:
Since my questions sparked the intro debate I should mention that I am in IST which is slightly different than CS. The introduction course for CS uses C++ as does the introduction course for students that aren't going into technology related major. Before taking this course which uses Java I had to take the generic intro which uses C++. That course just taught concepts like using variables and basic loops.

Vanadium
Jan 8, 2005

pokeyman posted:

I'm surprised I've never heard of an intro programming course doing stuff in the browser, maybe using something like Processing. It (anything in the browser) is shareable, it's the best REPL you can get, it can do graphics without dickery, and it should score high marks in co-op interviews.

It's not a real programming course but there was this:
http://cdsmith.wordpress.com/2011/08/16/haskell-for-kids-week-1/

Gravy Jones
Sep 13, 2003

I am not on your side
A dumb regular expression question because I'm slow and have never really looked at these things before. It's probably staring me in the face but my investigations were dead ends. Possibly a lack of understanding of the terminology.

I have

S[0-9]{4,5}

Which I think says "S" followed by four or five numeric digits. If I want to match a string that contains that and only that I do this:

^S[0-9]{4,5}$

What I can't figure out is how I allow for various iterations of that within the expression I'm matching. I know I can repeat the whole thing inside the ^$ for a specific number. But what about if it needs to be one or more... or less than 5 or something like that?

VVV perfect. Thanks.

Gravy Jones fucked around with this message at 00:12 on Feb 24, 2012

baquerd
Jul 2, 2007

by FactsAreUseless

Gravy Jones posted:

What I can't figure out is how I allow for various iterations of that within the expression I'm matching. I know I can repeat the whole thing inside the ^$ for a specific number. But what about if it needs to be one or more... or less than 5 or something like that?

Use parens to group.

One or more:
^(S[0-9]{4,5})+$

Less then five:
^(S[0-9]{4,5}){0,4}$

Look Around You
Jan 19, 2009

Gravy Jones posted:

A dumb regular expression question because I'm slow and have never really looked at these things before. It's probably staring me in the face but my investigations were dead ends. Possibly a lack of understanding of the terminology.

I have

S[0-9]{4,5}

Which I think says "S" followed by four or five numeric digits. If I want to match a string that contains that and only that I do this:

^S[0-9]{4,5}$

What I can't figure out is how I allow for various iterations of that within the expression I'm matching. I know I can repeat the whole thing inside the ^$ for a specific number. But what about if it needs to be one or more... or less than 5 or something like that?

one or more: ^S\d+$
less than 5: ^S\d{0,4}$ (or ^S\d{1,4}$ if it needs one or more)

\d is a shortcut for [0-9].

e: I'm dumb, yeah put it in parens for grouping.

^(S\d{4,5})+$
^(S\d{4,5}){0,5}$

e2 I was paren happy, too many close parens.

Look Around You fucked around with this message at 00:14 on Feb 24, 2012

Safe and Secure!
Jun 14, 2008

OFFICIAL SA THREAD RUINER
SPRING 2013
E: Never mind.

Safe and Secure! fucked around with this message at 05:00 on Feb 24, 2012

oRenj9
Aug 3, 2004

Who loves oRenj soda?!?
College Slice
Can anybody help me with this sed command, I'm trying to remove carriage returns from some files. The command worked for most of hte files, but this one is being a bitch for some reason.

code:
 redacted $ sed -e 's/\\r//g' includes/lib/script.inc | od -c
[snip]
0005520                                    p   r   i   n   t       "   \
0005540    n   "   ;  \r  \n  \r  \n                                   /
0005560    /       C   l   o   s   e       s   t   r   e   a   m  \r  \n
0005600                                    f   c   l   o   s   e   (   $
0005620    _   s   t   d   i   n   )   ;  \r  \n                        
0005640    }  \r  \n                   }  \r  \n  \r  \n           }  \r
0005660   \n  \r  \n   ?   >  \n                                        

I've tried 's/\\r//g', 's/\r//g', and 's/\015//g' and none of them are doing the trick. Since this command worked for other files, I'm at a loss as to why it isn't work on this one. Oh, and just-for-fun:

code:
 redacted $ sed -e 's/r//g' includes/lib/script.inc | od -c
0005420    /       C   l   o   s   e       s   t   e   a   m  \r  \n    
0005440                                f   c   l   o   s   e   (   $   _
0005460    s   t   d   i   n   )   ;  \r  \n                           }
0005500   \r  \n                   }  \r  \n  \r  \n           }  \r  \n
0005520   \r  \n   ?   >  \n                                            
Works just fine, it removed all of the regular "r"s.

ToxicFrog
Apr 26, 2008


oRenj9 posted:

Can anybody help me with this sed command, I'm trying to remove carriage returns from some files. The command worked for most of hte files, but this one is being a bitch for some reason.

I don't know what could be causing this*, but is there a compelling reason why you can't just run dos2unix on the files?

* Ok, if you were doing this on windows (say, using cygwin with the "open text files as text" option) sed would be seeing \r\n as \n alone and not doing any replacement), but you said it worked on other files, so it can't be that.

oRenj9
Aug 3, 2004

Who loves oRenj soda?!?
College Slice
I'm on OSX, so there is no dos2unix. However, I might have been mistaken on it working for other files. Looking through my command history, I found some `tr -d '\015'` in there which might account for why I thought it worked on some files.

I think I'm just going to give up on sed and use tr anyway.

minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender
I have an OOP design question. I have a class that answers Permission questions. The API is nice and simple to use:
php:
<?
$perms = new Permissions();
if($perms->mayUserOpenDoor($user, $door)) {
  $door->open();
}?>
However the Permissions class needs a database connection to do its job. This is pretty easy to hide in the Permissions constructor:
php:
<?
class Permissions {
   function __construct() {
     $this->db_connection = ServiceFinder::getDatabaseConnection();
   }
}?>
But hiding the dependency on the DB connection makes Permissions difficult to unit-test, because it's now hard to inject a mock database. Articles I've read on writing testable code suggest that all dependencies should be specified up-front so that the "testing" clients can inject their own mocks/test-doubles:
php:
<?
class Permissions {
   function __construct($db_connection) {
     $this->db_connection = $db_connection;
   }
}?>
But this makes the API more complex from the POV of the application client, because now it needs to know that Permissions needs a $db_connection. I want that dependency hidden from the application client. So it sounds like I need a facade:
php:
<?
class PermissionsFacade {
   function __construct() {
     $db_connection = ServiceFinder::getDatabaseConnection();
     $this->permissions_calculator = new Permissions($db_connection);
   }
   function mayUserOpenDoor($user, $door) {
     return $this->permissions_calculator->mayUserOpenDoor($user, $door);
   }
}?>
This seems to be the best of both worlds:
- The "application" client instantiates the PermissionsFacade, and is thereby insulated from knowing what the (internal) Permissions class needs.
- The "testing" client instantiates Permissions and since Permissions declares all its dependencies up-front, the testing client can inject mock/test-double database connections for speedy unit tests.

Does this seem right? It smells wrong to me because PermissionsFacade itself can't be easily tested, as it's not declaring all its dependencies up front. What's the best way to go about this?

shrughes
Oct 11, 2008

(call/cc call/cc)

minato posted:

I have an OOP design question. I have a class that answers Permission questions. The API is nice and simple to use:
php:
<?
$perms = new Permissions();
if($perms->mayUserOpenDoor($user, $door)) {
  $door->open();
}?>

The problem with this API is that it's entirely possible for the programmer not to write the check. So instead how about :

php:
<?
$perms = new Permissions();
$door->open($perms, $user);
?>
Or better yet:
php:
<?
$userperms = new PermissionsForUser($user);
$door->open($userperms);
?>
Any action that requires permissions should be impossible without supplying the object proving that such permissions were granted.

Also, having it have its own database connection is icky. Is there not already an existing database connection? With an independent db connection, your permission-checking ends up not being rolled up in the same transaction as your other operations, if they modify the database. If this point is valid, you'll have to pass the database connection to the Permissions object, or maybe there's no need for a persistent permissions object, I don't know what other state it has.

If there is no other database connection or the db is read-only, I would still pass the permissions object separately. Random pieces of code in your project should not just secretly be asking for permissions, opening database connections behind your back.

shrughes fucked around with this message at 00:38 on Feb 25, 2012

minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender
I don't disagree with anything you said, but you focused on areas that weren't the core problem I'm trying to address. I want to resolve the conflict between wanting to hide dependencies (like the DB connection) from the "application" client, but not from the "testing" client.

nielsm
Jun 1, 2009



minato posted:

I don't disagree with anything you said, but you focused on areas that weren't the core problem I'm trying to address. I want to resolve the conflict between wanting to hide dependencies (like the DB connection) from the "application" client, but not from the "testing" client.

What is to prevent you from replacing the ServiceFinder in this?

minato posted:

php:
<?
class Permissions {
   function __construct() {
     $this->db_connection = ServiceFinder::getDatabaseConnection();
   }
}?>

Of course you want to find different services when you are in a testing environment. It's natural to replace the ServiceFinder.

minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender
Replacing ServiceFinder occurred to me too, but apparently a "ServiceFinder" is a testability anti-pattern because it's effectively using global state, and doesn't make it clear to anyone using the class that the ServiceFinder is being used at all. IOW if I was to employ a unit test writer to test that class, they'd have to reverse-engineer the code to understand the dependencies instead of relying solely on the API (i.e. white-box testing vs black-box testing).

nielsm
Jun 1, 2009



minato posted:

Replacing ServiceFinder occurred to me too, but apparently a "ServiceFinder" is a testability anti-pattern because it's effectively using global state, and doesn't make it clear to anyone using the class that the ServiceFinder is being used at all. IOW if I was to employ a unit test writer to test that class, they'd have to reverse-engineer the code to understand the dependencies instead of relying solely on the API (i.e. white-box testing vs black-box testing).

Then do what shrughes suggests.
Don't have a "permissions master" that exists outside of users or whatever kind of role-system you have. Your problem, as you have identified, is that your permissions master needs to access the database or otherwise, and it needs to know what database to access for that.

You need to design your system so either you will be passing some global database object around, or the database is only explicitly referenced in a few locations.

What I would offhand suggest was having your User class know about permissions and implement an interface to check for a user having some specified permission. Then, for every operation, you pass in a user object that specifies the user attempting to perform the operation, and the operation implementation will query for the permission needed.
You can then test your operations by supplying a mock user object.

Your real user class would be the one to know about the database, creating/obtaining a user object would involve the database. When you then need to test the user class you can supply a mock database. (Or supply a real database, but a connection to a testing environment populated with mock data.)


Your current design requires you to pass around a global database object, either as an explicit global or as a "fake" global. (In theory, a global is like a value passed by reference to every single function everywhere. The difference is just whether you make it explicit that it's going in.)
Change your design or live with it.

Adbot
ADBOT LOVES YOU

minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender
Thanks for the input, I appreciate it. What you suggest is unfortunately not possible for this app (politically, if not technically).

After some reading and discussion, the issue I had with ServiceFinder being effectively global may not be such an issue after all. The nuance that was eluding me was that it's not important to make every single class in the app testable via dependency injections, just the classes that do meaningful work.

In other words, the glue code isn't worth unit testing. So I might end up writing this:
php:
<?
class MyApplication {
   $perms = $PermissionsFactory->getPermissions();
   if($perms->mayUserOpenDoor($user, $door)) {
     ...
   }
}
// My job is to do object-graph creation
class PermissionsFactory {
  function getPermissions() {
    $db = ServiceFinder::getDatabaseConnection();
    return new Permissions($db);
  }
}
// My job is to answer permissions questions
class Permissions {
  function __construct($db) {
    $this->db = $db;
  }
  function mayUserOpenDoor($user, $door) {
    return $this->db->someDatabaseSql();
  }
}?>
So I can unit-test Permissions easily because I can inject the dependencies, and I can unit-test the application code by mocking getPermissions() to return a stub class. I don't concern myself with unit-testing the PermissionsFactory because it's just glue code that doesn't do anything beyond object-graph creation.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply