8 ms·
Jackson structured programming
- gerikson 5y agoI learned to plan programs with this.
- ithkuil 5y agoI have to admit that when I first heard the Jackson reference in https://youtu.be/HxaD_trXwRE?t=00m44s https://youtu.be/HxaD_trXwRE?t=00m44s I thought it was about the other Jackson.
- zetalyrae 5y agoFor such a young discipline, it's amazing how much of software practice used to be standard operating procedure and is now all but forgotten. At one time Dijkstra had to actually argue for structured programming. No-one would take the counter position today. The equivalent debate nowadays is between languages that separate statements and expressions and expression-oriented[0] languages. [0]: https://en.wikipedia.org/wiki/Expression-oriented_programming_language https://en.wikipedia.org/wiki/Expression-oriented_programmin...
- TeMPOraL 5y agoIs that really a debate? Gosh, I'd love to see the "separatist" arguments, because ever since I've discovered Lisp, I've automatically assumed that separating statements and expressions is one of those stupid historical baggage things, a stepping stone in early PL design that we can't just get rid of. I mean, how many libraries with weird APIs were created just because you can't write the following in most Algol-like languages: return if(sth) { foo = SomeProcessing(); Transform(foo); } else if(sthelse) { Transform(someDefault); } else { someErrorDefault; }; In many languages, people are resorting to "immediately invoked function expressions" to simulate this pattern (whether for returning or assigning). And those that can't, well, here goes another pointless little function to encapsulate it[0]. -- [0] - Which transitions into what is a real debate - "lots of small functions" vs. "fewer but larger functions". It's one of those holy wars that can't die, because both sides have good arguments. But it's a false choice - a limitation of the tools we're using to write programs. 'emilprogviz has a nice summary of that last point here: https://emilprogviz.com/ep05/ep05-transcript.html https://emilprogviz.com/ep05/ep05-transcript.html Linking to transcript, in the spirit of "text with screenshots is almost always better than a video" - (nice job providing it Emil!) - but the video itself is good too, as are others on that site.
- zetalyrae 5y agoOk it may not exist as a debate outside my own head :) To offer one argument: the problem with expression oriented languages is their generality, in that you can write "weird" expressions, e.g.: let x = [giant block of code with multiple nested lets, ifs, etc.] in f(x) I've definitely done this a number of times. Languages that separate statements and expressions force you to break things down further and prevent the code from going too far to the right. Also, for low level languages, the mapping between code and assembly is clearer in languages that separate statements and expressions (I need a more succinct term). EDIT: Also, by preventing statements from being used as expressions, you encourage breaking up long and complex statements into smaller functions.
- TeMPOraL 5y ago> in that you can write "weird" expressions Oh, I see what you mean. I discovered Lisp after working in C++ and Java, so I avoided this pitfall in my code, but if I had a dollar for every instance of: (let ((some-variable (progn (do stuff) (do other stuff) (let ((some-helper-var ...)) (some more code with some-helper-var) (more-of-the-same (progn ...))) ;; 50-100 lines later, just return one of the values some-variable) that I saw in Lisp codebases, particularly in Emacs, well... I could feed my family for a month or two from that money. There's plenty of abuse potential here (and for the love of god, if your language has 'let', it probably also has lambdas or 'flet', use that to create local functions...). But mitigating this, arguably, is a problem for style guides - the overall feature of "everything is an expression" is powerful. It has nice simplicity to it, and reduces boilerplate :). > Also, for low level languages, the mapping between code and assembly is clearer in languages that separate statements and expressions I'm guessing this is where the separation originally came from. Assembly is essentially statement-only. But at this point, I think all programming languages in use crossed the threshold where we're actually programming to an "abstract machine", and being expression-oriented seems to confer greater expressiveness. > (I need a more succinct term). "Separatist"? :). > EDIT: Also, by preventing statements from being used as expressions, you encourage breaking up long and complex statements into smaller functions. Ah yes. The real debate. I edited my comment to mention it before I saw your edit :).
- valyagolev 5y agovon Neumann was angry at a student for writing a program that would produce binary code rather than assembling it by hand https://twitter.com/sigfpe/status/1420961392585154569 https://twitter.com/sigfpe/status/1420961392585154569
- TeMPOraL 5y agoOh, the brief time in computing history when computer time was more expensive than human time.
- valyagolev 5y agohighlights the point that not valuing either will waste both
- microtherion 5y agoIf you take into account that the particular humans whose time was (not) valued here were graduate students, that time may not have been so brief after all.
- lou1306 5y agoI mean, it sounds weird now, but back then the assembler would indeed have eaten up precious CPU time. Imagine if, nowadays, a grad student took a node in a scientific cluster to run Dreamweaver in a Windows VM instead of writing HTML by hand. (Sorry, it's the closest analogy I could come up with)
- zetalyrae 5y agovon Neumann was probably the most intelligent person ever documented. He was probably frustrated that people couldn't see the machine code fully formed in their mind's eye :)
- runlaszlorun 5y agoAgreed! I also think that von Neumann (and some of his contemporaries as well) were likely the last to be able to understand the entire breadth of math, physics, and computer science at the time. These days we’re all far too specialized…
- AnimalMuppet 5y agoNo, I don't think that's the equivalent debate today. Structured programming vs "the old way" was about clarity of control flow. Structured programming was clearly superior once you had machines with enough muscle to handle the overhead. (And once you realized that you were trying to optimize for programmer time rather than for machine time.) I don't see expression-oriented as being similar to that at all. Expression-oriented may provide a boost to programmer efficiency, but it's not nearly on the order of structured programming vs. unstructured. It doesn't require changing peoples' mindset to realizing that programmer time is more valuable than machine time; they already know that. And, the parallel problem would be clarity of data flow, and I'm not sure that expression-oriented is a huge win in that area.
- smnplk 5y ago>> And, the parallel problem would be clarity of data flow, and I'm not sure that expression-oriented is a huge win in that area. In my opinion it is, because you can compose data transformations from smaller parts. Each part can do only one thing. For example in Clojure, you could do. (def transform (comp (do-thing-a) (do-thing-b) (do-thing-c)) (map transform my-collection) Or you could use a threading macro, with thread first or thread last semantics, which can also help you build clear pipelines. (-> basket-of-apples (select-ripe) (clean) (cut-to-pieces-of-size 4) (pack)) Not to mention transducers, which can further improve and clarify data flows.
- CraigJPerry 5y agoThis is referenced(1) as a core inspiration in the preface to “How to Design Programs” but i never researched it further because i’ve found the “design recipes” approach in htdp to be pretty solid in real life problems. 1. Analyse the problem and derive appropriate data representations, write out illustrative examples 2. Write a signature for the function - what does it consume and what does it produce. Spend time to get a concise definition of the computation it performs. 3. Create some illustrative examples of what the function does 4. Outline the function 5. Fill in the gaps to complete the definition of the function 6. Tidy up by converting some of those illustrative examples into tests There’s a further practice to this of iterative refinement - taking what you learn as you apply this process and use that info to refine what you did. This is a pretty solid way to go about things and it’s utterly trivial to bring a colleague up to speed with what you’re doing at any step when you need a hand. The biggest gap in practice of this method that i’ve found is a lack of concern for efficiency. It’d be fairly trivial to produce an n^3 solution following these steps when an n solution exists. I was always swayed by the “make it work, make it right, then make it fast” approach before. (1) … Actually i just went and opened the book, the actual reference is to Michael Jackson’s method for creating COBOL programs which is the progenitor of JSP.
- DEADB17 5y agoIn the "Fundamentals"[1] course they use a table format for the design recipe that makes the correspondence between data and functions more obvious, and perhaps the JSP inspiration more evident. [1] https://course.ccs.neu.edu/cs2500f17/design_recipe.html https://course.ccs.neu.edu/cs2500f17/design_recipe.html
- avinash 5y agoRead the book, which I obtained from the British Council library, when I was around 15. I have to say that the book made quite an impression on me at the time.
- keithnz 5y agothis is how I was first taught how to design software. I found it quite unnatural and didn't really use it. But it did help me start thinking about how to structure software.
- aidanr 5y agoI've just got "Structured Program Design Using JSP" off the bookshelf. Haven't looked at it in about 30 years! I was once sent on a work course to learn how to write COBOL using Jackson Structured Programming. I _loathed_ it. I remember thinking that a) it tried reduce the programmers role to little more than that of an automoton b) it was completely at odds with my views (30 years ago and still today) that good software development is a blend of the technical and creative/artistic. Happily very little of my working life involved actually using JSP (well Java Server Pages excluded).
- Zenst 5y agoBiggest erk and put-off many in COBOL had with JSP was exception handling and with that - without using GOTO (which was banned for JSP hardcore mentalities) you would end up setting flags and having checks - adding a lot of processing into the code-base at a time that was still before the IBM PC was to come about. Even then, CPU's for large mainframes et all, and the cost of CPU cycles and storage, sure did have a far larger value than in later years.
- danielnicholas 5y agoJSP used the "quit" statement to handle errors and backtracking; it was a primitive form of exception before exceptions were common. There's a lengthy defense of this in the JSP book (on p.282) arguing that eliminating GOTOs dogmatically is a mistake.
- zdkl 5y agoDisclaimer: I have done exactly 0 research on JSP before today and come from python/lisp land. Being in the middle of developping an OpenAPI application with python's Pydantic (an extension of type annotations), I can't help but feel python is this close to being a combination of JSP and data model definitions. To go one step further if you write your modules with Hy (a lisp that interops & ~transpiles to python), you get a pretty darn elegant codebase that is a rather direct mapping of your domain problem to expressions which look a lot like these JSP examples. Maybe I'm only just discovering for myself the "power of typed languages" (feel free to rib on duck typed devs here) but it feels like a huge progress in terms of productivity, bug count and readability. I love modern python.
- ChrisMarshallNY 5y agoHeh. I remember when the concept of subroutines was considered dangerously subversive. Structured Programming was thought of as revolutionary. Most folks were either doing COBOL or Assembly, at the time. C was just beginning to feel its oats (It was still thought of as a mostly academic language, but it spawned a few languages that were considered "workhorse" languages, like PL/1). I did start using Pascal, in the 1980s, because that was Apple's native language. It was a very strange language, coming from Assembly, FORTRAN, BASIC, and PL/1.
- cross 5y agoPL/1 definitely predates C.
- ChrisMarshallNY 5y agoAh. That makes sense. I always assumed it was one of many derivative languages. I wrote a tool or two, in PL/1.
- mech422 5y agoI have really fond memories of working on Stratus VOS and PL/1. Those machines were FUN :-D
- aaronrobinson 5y agoI was taught this when working at British Gas in the mid 80s. I remember this being followed by Delta 3GL which allowed you to allocate code to the pre and post hooks etc of each node. Your function ‘places’ were there and you just assigned code. It was a very methodical way of working and IMO left less room for error.
- Zenst 5y agoDid you also have to endure the era of `4GL` code generators that would produce COBOL code and marketed shortly as would make COBOL coders redundant? I worked at Eastern Electricity Board in the early 80's - No JSP there, but did work upon a new project that was object focused - using COBOL - no data dictionary overkill project, but saw what would normally be one program broken down into a main body that would link in lots of functions - which in themselves would be small contained COBOL programs. So one data input screen would see a program for each field type, instead of one large program and the main code would in effect be a skeleton that would link in the screen template and needed programs to handle those input/output data fields. Certainly the way forward in many ways, though COBOL perhaps not the most learning towards that. I liked JSP, but then that was how I was taught COBOL in education. Never really got to use it in anger due to legacy standards and other factors which alas made sense unless your doing greenfeild at the time.
- dkarl 5y ago> In Chapter 3 of Principles of Program Design[1] Jackson presents two versions of a program, one designed using JSP, the other using the traditional single-loop structure. I think I've come back around to seeing some merit in the "traditional" version. All the state is declared before the main loop. You could stop the program after any iteration of the single loop, save the explicitly declared state, and restart where you left off. The logic inside the loop can be applied to any record and state. In the double-loop version, your place in the control flow is part of the state. If you stopped, you wouldn't know where to start up again. There's also a state variable (firstLineOfGroup) declared inside the loop. I know why I prefer the "traditional" version: it can easily be refactored to be functional, and making the state explicit means it doesn't have to be refactored if I want to store the state externally or switch from a batch architecture to a streaming architecture. The JSP version is inherently imperative and needs to be refactored before it can be used in a different architecture. Funny how ideas like that alter your taste.
- nyanpasu64 5y agoI think coroutines, generators, and async allow the compiler to transform the two-loop version into a state machine that can be suspended at a readLine() or println() call.
- dkarl 5y agoA compiler that could take the JSP version and transform it into a streaming job with managed state would be pretty cool. Otherwise, a programmer has to construct the streaming architecture around the code, whether they integrate it into an existing framework like Flink or write all the state handling and management themselves. In that case the processing code has to be structured so that the state is explicitly passed in and out for each record.
- deleted 5y ago[deleted]
- danielnicholas 5y ago
- Zenst 5y agoI started out from a BTEC (changed to BECTEC and 2 years instead of just 1 year shortly after I did mine) and was taught COBOL. First Job doing COBOL and I wrote a program, really upset the analyst - as with JSP exception handling done way differently than just using GOTO (a COBOL verb I'd never used or was even aware of as was hard core JSP). Was explained the whole aspect of efficiency and with many aspects of code - what looks neat and nice today over time will get modified and how it was easier to modify something with GOTO's over some elegant JSP layout. That and efficiency of the code - performance. So I learned the usual lesson many do when you go from Educational ideals into Working reality. Real World business don't run on cutting edge changing soon as that changes, legacy/stability and historical aspects do play out. So whilst you may know a better way, there are many factors that make that impracticable. Sure if rewriting your code-base and hardware to the cutting edge of the time was viable then people would do it, but testing and verification of code - when done properly takes longer than the time to build the latest cutting edge system. Let alone the whole cost factor. I imagine many have comparable stories upon their move from the realms of Education into Work. Do share as be nice to read what brain-walls today's first workers encounter.
- dustingetz 5y agoi believe this is equivalent to a modern functional effect system, which compiles an AST (typically a hosted monadic sub language, or equivalently a s-expression with control flow) into a DAG intermediate language. The DAG is abstract and is then further interpreted or compiled into an execution target, which evaluate the DAG with late bound runtime properties like asynchrony, exceptions, side effects, garbage collection, structured concurrency. the key idea is that the DAG is abstract and has no notion of the runtime behaviors like asynchrony; structured programming is about capturing the computation’s essential structure as a DAG and then using that structure to reflect the target runtime behavior. E.g. interpreting edges of the DAG as callbacks. Structure is also about constraints (what you can’t or shouldn’t do) and for example a DAG can’t express goto. But a DAG can express stack frames and lexical closures (by nesting).
- easytiger 5y agoThis was actually taught as part of the a level in the school i went to.
- vjust 5y agoI tried to follow Jackson’s book on Problem Frames, did not complete the book, though I’d consider trying to read it again. Its a non-formal or semi-formal methodology that emphasizes understanding the structure of problems and domains before solution design. Its a technique of architecture and systems engineering.
- danielnicholas 5y agoIf you want an intro to JSP, you might find helpful an annotated version [0] of Hoare's explanation of JSP that I edited for a Michael Jackson festschrift in 2009. For those who don't know JSP, I’d point to these ideas as worth knowing: - There’s a class of programming problem that involves traversing context-free structures can be solved very systematically. HTDP addresses this class, but bases code structure only on input structure; JSP synthesized input and output. - There are some archetypal problems that, however you code, can't be pushed under the rug—most notably structure clashes—and just recognizing them helps. - Coroutines (or code transformation) let you structure code more cleanly when you need to read or write more than one structure. It’s why real iterators (with yield), which offer a limited form of this, are (in my view) better than Java-style iterators with a next method. - The idea of viewing a system as a collection of asynchronous processes (Ch. 11 in the JSP book, which later became JSD) with a long-running process for each real-world entity. This was a notable contrast to OOP, and led to a strategy (seeing a resurgence with event storming for DDD) that began with events rather than objects. [0] https://groups.csail.mit.edu/sdg/pubs/2009/hoare-jsp-3-29-09.pdf https://groups.csail.mit.edu/sdg/pubs/2009/hoare-jsp-3-29-09...
- ob-nix 5y ago... this brings back memories! In the late eighties I, as a teenager, found a Jackson Struct. Pr. book at the town library. I remember I was amazed at the text and wondered why I hadn't heard about the method before. If I remember correctly did the book clearly point out backtracking as a standard method, while mentioning that most languages lacked that, so it had to be implemented manually.
- donatj 5y agoThere's an old Rob Pike talk where he asks the audience: "So how many of you are familiar with the work of Michael Jackson" Most of the crowd raises their hand to which he replies "Really? Quite a few! Well as you know, Michael Jackson developed Jackson Structural Programming". He was seemingly unaware of the popstar of the same name. - https://www.youtube.com/watch?v=HxaD_trXwRE&t=44s https://www.youtube.com/watch?v=HxaD_trXwRE&t=44s
- butterisgood 5y agoAlso the beer hunter. http://www.beerhunter.com/ http://www.beerhunter.com/
- azinman2 5y agoMichael Jordan is the name of a famous AI/ML researcher. What I love is they’re both tops of their careers.
- elwell 5y agoI fairly certain he was telling a joke. Hence the "well as you know" lead in.
- LukeShu 5y agoIt's been a long time since I watched that talk, but I seem to remember that about 40 minutes in he has a moment where he remembers that there's another Michael Jackson and apologizes for the confusion.
- danielnicholas 5y agoFor those not familiar with the JSP style alluded to in the comments, and its contrast to the "traditional style," here's an example of a function that splits a string into words. The "traditional" version was shown by a famous computer scientist in a conference talk a few years ago; I translated it to JS to provide some anonymity :-). JSP's claim to greater clarity is based on the correspondence between the code blocks and the structure being processed: the body of the outer loop processes a group (of gap and word); the body of the inner loops process a gap and a word respectively. The traditional style, in contrast, is like a state machine, and can't be viewed structurally---you need to think about what's happening at each point. This makes it harder to modify the code (eg, by adding something that happens once per word, which is now in two places) and often leads to bugs. This same structural clarity is why, in my view, code that uses list functionals like map/reduce is usually more comprehensible than traditional imperative code. // JSP version of a split function split_jsp = function (s) { words = []; i = 0; while (i < s.length) { while (is_white (s[i])) i++; word = ""; while (is_alpha (s[i])) word += s[i++]; if (word.length > 0) words.push(word); } return words; } // "traditional" version of a split function split_traditional = function (s) { words = []; word = ""; for (i = 0; i < s.length; i++) { ch = s[i]; if (is_white (ch)) { if (word != "") words.push (word) word = ""; } else word += ch; } if (word != "") words.push (word); return words; } is_white = ch => (ch == ' ' || ch == '\t' || ch == '\n') is_alpha = ch => ch != undefined && (/[a-zA-Z]/).test(ch)