Sunday, November 12, 2023

City college (CCNY) undergraduate computer science sequences

The sequences are important to understand for CCNY CS students, because they need to be taken strictly in order across several semesters. Without good planning, it's easy to need more than four years to complete the degree. It's also very easy to get closed out of a full class in any given semester.

The most important sequence is:

  1. CSc 10300 Intro to Computing for Majors
  2. CSc 10400 Discrete Math Structures (this also needs Calculus I, so that should be taken ASAP)
  3. CSc 21200 Data Structures
  4. CSc 22000 Algorithms
Most Computer Science classes depend on CSc 22000 Algorithms!

The next most important sequence is:
  1. Engl 11000 Freshman Composition
  2. Engl 21007 Writing for Engineering
  3. CSc 22100 Software Design Lab
...because multiple required classes depend on CSc 22100 Software Design Lab.

Also important:
  1. Math 20100 Calculus I
  2. Math 21200 Calculus II
  3. Math 21300 Calculus III, Math 34600 Linear Algebra, CSc 21700 Prob & Statistics
  4. CSc 30100 Numerical Issues in Scientific Prog
...because CSc 30100 Numerical is a required class, and is also required by multiple electives.

And, after the first sequence or two above has been completed, the following required classes are better to take sooner rather than later, because they are required for various electives:
  • CSc 30400 Theoretical Computer Sci
  • CSc 33200 Operating Systems
  • CSc 32200 Software Engineering
There's also the required small sequence:
  1. CSc 21100 Fund. of Computer Systems
  2. CSc 34200 Computer Organization & CSc 34300 Computer Organ. Lab
...which is also the prerequisite for just one elective.

It's good to take Speech 11100 Foundations of Speech Comm early, and maybe CSc 11300 Programming Language, but all other classes should be treated as "filler", taken to reach at least fifteen credits per semester when the above are not possible.

Friday, August 25, 2023

Simple reactive language idea

Here's my idea for a high level programming language in case I never get around to implementing...

Start with a really simple subset of a boring procedural language. I like python syntax, but it's not important.

Support reactive variables, aka cells aka FRP signals. Forbid reassigning globals except using a repl. Make that statically checkable.

a = 1
b = a + 2
//changing a to 4 automatically changes b from 3 to 6

Make functions use Mutable Value Semantics, for all parameters and return values. That is, have all values be semantically "pass by value", not just primitive values. So changing things inside a function has no affect on things outside of the function except for what the function explicitly returns. Make it relatively fast using persistent data structures.

Support working with individual members of a collection reactively. So, in addition to:

fuSprite = mouse.position + 2
//for a single sprite which follows the mouse

also support:

a barSprite = mouse.position + 2 on mouse.click
//multiple stationary sprites, with a new one created every time the mouse is clicked

(I haven't thought too much about the best syntax here. The word "a" or "an" in beginning is cute and english-y, but may be too much. I also don't know whether the trigger ("on mouse.click") should be before or after the expression. Also please forgive my handwavy introduction of events.)

Though the last pair of examples are GUI oriented, I'm dreaming of this language for general purpose use, including traditional server side code. I can't help thinking this is the "holy grail", a major step towards liberating programming from the von Neumann style. It's not an especially original idea, just a rejiggering of push-pull FRP for all non-local mutation, but I can't see why it wouldn't make programming dramatically simpler.

The major advantages are:

  1. Referential transparency - like in haskell but simpler
  2. Enhanced "view source" - anything you see on a computer, you could click and find out why, following the declarative trail all the way back to the first triggering events from outside
  3. True separation of concerns - this is only a hunch so far! I'm hoping that the more declarative approach could allow orthogonal implementation of genuinely useful features, like persistence or distributed consistency.

Tuesday, July 04, 2023

Trunk based dev and merging

The unfortunate reality is that new code contains new bugs. Unless you want to stop all feature development while a release candidate is being tested and fixed, you're going to need a mechanism for selectively including code in releases.

There are two different ways to do this: trunk based development and release branch merging.

If you can get away with having only a single version of your software running live at a time, you can use trunk based development very simply: Have only a single release branch live at any time. Always add changes to trunk, and never directly into the release branch. Cherry pick bug fixes from trunk to the release branch. Manually test bug fixes in the release branch.

If you need to support different groups of users using different versions at the same time, trunk based development gets a little trickier. For example, Stakeholder A desperately want a new feature, but delivering that feature risks destabilizing the the product for Stakeholder B. You'll need multiple release branches that include different sets of changes. There are only two known solutions: feature toggles and release branch merging.

Feature toggles involve guarding new code with a runtime flag, such that the risky new code can be disabled for stakeholders that don't care about it. One additional advantage of feature toggles is that, if the new code ends up having a major bug which is discovered in production, it can even be easily disabled for everyone. The two big disadvantages are: 1) feature toggles open up a brand new category of technical debt, and 2) you need to have whole new mechanisms for managing them. For example, how do features get toggled based on testing? How do you handle feature combinations and interactions?

The alternative is to leverage the merge support in modern revision control systems like git. Instead of trunk based development, fix bugs directly against the release branch. Then always merge all changes from more stable branches to less stable branches, from release branch to mainline. There is a bit written about this under the name "gitflow", but the approach existed before gitflow, and gitflow really describes a larger standard. Some things are not complicated: if you're doing code reviews, you should be using "topic" branches. Many web pages just confuse matters in their comparisons of gitflow, github flow, gitlab flow, and trunk based development. The real question is: would you prefer to use feature toggles to enable trunk based development, or would you prefer to merge from release branches?

Release branch merging is not a panacea, and it can be a pain. Arguably it is simpler than feature toggles though; it is trivial to understand whether master is caught up with all of the bug fixes from release branches. The installed version number tells you exactly which code is in your system, and you easily compare it with other versions of the code that were or will be running at any other time.

Quotes:

Raymond Chen, long time Microsoft developer: “Cherry-picking is a common operation in git, and it’s not a good idea. Sometimes it’s a neutral idea, but I haven’t yet found a case where it’s actually good.

Google according to Winter, Manshreck, and Wright: “A key to reliable continuous releases is to make sure engineers "flag guard" all changes.” (emphasis mine)


Friday, February 03, 2023

Messaging notifications

Funny that we're hoping to soon build programs that can think like people, but we can't build group text messaging that doesn't suck.

We need a few simple features, each related to the previous:

1) Notify a group of people regarding the start of a conversation, but not each subsequent message in the conversation.

2) Show at a glance if there are unread messages of genuine interest. So allow easily dismissing a whole conversation.

3) Dismissing on your phone should dismiss on your computer and vice versa.

I have a sense of why the feature 1 is hard: people aren't good at selecting threads of conversation. There are three remedies:
  • make the UI more clear, perhaps automatically labeling each thread with an automatically generated subject
  • make it possible to change the thread that a message is in, after the message was already "sent"
    • changing the thread is too late for sounds triggered by notifications, but they could update the "keep up-to-date" style interface of feature 2 above. 
  • if notifications are actually working like they should, people will be more motivated to get the thread right in order to get the notification right.