Do Scratch broadcasts really support modularity?

My answer NO - not in practice. They confuse things and make modularity harder to teach.

I am very confused. As a primary school educator (and ex developer with a CS background) I have found that using broadcast develops poor programming habits, confuse me - other teachers and pupils
There seem to be many conflated concepts here

  1. Managing concurrency / Co-ordinating action through message passing - Communicating between objects / or whatever you want to call them depending on your paradigm.
  2. Functional decomposition (modularity) (procedures) again what ever you want to call them.

What is significant is - where is the flow of control - and how do your co-ordinate this with two very different programming constructs.

The lack of early functions (procedures/objects) or again whatever you want to call them - as implemented in Scratch was an awful situation (in my opinion). As teachers and students became very confused with a construct that could initiate multiple new threads but did not return control to the "calling" thread vs modularity... which is so different. I find it hard to write using the proper technical terms.

A huge swathe of resources were created which teach a whole host of misconceptions in this area and which are now "fixed" as "truth" in the teaching community and are hard to overcome now .

There is a paper which I thought gave the background of the design decision to not include functions - because of early student difficulty in understanding the difference between the two constructs http://web.media.mit.edu/~jmaloney/papers/ScratchLangAndEnvironment.pdf

See See 3.4 Inter-Sprite Communications and Sharing
and
3.5 Procedures
" Early versions of Scratch had a mechanism for creating procedures. In early
field tests, however, many users were confused by procedures since they seemed
very similar to broadcasts—both involved associating a name with a collection
of commands. In the interest of simplicity and minimalism, procedures were
removed from the language before Scratch was officially released, and Scratch
has gotten along surprising well without them.
Yet procedural abstraction is one of the “powerful ideas” of computer
science and procedures have practical value as a way to structure code as
projects grow. The Scratch team is considering reintroducing procedures as
a way for users to define their own command blocks. Other researchers have
been developing a variant of Scratch that supports not only procedures but
first-class functions, closures, and a complete functional programming system
[Harvey and Monig 2010]"

THANK GOODNESS they put them back in. I just wish they had not simplified ... and had made procedures HIGH profile in the first place.

This is all my own view :wink:

GREAT points, thank you!

You know, us being the folks who brought back procedures we don't need to argue about their usefulness, especially for modularity! My point about broadcast in the original post really was that I don't want to turn them into function calls by adding the capability to also let them pass parameters. Instead I want folks to use functions, custom blocks for this.

"Messages" à la Scratch are not the kind of messages you find in OOP languages (where they really are just function calls undergoing a fancy name look-up). I've said time and again that I find the term "message" misleading, because every - often half educated - programmer gets triggered by this term and associates it with "message passing", and then - worse - that's what they teach in school. To me they're just symbols, very high-level events. No pay load, no control flow. Except, of course for broadcast and wait, which is kinda like GOSUB used to be in BASIC, and essentially a ... let's say questionable ... idea.

So why did I say broadcast is perfect for modularization? To me it's a question about granularity or unit of distribution. Letting a bunch of sprites react to just symbols is a great way to let kids share them (the sprites) among projects, a great way for students to collaborate via "sprite-ownership", without having to define a whole data exchange protocol first. Instead, if those sprites really need to share state, they can share global variables the same as they already share system resources such as peripherals (e.g. the mouse pointer). By just communicating through symbols and shared variables it's easy to collaborate on the level of contributing and "owning" sprites, because kids don't have to document and agree on the innards of the sprites, such as which costumes, which names for sound, which local custom blocks etc.

Contrary to some I believe that modularity on the macro-level does not have to resemble or mimick the exact mechanisms of the micro-level. Where a module might use direct function calls to pass data internally, it might be useful for modules to communicate among each other through a mechanism that doesn't introduce complex dependencies. That's what I like about "messages" or better "symbols" for.

Great discussion, btw.

[edit:] I've heard the story about Scratch's alleged procedures, and that they claim to have "taken them out" again, and I've even seen demos of those early versions of Scratch, and I'm not sure I'd call these early mechanisms "procedures". They might have overstated the alleged prior existence of procedures in Scratch. I do know that when I first implemented BYOB for the Scratch Team using our Scratch sources the evaluator didn't allow parameter passing and recursion was impossible, not to speak of variable scope, which didn't exit, so I had to wrestle hard to make procedures possible. If they really did have procedures and functions in earlier versions of Scratch they must have done a helluva job to completely erase any trace of them from existence in the sources :slight_smile:

Are there examples of kids combining two (or more) independent projects in a manner that was significantly simplified by relying upon symbols/messages (that would have been more difficult if instead the projects relied upon custom blocks)? I see the potential here for doing so, but wonder if this really occurs in practice?

In a project 20 years ago I was very impressed when two Swedish 7-years olds took a Pong game and a Space Invaders game and created Space Invaders Pong. The Pong paddle could hit the ball but also shoot missiles at the invaders. And the ball bounced off invaders.I forget how they kept score. Is this the kind of thing the kind of modularity we are talking about should support?

I agree it doesn't "have to" but it does lead to a simpler computation model (or notional machine). And there is something beautiful about very expressive systems despite containing only a small number of primitive constructs.

I've experimented with a version of Scratch from February 2004, and I can confirm that it did actually have procedures, with both parameter passing and recursion! The October 2004 version does as well, but I haven't tried any later builds.

That's brilliant! Especially for supposedly-preoperational 7 year olds! Is the project online somewhere?

I don't know about early versions, but when they decided to add procedures in 2.0 it was at first going to be procedures without inputs. I made them add inputs by saying "how does this differ from broadcast and wait?" :~)

I wish it was still online. I found other games made in the project in the Wayback Machine. You can see the two boys in the photos posted along with another game they made called "Minotaur Rules the World".

Also all these games only ran in Windows.

And if there is more than one listener to the broadcast then broadcast and wait does more than procedures without inputs.

I realise that this discussion has gone off into some deep CS stuff...

...BUT...

as an ex-primary school (7-11 year olds for non-UK people) educator teaching Scratch, I've NEVER had to go beyond the concept that broadcasts are whispered messages between scripts/sprites.

If they contravene some CS principle - so what? :slight_smile:

Its Scratch

Scratch is to introduce computing - not be some sort of definitive CS reference

Not be Lisp/Scheme/C+++ or Snap! :slight_smile:

Please carry on with the great CS discussion but stop dissing Scratch :slight_smile:

To the extent that that's addressed to me: I don't mean to dis Scratch. I think it's an absolutely brilliant piece of work, in which the actual software is just part of a thriving community of work including adults and kids together. I admire the careful design effort that has gone into every little thing. I made Jens implement that little arrow at the bottom of looping blocks that reminds you there's a loop happening, taken from Scratch.

