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
Remulak
Jun 8, 2001
I can't count to four.
Yams Fan
Oh god this is giving me flashbacks to when my wife taught remote webdev for non-majors, the material was archaic and they didn’t want anything changed. When she complained and even offered to update the course they did that they always do to adjuncts that actually try to make things better and stopped giving her courses.

Adbot
ADBOT LOVES YOU

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

pokeyman posted:

This is sounding like the most realistic intro dev course around. Possibly unintentionally.

Also flashing back to failing an assignment because I used java.util.Scanner when that was next week's assignment.

Yeah sounds about right.

Ihmemies
Oct 6, 2012

Apex Rogers posted:

Yup. This reeks of junior dev coming in and trying to change the world on day 1, not realizing the restrictions that are in place, for good or bad.

If they want to hold a course set in stone, they should teach C or FORTRAN or something. With web they really should get on with the times.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Ihmemies posted:

I have determined that our university’s webdev1 course is pure coding horror. Plain ES5/6 mixed haphazardly, mongodb, age old node packages. I tried to swim against the tide, using ES6 features like modules, and import/export, until a test in this week’s assignments banned them.

/home/user/study/tuni/webdev1proj/dist/models/user.js
I give up. I am making Internet Explorer compatible webpages with pure ECMASCRIPT 5 in TYOOL 2023. And I don’t have a choice if I want a grade from the course.

gently caress. gently caress this horseshit. 2nd largest uni in Finland btw, don’t come here to get your CS degree.

i'm 38, a principal engineer at a software company and have a master's degree in computer science and i literally never took a class that had javascript or any other form of webdev in the curriculum - every class i took at undergrad or grad level was in C++/C#/java.

i am a big fan of functional programming (which is also something that I didn't learn in college) but I feel that restricting for loops is getting lost in the sauce (unless the objection is that for loops require declaring an variable as an iterator). Do the tests bomb out if you use Array.prototype.foreach (which is a horrible method that you shouldn't use but it might let you pass this class?)

It feels like the instructor probably wanted to teach a class using haskell or closure or something and they might've been at odds with the department because "no one uses those languages in real life." Which given my entire experience with cs education is completely ironic.

Ihmemies
Oct 6, 2012

We don’t have enough courses with “real” programming languages so I have to take some web courses too. I’m doing a Haskell course now and it’s not too bad.

The problem was typescript’s polyfills. I did the experiment in a branch so our main still has the vanilla JavaScript version. I just wanted to vent, there’s no problems left to solve anymore really :cheers:

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Bruegels Fuckbooks posted:

i am a big fan of functional programming (which is also something that I didn't learn in college) but I feel that restricting for loops is getting lost in the sauce (unless the objection is that for loops require declaring an variable as an iterator).

Something like "we're trying to teach recursion so no for loops please" seems pretty reasonable?

OP the real answer is figure out how to obfuscate the for loops to bypass the for loop detector.

Athas
Aug 6, 2007

fuck that joker
Use JavaScript to implement an interpreter for a small Lisp and write all your code in that.

canis minor
May 4, 2011

Put your js code in a comment and eval that node

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man
yeah i feel like people are missing that the "linter" is a homework checker and the rule "no for loop" is not asinine it's the assignment, that's the purpose of the assessment: can you use recursion to do things you have previously only used iteration for.


do your drat homework op

Ihmemies
Oct 6, 2012

Phobeste posted:

yeah i feel like people are missing that the "linter" is a homework checker and the rule "no for loop" is not asinine it's the assignment, that's the purpose of the assessment: can you use recursion to do things you have previously only used iteration for.


do your drat homework op

I don't think your reading comprehension is very.. comprehensive.

StumblyWumbly
Sep 12, 2007

Batmanticore!
The painful part of teaching CS is that many of the important tricks are mainly applicable to large projects, but you don't necessarily want to make a large project be the assignment, so you get questions like "Do X, but don't use these 5 common features that would make this easy"

Athas
Aug 6, 2007

fuck that joker

StumblyWumbly posted:

The painful part of teaching CS is that many of the important tricks are mainly applicable to large projects, but you don't necessarily want to make a large project be the assignment, so you get questions like "Do X, but don't use these 5 common features that would make this easy"

I disagree; most important tricks are useful even in the small.

However, overly elaborate object oriented analysis and design is not one of those tricks, yet many study programmes still insist on teaching it to students who've never written a program with more than fifty lines of code.

In my own teaching, the only time I ban the students from using a language feature is when I ask them to implement binary arithmetic in C without using control flow or any built-in arithmetic. And that's only because the learning goal is to understand the two's complement representation and how arithmetic can be expressed as Boolean logic. If the students had more time, I'd have them do it in a proper hardware description language.

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

Athas posted:

I disagree; most important tricks are useful even in the small.

However, overly elaborate object oriented analysis and design is not one of those tricks, yet many study programmes still insist on teaching it to students who've never written a program with more than fifty lines of code.

In my own teaching, the only time I ban the students from using a language feature is when I ask them to implement binary arithmetic in C without using control flow or any built-in arithmetic. And that's only because the learning goal is to understand the two's complement representation and how arithmetic can be expressed as Boolean logic. If the students had more time, I'd have them do it in a proper hardware description language.

At least in my experience, I've run into a lot of scenarios where tutorials /etc all run over common tips like dependency injection/etc without explaining it, resulting in a sort of 'implement magic' problem, and many of these don't really show their problems until your project gets up to a larger scope.

DI in specific, just to pick a topic, is something that most student projects could absolutely avoid, because...well gently caress it, how many lines of code could you have written? Oh no, you're initializing a client over and over? Who cares. Unless your teacher has you writing tests, you'll probably never even pick up on the downsides, and even if they do, you might just monkeypatch things to get it working.

I don't disagree with you that sometimes people teach stuff that's way too big to be useful, but I also think that there's a lot of common software design stuff that tends to just get cargo culted in sometimes; leading to issues like me having to rip out a thousand lines of code that implemented absolutely useless java-style 'private instance variables' in Python because the people didn't know why you did it that way in Java, but they sure as hell were going to keep doing it that way.

Context for that - I mean stuff like this, devoid of any transformation or side effects:
Python code:
class Butts:
  _left_cheek: Cheek

  @property
  def left_cheek(self) -> Cheek:
    return self._left_cheek

  @left_cheek.setter
  def left_cheek(self, value):
    self._left_cheek = value

Ihmemies
Oct 6, 2012

Ok we're at uni's datastructures & algos course. Had some kind of publication database project, and I got some works to peer review from other students.

Someone had used std::find in every possible func to check if an affiliation/publication exists.

C++ code:
    std::unordered_map<AffiliationID, AffiliationData> affiliations_map;
    std::unordered_map<PublicationID, PublicationData> publications_map;

     std::vector<AffiliationID> affIDList;
    std::vector<PublicationID> pubIDList;
And had this datastructure. He used map.find in a case or two, but in most cases he used std::find on the two vectors there. As a result:

code:
> perftest get_affiliations_distance_increasing 10 10 100;1000;10000;100000;1000000
Timeout for each N is 10 sec. 
For each N perform 10 random command(s) from:
get_affiliations_distance_increasing 

      N ,    add (sec) ,   cmds (sec) ,  total (sec)
    100 ,     0.000844 ,     0.000139 ,     0.000983
   1000 ,    0.0133741 ,    0.0013541 ,    0.0147282
  10000 ,     0.984839 ,    0.0182649 ,       1.0031
 100000 , ADD Timeout!
 
I had to get the thing pass school's automatic graders so I ditched the std::find in favour of map.find:

code:
perftest get_affiliations_distance_increasing 10 10 100;1000;10000;100000;1000000

Timeout for each N is 10 sec. 
For each N perform 10 random command(s) from:
get_affiliations_distance_increasing 

      N ,    add (sec) ,   cmds (sec) ,  total (sec)
    100 ,    0.0003254 ,    0.0001128 ,    0.0004382
   1000 ,    0.0030873 ,    0.0013762 ,    0.0044635
  10000 ,    0.0306572 ,    0.0179135 ,    0.0485707
 100000 ,     0.376332 ,     0.277596 ,     0.653928
1000000 ,      4.69242 ,      5.16892 ,      9.86135
Because the project timed out, it did not pass school's automatic graders and got F for the project. I guess the student still wanted some peer feedback on why his program ran so godawfully slow. He correctly documented that his functions are generally O(n) worst case. For a single function call. Ok that didnt ring any bells, since the task description said funcs running at O(n^2) or above are too slow and not allowed, but my funcs are O(n) so I shouldn't have any problems right :)

Well if you add 1M affiliations, and for every add, search the datastructure if the affiliation already exists. Of course it doesn't exist because it hasn't been added yet, thus std::find ends up iterating through the whole dataset. Every time. Adding 1M affiliations to empty dataset means a total of ~500 billion (5 and 12 zeroes) iterations..

So the actual average case performance becomes O(n^2) for most of the functions, when ran repeatedly. Want to add 1M new affiliations? O(n^2). Want to look up an affiliation's name N times? O(n^2).

The autograder graded the work to 6 levels, from 0..6. This got initially 0 thus a fail because the code timed out during performance tests. I spent 1,5 hours replacing the std::finds with map.find and got a 5 out of 6 so the 2nd best grade for the project.

This was my horror story today. Actually quite sad, the guy had probably seen a lot of effort but could not realize by himself why the evil automatic grader failed his beautiful software.

Also this beautiful question was asked. Performance grader runs on linux so it counts every cmd the program executes.

quote:

What does the command count mean in perfestimate? Does higher command count mean that it is faster since it ran more commands in the time?

Well I'll share some snippets of the horror anyways..

C++ code:
bool Datastructures::add_affiliation(AffiliationID id, const Name &name, Coord xy)
{
    if ( std::find(affIDList.begin(), affIDList.end(), id) != affIDList.end() ) {
        return false;
    }
// etc
}

Name Datastructures::get_publication_name(PublicationID id)
{
    if ( std::find(pubIDList.begin(), pubIDList.end(), id) == pubIDList.end() ) {
        return NO_NAME;
    }

    return publications_map.at(id).name;
}

bool Datastructures::add_affiliation_to_publication(AffiliationID affiliationid, PublicationID publicationid)
{
    if ( std::find(pubIDList.begin(), pubIDList.end(), publicationid) == pubIDList.end() ) {
        return false; }

    if ( std::find(affIDList.begin(), affIDList.end(), affiliationid) == affIDList.end() ) {
        return false; }

    //Add publication and affiliation to eachother.
    affiliations_map.at(affiliationid).related_pubs.push_back(publicationid);
    publications_map.at(publicationid).related_affs.push_back(affiliationid);
    return true;
}

and so on..

Ihmemies fucked around with this message at 15:14 on Dec 9, 2023

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...
Student code is cheating, unless they're a grad student or above who should realistically know better. All of us made abject horrors of one kind or another.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Replacing uses of std::find() on a map with map.find() is something I've done to actual production code to fix performance problems multiple tims.

CPColin
Sep 9, 2003

Big ol' smile.
Yeah, I've seen if (map.contains(key)) { return map.get(key) } else { return null } plenty of times too

Ihmemies
Oct 6, 2012

Volmarias posted:

Student code is cheating, unless they're a grad student or above who should realistically know better. All of us made abject horrors of one kind or another.

The horror came from it that I spent 6 hours today fixing two projects as a part of the course’s mandatory peer review. We had to identify slow parts, and run the code on university’s code tester so it could provide new performance estimates.

I have no pedagogic skills so all this was quite difficult. Anyways, first guy would have went from failed to average grade with just the std::find removal. 2nd guy did multiple map.finds to regular map in a loop, which tanked his grade. I adjusted it and the program then was fast enough to produce the best grade.

People really should read more cpprererence. https://en.cppreference.com/w/cpp/algorithm/find

You don’t want to call that too many times repeatedly to a large dataset, if you can avoid it. We spent 14 weeks learning basics about data structures and algorithms and from my peer review sample size it feels people did not understand the theory at all :eng99:

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Student code is cheating but still hilarious, and that includes mine.

GABA ghoul
Oct 29, 2011

CPColin posted:

Yeah, I've seen if (map.contains(key)) { return map.get(key) } else { return null } plenty of times too

I'm not a coding horror perpetrator, BUT ...

IIRC the .NET hashmap actually throws an exception when a key is not present. So for someone coming from that neck of the woods that would be good code.

There is a TryGet method too, so you don't actually have to write the above every time. But I don't know how long it's been there

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
std::find is appallingly named. If it were a method on a data structure where a linear search is the only reasonable implementation for a find, then maybe; but as a free function, it really ought to be called something like std::linear_search.

While I’m on the subject, I also hate how std::upper_bound has an important precondition that isn’t stated at all. It should either do that (i.e. std::upper_bound_in_sorted) or be named after the algorithm (i.e. std::binary_search_upper).

Really the whole iterator-based algorithms concept is a rolling disaster.