But they have this idea that having really powerful features in the language will scare away the eight year olds. (Truth in arguing: When I say that to Mitch he vehemently denies thinking that. But I don't know how to explain this point in different words.) We'll find out: We're about to jump into a large experiment to see whether adding the power of APL to simple blocks like + will scare users away. I'm betting that beginners won't even notice, or if they try it and it works they'll take that in stride. (Up to now if they try it they just get an error message, but it's totally clear what they meant and now we'll give them that.) Michael thinks I'm wrong. Cross your fingers.

CS principles have various justifications. Many of them (including the ones discussed in this thread) are about enabling projects to scale. We are talking about raising the ceiling. But when doing so if we also raise the threshold/floor, such CS principles may be counter-productive in many educational contexts.

Some CS principles are about powerful ways of thinking - e.g. Snap!'s first-class functions and the forthcoming APL-like generalisations of some blocks. They can be very valuable even to students who do not intend to study CS. But in some cases, these principles are difficult to learn (and teach).

Some CS principles are about avoiding bad ways of thinking about and expressing computation. See this Wikipedia article 'Considered Harmful'. Perhaps broadcasting symbols without more information is an example.

Nah,scratchblocks does that.

This is a fairly old thread, but I have found a thesis which appears to be a potential origin point for Scratch's broadcasting system, and it actually provides some pretty compelling arguments.

Back in Scratch 0.1, objects could communicate by running each other's scripts. This was done by dragging a block from one sprite's block palette to another sprite's script panel.

This screwed with modularity in a big way, as which sprite the block "belonged to" was hard-wired - if a sprite communicated with other sprites within a project, you couldn't take it from one project and put it in another without ruining its functionality, as the other sprites it communicated with didn't exist there.

The alternate solution of being able to store sprite references in variables and sending messages to the sprites referred by those variables is mentioned, but that path "wasn't taken" in this paper. Probably for good reason, too, since I don't think it would've been intuitive in the slightest for kids using Scratch.

There are some differences between the way broadcasts were envisioned on paper and how they eventually got implemented. One of the ideas that I wouldn't mind seeing in modern Scratch are the "repeat until broadcast" and "wait until broadcast" blocks.

Two other ideas that really stuck out to me are (A) the idea of broadcasts with data arguments, and (B) the idea that a broadcast hat script should just continue on, instead of restarting or running multiple times at once, when it receives the same broadcast again.

The second idea seems a bit counter-intuitive, and I think the author wasn't too sure about it either. Broadcasting a message should cause the responses to activate in other sprites regardless of whether they were already responding to that message. On the other hand, broadcasts running multiple times simultaneously could lead to very confusing behaviours and race conditions. Modern Scratch's behaviour, where the broadcast script restarts when it's sent again, is probably the best answer here, even if it's not perfect.

This got me thinking. In modern Scratch, sending a broadcast restarts any broadcast scripts that were already running. Therefore, using global variables to communicate extra information as well as broadcasts is actually functionally equivalent to specialized broadcast data parameters. If a broadcast script receives a value this way, the same broadcast message could be sent again, but this couldn't cause any interference, because it means the hat script stops what it's doing and restarts anyway.

Essentially, the Scratch Team started with the idea of one sprite telling another sprite to run scripts. They realized that this was either too rigid or too confusing, as either the receiver would be hard-wired into the block itself or it would have to make use of variables that stored "sprite references".

Then someone came up with the idea of the broadcasting system with support for data arguments, and it was tweaked so that broadcast scripts stopped and restarted when the same broadcast was resent. Finally, I'm guessing, they realized that these data arguments were unnecessary, and could be replaced by global variables, as all the scripts with access to the old values would have been stopped and restarted anyway.

I realize now that broadcasts actually do have some strengths to them, even when it comes to modularity. While I disagree with the Scratch Team for waiting so long to implement custom blocks, and I think it could still be improved in some respects, I respect their thought process in coming up with the broadcasting mechanism.

Anyway, it's 2 am where I live. I should've been asleep 2 hours ago, but that paper really captured my attention. Goodnight!

Thanks for posting this thesis! Much of Scratch's original interpreter was Dave's work, and afaik the concept of broadcasts was Brian Silverman's original idea.

I don't understand this. If like in NetsBlox message parameters are part of the "message" then if some sprite sends <dance 3> and it or another sends <dance 4> then how would a global variable capture whether it is 3 or 4. Or are all message sends synchronous so that immediately after sending all the receiving hats start working?

I don't see why this is the "best answer". If each message, say, moves a sprite then it may only move once instead of twice depending upon who knows what. Queueing messages seems much better.

I fail to see why computer science ideas that are over 50 years old are being ignored here - they aren't hard. Smalltalk did this so much better and it was designed for children.

Oh, I cannot not agree with this! :smiley:

Sadly, though, Smalltalk may have been designed for children, but it was only successful in enterprise applications. Didn't all the schools use Pascal and later Java? I'm sure this is entirely unrelated to how events / messages / dependents-updates worked in Smalltalk, but perhaps symptomatic nonetheless.

But, boy, I sure miss Smalltalk!

By "it" do you mean Smalltalk-80 or also Smalltalk-72 and Smalltalk-76 that Alan Kay claims were kid-friendly? And I don't know much about the history of Squeak...

In modern Scratch, resending a broadcast stops and then restarts all the matching "when I received" blocks. If you're using broadcast arguments or global variables to determine which kind of dance to do, either way, all the sprites will stop doing dance 3 and start doing dance 4.

If you use a global variable to communicate the dance number, it doesn't matter that the variable is overwritten - it's no longer accessible, because all the scripts that were doing dance with 3 already stopped and restarted anyway.

Therefore, if those broadcast arguments are clogging up the UI and don't actually add any extra safety to the broadcasting mechanism, there's no reason to keep them.

Of course, this all depends on the modern Scratch behaviour of broadcast scripts stopping and restarting when the broadcast is resent. Whether that should actually be the case is another question entirely.

The justification given in the paper is that the "stop and restart" behaviour ensures that each script can only be running once at a time, rather than a script running several times at once. They believed it would be more intuitive for kids to understand, and would also make it far easier to visualize the current running state of the project - all the GUI needs to do is indicate if a script is running or not running.

Of course, the same is also true to an extent if messages were queued. Page 43 briefly mentions a behaviour where broadcast blocks would wait for their scripts to finish running, then start them again and continue on. This is close to, but not the same as the message queueing behaviour you seem to prefer. I wonder if they just didn't consider it.

Thanks. But I'm still unclear about this. Consider how differently these two ways of broadcasting work.

Here's the project:
https://snap.berkeley.edu/snap/snap.html#present:Username=toontalk&ProjectName=broadcast