Ihmemies
Oct 6, 2012

In cpp you can use iterators like this.

code:

if (auto search = example.find(2); search != example.end()) {
        std::cout << "Found " << search->first << ' ' << search->second << '\n';
}
Personally I learned this right now. I had been using the same idea but with more code.

Ihmemies fucked around with this message at 18:42 on Dec 9, 2023

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

rjmccall posted:

Really the whole iterator-based algorithms concept is a rolling disaster.

That's just hindsight. Reading one of the original STL papers was a real watcher-of-the-skies-when-a-new-planet moments for me.

VikingofRock
Aug 24, 2008




Is there anything that would prevent them from adding a template specialization that would call map.find() when you call std::find() on a map?

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
could this fellow student have gone to the professor or to teaching assistants to get feedback and help on why their code ran so slow? the op refers to "peer feedback". That's all very well, but shouldn't the student be able to get help from the people actually teaching the course? Something seems a bit lacking, but it's possible I misunderstand (perhaps for example it is a case where they can't provide specific help on the exercise until after the deadline for submission, because it's part of the assessment for the course)

If the student understands nearly everything they need to understand, but not the particular thing they missed here, it seems a poor show if they can leave the course none the wiser when it could have been pointed out and corrected. that is the point of teaching surely.

SupSuper
Apr 8, 2009

At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it.

VikingofRock posted:

Is there anything that would prevent them from adding a template specialization that would call map.find() when you call std::find() on a map?
std::find only takes iterators, not containers. You can't get to map.find() from map.begin() map.end()

OddObserver
Apr 3, 2009

Ihmemies posted:

In cpp you can use iterators like this.

code:

if (auto search = example.find(2); search != example.end()) {
        std::cout << "Found " << search->first << ' ' << search->second << '\n';
}
Personally I learned this right now. I had been using the same idea but with more code.
It's a C++-17 feature, so there is a lot of code/text out there that doesn't take advantage of it.


VikingofRock posted:

Is there anything that would prevent them from adding a template specialization that would call map.find() when you call std::find() on a map?

There are overloads that take unary predicates, those won't work with anything other than a linear scan..

Edit: nm, that's find_if; still would be weird, though.

...Actually I am confused as to how the original code works, won't find for key fail since values in a map are KV-pairs?

OddObserver fucked around with this message at 19:50 on Dec 9, 2023

Xarn
Jun 26, 2015

Plorkyeran posted:

Replacing uses of std::find() on a map with map.find() is something I've done to actual production code to fix performance problems multiple tims.

I have flashbacks from being the "performance" expert at my first job during uni, which meant I would go and fix foreach loops over hash maps from our (very cheap) outsourced team. Pretty much everyone in that got exactly what they paid for.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Zopotantor posted:

That's just hindsight. Reading one of the original STL papers was a real watcher-of-the-skies-when-a-new-planet moments for me.

On the one hand, yes? I’m stating my opinion about it. The default assumption should be that I’m speaking from my current perspective, not engaging in an elaborate thought exercise about what my opinion would have been thirty years ago. That does mean I’m speaking with hindsight. I’m not trying to call the STL designers clueless idiots; I’m saying they nonetheless came up with a design that I think makes a lot of mistakes.

On the other hand, I think people back then could have criticized — and probably did criticize — that design on grounds that have been more-or-less proven correct. There is absolutely some elegance in how the STL generalizes pointers into iterators and recognizes a hierarchy of capabilities. But that design also fails to appreciate some of the ways in which pointers as array iterators are unique, and that was already clear just in the non-array-like collections in the STL. And it specifically broke with standard OO principles like “make self-contained concepts classes and make the operations on them methods”, and I think if they’d stuck to that philosophy, the design still would’ve had that hierarchy-of-capabilities elegance but without its biggest flaws.

rarbatrol
Apr 17, 2011

Hurt//maim//kill.
All this talk about inefficient implementations made me remember something I fixed a few years back that had been in production for almost a decade. It was a 3rd party OCR tool that would process a document page by page, and we would dump the per-page text output into a temporary database for jobs like this. How did the original author collate the OCR output back into a single piece of text? By iterating over all the page numbers and running a SQL command, something like:
code:
UPDATE [DestinationTable] SET [DestinationText] = [DestinationText] + (SELECT [PageText] FROM [JobsDB].[Pages] WHERE [PageNumber] = @page AND [JobID] = @jobID) <appropriate where clause goes here> 
Not only was it fairly slow once it got up there in page count, it was using cross-database transactions so it would block other job types. When that process encountered the odd 100,000 page job, it was guaranteed to ruin somebody's day.

rarbatrol fucked around with this message at 21:25 on Dec 9, 2023

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
I think Stepanov's decision to make iterators the primitive data structure instead of ranges has proven to be the biggest mistake. You don't lose any generality with ranges and it makes many things infinitely less clunky.

SupSuper posted:

std::find only takes iterators, not containers. You can't get to map.find() from map.begin() map.end()

The public API does not expose what you need, but it would not be impossible to implement a O(log N) lookup in a map given a pair of iterators. The STL's free functions could have done the more optimal thing that the member functions do even with their current API had that been a design requirement from the beginning. I'd like to think that if the STL had gone through another iteration or two before it got standardized and thus frozen that would have been one of the problems he would have solved.

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

rjmccall posted:

On the one hand, yes? I’m stating my opinion about it.

Yes, sorry. Rereading my post, I see it could be taken as condescending; that was not intended (non-native speaker here).
What I should have written was something like, "nowadays I see that too, but…"

Nalin
Sep 29, 2007

Hair Elf
STL's biggest horror is how they implemented std::swap.

ExcessBLarg!
Sep 1, 2001

Ihmemies posted:

Ok we're at uni's datastructures & algos course.
As the rest of the thread is kind of beating around, it's interesting to me that this course uses C++ as the language of instruction. Most schools switched to Java or C# some 20 years ago, because even back then C++ was a language with a lot of legacy and baggage, and the nuances of C++ aren't easy for a novice to decipher and, simultaneously, distract from the actual learning of data structures and algorithms.

Also, I don't think an autograder running on a correct, but inefficient program should result in a failing grade unless the student has access to the autograder ahead of the assignment due date (it wasn't clear to me if this was the case here), and even then I'm not sure it should do that. Like, a student inefficiency using an O(n) search where a O(1) lookup is warranted is a common mistake to the point that the autograder should be aware of it.

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


This doesn't seem to be a particularly well-designed course.

senrath
Nov 4, 2009

Look Professor, a destruct switch!


ExcessBLarg! posted:

As the rest of the thread is kind of beating around, it's interesting to me that this course uses C++ as the language of instruction. Most schools switched to Java or C# some 20 years ago, because even back then C++ was a language with a lot of legacy and baggage, and the nuances of C++ aren't easy for a novice to decipher and, simultaneously, distract from the actual learning of data structures and algorithms.

Also, I don't think an autograder running on a correct, but inefficient program should result in a failing grade unless the student has access to the autograder ahead of the assignment due date (it wasn't clear to me if this was the case here), and even then I'm not sure it should do that. Like, a student inefficiency using an O(n) search where a O(1) lookup is warranted is a common mistake to the point that the autograder should be aware of it.

On the other hand, you have to set the autograder to time out eventually, otherwise you'll eventually end up in a situation where the entire system is blocked on infinite loops submitted by students.

ExcessBLarg!
Sep 1, 2001

senrath posted:

On the other hand, you have to set the autograder to time out eventually,
That's totally fine. The autograder should be able to recognize the result of the 10k test case and assign an appropriate grade when it hits the timeout.

senrath
Nov 4, 2009

Look Professor, a destruct switch!


ExcessBLarg! posted:

That's totally fine. The autograder should be able to recognize the result of the 10k test case and assign an appropriate grade when it hits the timeout.

It really depends on what the grading criteria was. If the criteria was "can it handle each of these cases", then yes, it should've given them points for the three cases it handled. But if the criteria was based on how fast each program is, then a 0 for a timeout is reasonable.

ExcessBLarg!
Sep 1, 2001

senrath posted:

It really depends on what the grading criteria was.
Right, I'm saying a failing grade for this kind of assignment is bad criteria.

Adbot
ADBOT LOVES YOU

senrath
Nov 4, 2009

Look Professor, a destruct switch!


ExcessBLarg! posted:

Right, I'm saying a failing grade for this kind of assignment is bad criteria.

As long as they knew ahead of time that they'd be graded on speed I don't think it is. If the assignment explicitly said it needed to run quickly then an inefficient implementation doesn't meet what was required.

That said, yeah, you're probably right that it was poorly signposted and poorly implemented because a lot of courses are just badly put together.

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