├── LICENSE ├── README.md ├── agenda-master.md ├── exercises.md ├── lola-club ├── agenda-g1s1-with-notes.md ├── agenda-g1s2-with-notes.md ├── agenda-g1s3-with-notes.md ├── agenda-g1s4-with-notes.md ├── agenda-g2s1-with-notes.md ├── agenda-g2s2-with-notes.md ├── agenda-g3s1-with-notes.md ├── agenda-s1.md ├── agenda-s2.md ├── agenda-s3.md ├── agenda-s4.md ├── agenda-s5.md ├── code-s1.pdf ├── code-s2.pdf ├── code-s2.txt ├── code-s3-scribbled.jpg ├── code-s3.pdf ├── code-s3.txt ├── code-s4.pdf ├── code-s4.txt ├── code-s5.pdf ├── code-s6.pdf ├── code-s7-notes.md ├── code-s7.pdf ├── code-s7.rkt ├── code-s8-notes.md ├── code-s8.lua ├── code-s8.pdf └── code-s8.tic └── neontribe-club ├── retrospective ├── exercises.md ├── reflections.md └── wash-ups.md ├── session1 ├── agenda-s1.md ├── code-sample-ARCVService-Note.pdf ├── code-sample-gbptm-UI-LooListItem.pdf ├── completedExercises │ ├── colouring-example.jpg │ └── what-for-example.txt └── what-happened-s1.md ├── session11 ├── agenda.md ├── marked-up-code.jpg └── notes.md ├── session2 ├── agenda-s2.md ├── completedExercises │ ├── colouring-example.jpg │ └── what-for-example.txt ├── python_file_1.pdf ├── python_file_1_test.pdf ├── python_file_2-tests.py ├── python_file_2.pdf ├── short-code-option-1-code-format.pdf └── what-happened-s2.md ├── session3 ├── agenda-s3.md ├── completedExercises │ └── doctest-example-coloured.jpg ├── doctest-example.py └── doctest-example.py.stdout ├── session4 ├── Signal-iOS-PhoneNumberValidator.swift ├── agenda-s4.md ├── neontribe_code_reading_club_session_4_notes.pdf └── neontribe_code_reading_club_session_4_notes.txt ├── session5 ├── agenda-s5.md ├── completedExercises │ ├── code-club-5-marked.jpg │ └── code-club-5-marked2.jpg └── ssh_key.py ├── session6 ├── agenda-s6.md ├── completedExercises │ ├── code-sample-marked-1.jpg │ └── code-sample-marked-2.jpg ├── example_code.html.haml └── washup ├── session7 ├── Example.cs └── agenda-s7.md ├── session8 ├── Example.rs ├── Notes.md ├── agenda-s8.md ├── example_code.pdf └── example_code.png └── sessionX ├── agenda-s10.md ├── agenda_s10.pdf ├── code_sample.pdf └── example.rb /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Neontribe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code reading club 2 | 3 | This is an experiment inspired by research and teaching excercises designed by [Felienne Hermans](https://www.felienne.com). At its core is the idea that the paradigm we use to teach programming is flawed. One of the most obvious ommissions is the ability to read code, both phoneticlly and analytically. We aren't suitably equiping ourselves with these building blocks. 4 | 5 | ## The Plan 6 | We run the club initially for 6-8 weeks. Hopefully we find it so useful that we don't want to stop. We meet for 1 hour every other week. Sometimes there is optional prep in the form of reading, that participants can choose to do as homework outside that time. 7 | 8 | ## The Collaboration 9 | Neontribe run the club and feed back to Felienne on a regular basis about what works and what doesn't. She comes up with potential exercises. We come up with potential exercises. We experiment and try to make the sessions useful and enlightening. 10 | 11 | ## The Expectation 12 | Participants should have some professional coding experience. Apart from that, the sessions should work for a diverse group (in terms of cognitive, formal training, experience, skills, style etc). The sessions use a variety of languages and styles of code. The key benefit should be increased ability to understand code when reading and a more sympathetic style of writing code to be read by others. 13 | 14 | ## The Stuff 15 | The directories in this repo contain the resources and wash-up notes from each session. 16 | -------------------------------------------------------------------------------- /agenda-master.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (5 mins) 4 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 5 | - Note a time the past 2 weeks when you used information learned about code in your work 6 | 7 | ## Exercises 8 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 9 | 10 | You will need: 11 | - two printed copies of the code for today's club 12 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 13 | - coloured pens, crayons or pencils 14 | 15 | ### Interaction with code (10 mins) 16 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 17 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 18 | 1. Colour3 the classes - circle and draw links between classes and their instances 19 | 1. Draw the indentaiton patterns - There are a few ways to do this. Fill over with black sharpie. Trace on graph paper. Trace on acetate. etc? 20 | 21 | #### Discuss the results (10 mins) 22 | 1. What patterns are visible from the colors and indentations only? 23 | 1. What parts of the code warrant more attention based on the colors and indentation? 24 | 25 | ### Content 26 | 27 | #### Identify (10 mins) 28 | 1. Define what it means to be important and independently identify the 5 lines you consider most important 29 | 1. Discuss in the group: 30 | - lines covered by many people? 31 | - lines named but not by a lot of people 32 | - Agree less than 10 of the most important lines 33 | 34 | #### Discuss (10 mins) 35 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 36 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 37 | 38 | #### Summarize in less than 10 sentences (10 mins) 39 | 1. Independently write down the essence of the code in a few sentences 40 | 1. Discuss in the group 41 | - topics covered by many vs few 42 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 43 | 1. Create a summary together 44 | 1. Compare the summary with the available documentation (inside and outside the code) 45 | - identify differences and similarities between the groups findings and the existing 46 | 47 | 48 | ## Wash up (5 mins) 49 | - What worked well 50 | - What worked badly 51 | 52 | ## Follow up (2 weeks of elapsed time) 53 | - Identify code for next session, keaping in mind Wash up and Reflection information 54 | 55 | 56 | -------------------------------------------------------------------------------- /exercises.md: -------------------------------------------------------------------------------- 1 | This page contains a set of exercises which can be used in Code Reading Clubs. Of course, your club does not need to use all exercises, they are meant as a starting point. If you are trying out variants, do let us know! 2 | For now we have divided them into basic and advanced. Advanced exercises can be used in clube that have been running for a while, or when doing a second seccion on the same code snippet. 3 | 4 | ## Basic Exercises 5 | 6 | You will need: 7 | 8 | - two printed copies of the code for today's club 9 | - coloured paper and scissors 10 | - acetate and something to write on it with 11 | - coloured pens, crayons or pencils 12 | - or: a tablet and tablet pen with a PDF of the code 13 | 14 | ### First glance 15 | 16 | The goal of this exercise is to practice to get a first impression of code and to act upon that. 17 | 18 | #### Look at the code (1 min) 19 | 20 | Look at the code at a glance, really not more than 1 minute. Then try to answer these questions: 21 | 22 | * What is the first thing that catches your eye? Why is that? 23 | 24 | * What is the *second* think that you see? Why? 25 | 26 | * Are these two things (variables, classes, prorgramming concepts) related? 27 | 28 | 29 | #### Discuss the results (10 mins) 30 | 31 | Discuss the results as a group. What lines of facts or concepts were chosen by everyone versus by only a few people? 32 | 33 | Reflect also on what kind of knowledge did you use in this exercise? Knowledge of the domain, of the progamming language? Of a framework? What knowledge do you think might be needed to better understand this code? 34 | 35 | ### Code structure 36 | 37 | #### Examine structure (10 mins) 38 | The goal of this exercise is to be a concrete thing to *do* when looking at new code for the first time. New code can be scary, doing something will help! 39 | 40 | Color variables 41 | * Go through the code and circle all variables in red 42 | * Then draw a link between variables and their uses 43 | 44 | Color method/function calls 45 | * Go through the code and circle all methods in blue 46 | * Then draw a link between methods and their invocations 47 | 48 | Instantiation 49 | * Go through the code and circle all instances of classes in green 50 | * Then draw a link between classes and their instances 51 | 52 | #### Discuss the results (10 mins) 53 | 1. What patterns are visible from the colors and links only? 54 | 1. What parts of the code warrant more attention based on the colors? 55 | 56 | ### Content 57 | 58 | #### All variable/class/method names (5 mins) 59 | 60 | Go through the code mechanically and create a list of all identifier names in the snippet. Of you have done the "examine structure" exercise before, this should be relatively quick and easy. 61 | 62 | #### Discussion (10 mins) 63 | 64 | Discuss in the group: 65 | 66 | * What can we learn from these names? 67 | * Which names are related to each other, from the names only? 68 | * Are there names that are ambiguous when looked at without context? 69 | 70 | #### A random line (5 mins) 71 | 72 | Select a random line from the code in whatever way you like. Examine this line individually. What is the main idea of this line? What lines does it relate to and why? 73 | 74 | #### Discussion (10 mins) 75 | 76 | Discuss in the group: 77 | 78 | * What is the 'scope' of the random line? What part of the code was seen as related? 79 | * How does the line fit into the rest of the code base? 80 | 81 | #### Identify most important lines (10 mins) 82 | Define what it means to be important as a group, and then independently identify the 5 lines you consider most important. 83 | 84 | #### Discussion (10 mins) 85 | Discuss in the group: 86 | 87 | - lines covered by many people? 88 | - lines named but not by a lot of people 89 | - Agree less than 10 of the most important lines 90 | 91 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 92 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 93 | 94 | #### Summarize in less than 10 sentences individually (10 mins) 95 | 1. Independently write down the essence of the code in a few sentences 96 | 97 | #### Discussion (10 mins) 98 | - topics covered by many vs few 99 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 100 | 101 | #### Summarize in less than 10 sentences (10 mins) 102 | 1. Create a summary together 103 | 1. Compare the summary with the available documentation (inside and outside the code) 104 | - identify differences and similarities between the groups findings and the existing 105 | 106 | ## Advanced Exercises 107 | 108 | These exercises are more advanced, in the sense that you might need a bit more understanding of the code for these to make sense. This might be because the group is familiar with the code before the session, or because you are doing a second club on the same code snippet. 109 | 110 | ### Code structure 111 | 112 | #### Examine structure (5 mins) 113 | 114 | Use one of the basic exercises to examine the structure of the code (such as circle variables and link them), or reuse the notes from the previous club. Individuallt study the patterns and think about what they tell you. What direction does the code 'flow' in? What parts stand out for lack of, or access of links? 115 | 116 | #### Discussion (10 mins) 117 | 118 | - Parts of the code covered by many vs few 119 | - Strategies used to decide 120 | 121 | ### Content 122 | 123 | #### Central thematic concepts (5 mins) 124 | 125 | Each participant gets 5 minutes to individually name the 5 most central concepts of the code. These could be names, themes, classes, or information found in comments. 126 | 127 | #### Discussion (10 mins) 128 | 129 | - Topics covered by many vs few 130 | - Strategies used to decide (e.g. method names, documentation, variable names, prior knowledge of system) 131 | 132 | #### Central programming concepts (5 mins) 133 | 134 | Each participant gets 5 minutes to individually name the 5 most central computer science concepts of the code. These could be algorithms, data structures, assumptions or techniques. 135 | 136 | #### Discussion (10 mins) 137 | 138 | - Topics covered by many vs few 139 | - Strategies used to decide (e.g. method names, documentation, variable names, prior knowledge of system) 140 | 141 | ### The 'why' of the code 142 | 143 | Reexamine the code snippet and list decisions and intentions of the creator(s) of the code. For example a decision to use a certain design pattern ir use a certain library or API? 144 | 145 | * What decisions were made in the creation of this code? 146 | * What assumptions do these decisions rely on? 147 | 148 | #### Discussion (10 mins) 149 | 150 | Gather all decisions people made individually and discuss: 151 | 152 | - Pros of these decisions 153 | - Possible cons of these decisions 154 | - Alternative solutions 155 | -------------------------------------------------------------------------------- /lola-club/agenda-g1s1-with-notes.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Club goals and expectations (14:05) 4 | - Intro code reading club concept 5 | - Intro people in the group including experience & types of programming 6 | - JS, python, done before, extent to which other people read code in the way that I do, from humanities background, words rather than structures 7 | - JS, php, bash, reading code is one of most importnt skills you can have as a programmer, most of our days spent writing and reading. 8 | - JS 4 years, no cs background, read similar on Dan Abrimov, reviewing and debugging 9 | - No tech education, humanities, not reading code as other people, dev ops not reading full time or as main activity but would like to, least experienced in group, reading documention, tutorial, not being able to tye everything together, and flow, being able to wrap my mind around it all and how the components fit together. Bash, python 10 | - CS bg. wroked in IT mich of adult life. bash, python, perl, bit JS. Reading more code than I write these days, not sure if I like that not. Better understanding of code I get exposed to. Read code blind sounded good to me. 11 | - Set sessions. Frequency and length. 12 | - Discuss with Rupert not sure if 1 per week will be better to get it moving more quickly 13 | - Discuss goals and expectations of group members 14 | - Done in intros 15 | 16 | ### Interaction with code (10 mins) (14:20) 17 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 18 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 19 | 1. Colour3 the classes - circle and draw links between classes and their instances 20 | 21 | #### Discuss the results (10 mins) (14:30) 22 | 1. What patterns are visible from the colors and indentations only? 23 | 1. What parts of the code warrant more attention based on the colors and indentation? 24 | 25 | - Know nothing abour redux react, modern, funky js. Curious about the useDispath - can't figure out what it's doing. 26 | - Interested in import (5-10) reliying on prefix to determine what sort of thing it was 27 | - diff between var and function in react / js. doing word names vs. 28 | - Looks similar to code I see every day 29 | - Asking what sort of tool for static typing were they using there are types written down all over the place. 30 | - consentrated on variables in the inside of the component itself 31 | - Took me a while, but interested in how the imports were effecting 32 | - What is this thing returning? And then work backwards 33 | - colouring starting from line 1 high density at the top. Not sure if that means it's more important or just where I started 34 | 35 | ### Content 36 | 37 | #### Identify (10 mins) (14:40) 38 | 1. As a group breifly define what it means to be important and what constitues a line 39 | 1. Independently identify the 5 lines you consider most important 40 | 41 | #### Discuss (10 mins) 42 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 43 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 44 | Discuss in the group: 45 | - lines covered by many people? 46 | - lines named but not by a lot of people 47 | - Agree less than 10 of the most important lines 48 | 49 | - Votes: 50 | - ONE: 5,7,8,9,10,11,12,14,27,31,33,52,67 51 | - TWO: 6,35,35,50,68,75 52 | - THREE: 19,24 53 | - FOUR: 47 54 | - Group agreed 10 lines: 6,19,24,27,33,34,35,47,50,75 55 | - In the initial "vote" one person admitted they could not choose only 5 an had ended up with 10 (all of the imports (5-12) plus the const declaration for component (14) and the export declaration (75)) which led to great discussion 56 | - Interesting note that when we ran this with another club 47 also got the most votes. 57 | - Which lines lead you to understanding more? 58 | - Conversation about important for experienced react/redux dev vs others "It's readable only because I know this pattern of use" vs. "I sense there is some magic" 59 | - Highlight at the end when we realised there was an early return which all but one had ignored. 60 | 61 | 62 | ## Wash up (5 mins) 63 | - What worked well 64 | - I love importance of lines. Natural inclinations of people - different for everyone 65 | - I've leart an awful lot by looking at code I've never seen before for the 1st time and mostly understanding (beginner) 66 | - First time I've scribbled on code since 20 years ago at uni. Enjoyable. 67 | - Discussion of importance was interesting 68 | - What worked badly 69 | - Forgot to mention the reflection reminder 70 | - Code snippet for next session? We forgot to talk about in Goals. 71 | - Yes please different languages / frameworks 72 | - Neutral comment 73 | - Is there value in recording. Yes, for an example / guide to facilitation (a one off). No, nit generally, agreed the value is in the participation, rather than observation 74 | 75 | ## Reminder to note for reflection next session (next time!) 76 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 77 | -------------------------------------------------------------------------------- /lola-club/agenda-g1s2-with-notes.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflections 4 | - Mentioned to my partner (also a developer) & she thinks it's a great idea. 5 | - I have to read and analyse 2 unfamiliar codebases in Java (not a language I use). I would have been apprehensive about this, but now I'm looking forward to it instead because of experience in code reading club. It'll be like a private code reading session. 6 | 7 | ### Interaction with code (10 mins) 14:08 8 | #### Discuss the results (10 mins) 14:15 9 | - I focused on finding things the things 10 | - Noticed varibles used but not declared 11 | - I had to re-map my idesa of what constitues and variable and a function 12 | - I noted external programs (like `node`) and bash commands (like `test`) as functions 13 | - Things seem to exist simply by referring to them. No imports. 14 | 15 | 16 | 17 | ### Content 18 | 19 | #### Identify (10 mins) 14:25 20 | One vote: 5,7,11,15,30,33,70,73 21 | Two votes: 18,53,82,84 22 | Three votes: 10,63,81 23 | 24 | #### Discuss (10 mins) 14:35 25 | Nine lines agreed: 10,18,34,53,63,73,81,82,84 26 | 27 | Agreed - purpose was to run `VS Code` application with electron. The branching was necessary for compatibility and configs for iOS, linux and Linux in Windows. As a group, we belatedly noticed early return (line 35) because it was pointed out by 1 group memeber. 28 | 29 | 30 | ## Wash up (5 mins) 31 | - Adds excitement to read something in a language I'm not familiar with 32 | - There were no philosophical conversations around what constitutes important, maybe due to language or nature of the code in execution 33 | - Looking at code different languages makes me question my mental model of what code really is and how it interacts with the machine (what really is the difference between a command and a function). No matter how we imagine it, it boils down to instructions for the hardware. 34 | -------------------------------------------------------------------------------- /lola-club/agenda-g1s3-with-notes.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda (14:05) 2 | Code source: https://github.com/moment/moment/blob/develop/src/lib/create/from-anything.js 3 | 4 | ## Reminder to note for reflection next session (14:10) 5 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 6 | 7 | - Practice! New project read completely new code bases never seen before. Directly applicable. 8 | - Google alternate sulutions for client - I found myself underlining 9 | - Spent last week unfamiliar codebases jvm. groovy grails java. Also project is in french - an extra layer of amusement. Reflection that acrynyms CMS is not a CMS in french. 10 | - You tube video of someone doing work to be able to code without typing due to RSI - voice transcription for writing software. There is crossover here. 11 | 12 | ### Interaction with code (10 mins) (14:20) 13 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 14 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 15 | 1. Colour3 the classes - circle and draw links between classes and their instances 16 | 17 | - First time arrows going up. 18 | - Adds to the clutter if I arrow from imports 19 | - Marking 89 as constructor 20 | - What is a class? 21 | - Started marking returns as well as variables etc in the colouring stage. Moticated by conversaion last week about early returns. Could this be another 'pattern' we scan look for in this section? 22 | 23 | #### Discuss the results (10 mins) (14:30) 24 | 1. What patterns are visible from the colors and connections only? 25 | 1. What parts of the code warrant more attention based on the colors and connections 26 | 27 | 28 | ### Content 29 | 30 | #### Identify (10 mins) (14:40) 31 | 1. If necessary, define / remind in group a meaning of importance 32 | 1. Independently identify the 5 lines you consider most important 33 | 1. Note down which line numbers people selected individually 34 | 35 | This time there was virtually no consensus but as a group we agreed 22,47,88 as being important. 36 | - We talked a lot about why that might be including: 37 | - Eveolved oever a long time 38 | - Backward compatibility 39 | - Not really doing one thing (exports 2 completely different types of function) 40 | - Returns vs mutations 41 | - 42 | 43 | #### Discuss (10 mins) (14:50) 44 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 45 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 46 | 1. Discuss in the group: 47 | - lines covered by many people? 48 | - lines named but not by a lot of people 49 | - Agree less than 10 of the most important lines 50 | 51 | #### Summarize in less than 10 sentences (10 mins) (15:00) 52 | 1. Independently write down the essence of the code in a few sentences 53 | 1. Discuss in the group 54 | - topics covered by many vs few 55 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 56 | 57 | WE DID NOT GET THIS FAR - but getting closer. 58 | 1. Create a summary together 59 | 1. Compare the summary with the available documentation (inside and outside the code) 60 | - identify differences and similarities between the groups findings and the existing 61 | 62 | ## Wash up (5 mins) 63 | - What worked well 64 | - Excitement: At the end of the session one member of the group grabbed a plastic box full of pens and held it up to the camera "This is my box of colours!" 65 | 66 | - What we want to do better next time 67 | - Try with a Miro board 68 | - discuss our stragtegies as well as the summarise the code and the important bits 69 | - try some Elm 70 | -------------------------------------------------------------------------------- /lola-club/agenda-g1s4-with-notes.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | https://github.com/carwow/elm-slider/tree/master/examples 3 | 4 | 5 | ## Reflection (14:02) 6 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 7 | - 8 | - Continuing to work on project to make changes in code. So this is extremely appliable. The logic in determining user lang preference is not terrible obvious - and there were no test cases. It was not clear which input preferences would result in which files being read from the server. So I did actually take a pdf of main controller & highlighted with a cup of tea. I could have just tried loads of different inputs and checked what happened, but instead, I made the effot to not just fiddle and look at output. Keen to apply this 9 | - I've only been writing code last week - so I didn't get the opportunity. 10 | 11 | ### Code structure 12 | 13 | #### Examine structure (14:08) 14 | The goal of this exercise is to be a concrete thing to *do* when looking at new code for the first time. New code can be scary, doing something will help! 15 | 16 | Color variables 17 | * Go through the code and circle all variables in red 18 | * Then draw a link between variables and their uses 19 | 20 | Color method/function calls 21 | * Go through the code and circle all methods in blue 22 | * Then draw a link between methods and their invocations 23 | 24 | Instantiation 25 | * Go through the code and circle all instances of classes in green 26 | * Then draw a link between classes and their instances 27 | 28 | #### Discuss the results (14:18 mins) 29 | 1. What patterns are visible from the colors and links only? 30 | 1. What parts of the code warrant more attention based on the colors? 31 | 1. What strategy did you use to identify the different types of element? 32 | 33 | - Confused. Not know what is a declaration etc. Drew nothing. 34 | - Model, View, Update (is the update like a controller?) 35 | - weird syntax - the part with in confused me 36 | - what is the return 37 | - Oh - that's a type declaration 38 | - Started trying to colour variables, types, functions but got stuck and tried a new strategy of figuring out what was imports so I could see what was defined in this file vs. defined elsewhere 39 | - Cmd seems to be a global 40 | 41 | ### Content 42 | 43 | #### Identify most important lines (14:31) 44 | Independently identify the 5 lines you consider most important. 45 | 46 | #### Discussion (14:41) 47 | Discuss in the group: 48 | 49 | - lines covered by many people? 50 | - lines named but not by a lot of people 51 | - What strategy did you use to identify importance? 52 | - Agree less than 10 of the most important lines 53 | 54 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 55 | 56 | 57 | | votes | lines | 58 | |---|---| 59 | | 1 | 11,26,31,36,72,73,74,83,104,107,114 | 60 | | 2 | 65,105 | 61 | | 4 | 12 | 62 | | 5 | 20 | 63 | 64 | 8 agreed lines - 12,20,31,36,65,73,83,105 basically the function declarations for init, update, view, the defiition of main (the export) and the definition of the Model record. 65 | 66 | 67 | 68 | #### Summarize in less than 10 sentences individually (15:01) 69 | 1. Independently write down the essence of the code in a few sentences 70 | 71 | #### Discussion (10 mins) 72 | - topics covered by many vs few 73 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 74 | 75 | #### Summarize in less than 10 sentences (10 mins) 76 | 1. Create a summary together 77 | 1. Compare the summary with the available documentation (inside and outside the code) 78 | - identify differences and similarities between the groups findings and the existing 79 | 80 | ## Wash up (5 mins) 81 | - What worked well 82 | - Doesn't make me anxious that I don't understand because it's an academic exercise.I'm not trying to debug it or work on it. 83 | - The more I stay with the code the more readable it seems. If you know the syntax, it looks much easier than any other language I've used. That's just an instinct 84 | - It looks really clean if you know what you are reading. Not too many semicolons and keywords and curly braces 85 | - It's nice looking at languages I don't use 86 | 87 | - What worked badly 88 | - That was the most confusing code I've read 89 | - I've looked at elm before because I heard it has nice error messages, but when I read a blog post I'm like whoa, no way that looks hard 90 | 91 | ## Next time 92 | - Prolog? https://meet.google.com/linkredirect?authuser=0&dest=https%3A%2F%2Fyarnpkg.com%2Ffeatures%2Fconstraints 93 | - Would have been better to explain syntax first? In real world, you'd probably look up the basics before reading if the language was totally unfamiliar 94 | -------------------------------------------------------------------------------- /lola-club/agenda-g2s1-with-notes.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Club goals and expectations 4 | 5 | Motivations 6 | * atttracted by fun, learning GQL 7 | * interested and curious recent tangles with legacy 8 | * curious problem solving 9 | * it all life, not engaged with code 10 | * had touble reading someone else's code 11 | * make the bridge to a humanities-style reading approach 12 | 13 | Wished-for Gains 14 | - encounter new languages 15 | - improve skills at reading code 16 | - engaging with software from a non-project persepctive 17 | 18 | 19 | ### Interaction with code (10 mins) 20 | 21 | 22 | * comforting to draw the connections 23 | * interesting to see the imports being used 24 | * the use of imports led me to an important line 25 | Some participants were drawn directly into a consideration of the code's functioning. 26 | Discussing the shapes in abstract was not easy. Perhaps harder because we lacked visual reference. 27 | 28 | ### Content 29 | 30 | #### Identify (10 mins) 31 | * importance is not crashing 32 | * importance is the core funtions 33 | 34 | #### Discuss (10 mins) 35 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 36 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 37 | 1. Discuss in the group: 38 | - lines covered by many people? 39 | - lines named but not by a lot of people 40 | - Agree less than 10 of the most important lines 41 | 42 | Discussion around outliers was especially productive 43 | 44 | #### Summarize in less than 10 sentences (10 mins) 45 | We didn't get this far... 46 | 47 | ## Wash up (5 mins) 48 | - What worked well 49 | - What worked badly 50 | 51 | * the code was blurry at the start later it was clear 52 | * taking time and identifying was different from my normal approach to open a new file 53 | * interesting to see how different perspectives on importance 54 | * seeing similar apporaches to problems we face 55 | 56 | - it might be nice to see the code in advance for some 57 | 58 | ## Reminder to note for reflection next session 59 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 60 | -------------------------------------------------------------------------------- /lola-club/agenda-g2s2-with-notes.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reminder to note for reflection next session 4 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 5 | 6 | * Some folk report it is making them reflect consciously when reading code 7 | * One had tried marking up, when reading a difficult piece. Not sure it helped 8 | * Others simply that they enjoyed the first session and were looking forward to another 9 | 10 | ### Interaction with code 11 | 12 | * in this case the locus is in the centre 13 | * indentation supports this 14 | * as does the upflow from the hoisted private functions 15 | 16 | ### Content 17 | 18 | #### Identify (10 mins) 19 | 20 | * We talked about trying to to this with blocks not loc, but it seemed to be cheating in the end 21 | 22 | #### Discuss (10 mins) 23 | 24 | 25 | #### Summarize in less than 10 sentences (10 mins) 26 | Interesting and lengthy discussion in which we discovered that we were still split about the core purpose of the code. We had become enmeshed in some of the edge cases, and had mostly ignored a main case. 27 | 28 | ## Wash up (5 mins) 29 | - What worked well 30 | - What worked badly 31 | 32 | 33 | 34 | This applies validation rules to phone numbers, ensuring they have a country code, and using stricter rules for Brazilian and US numbers than for the rest of the world. -------------------------------------------------------------------------------- /lola-club/agenda-g3s1-with-notes.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Club goals and expectations 4 | 5 | * need to read different languages - already has an idea for us to read some C# - general knowlege about programming 6 | * get comfortable reading someone else's code - understand faster - exposure to concepts - diminish fear 7 | * reading code makes you better - make one's mind more flexible 8 | * didn't learn many languiages in school - interested to find if I can understand code in an unfamiliar language - how can I apply my general knowlege - gain a view of other languages to explore possible change 9 | * curiosity - compare a book club with a code club - see pateterns and particularites 10 | * like a puzzle game - fun - understand other patterns 11 | 12 | ### Interaction with code 13 | 14 | * i didn't start from the top and missed stuff - I use phpstorm for this normally - it is harder on paper 15 | * it feels necessary to tread from top to bottom 16 | * declaration then use - inline definitions buck the trend 17 | * I tried to be the interpreter/compiler 18 | * I threaded the word patients through the code 19 | 20 | ### Content 21 | 22 | #### Identify (10 mins) 23 | 1. As a group breifly define what it means to be important and what constitues a line 24 | 1. Independently identify the 5 lines you consider most important 25 | 26 | * inverse importance - what can you take out 27 | * locus - many things pointing to it 28 | * correctness - will it break 29 | * function - relies on an understanding of the purpose of the code 30 | 31 | #### Discuss (10 mins) 32 | 33 | 34 | ## Wash up (5 mins) 35 | * even if excerscises don't "work" for everyone they all have value because they articulate different approaches 36 | 37 | 38 | -------------------------------------------------------------------------------- /lola-club/agenda-s1.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Club goals and expectations 4 | - Intro code reading club concept 5 | - Intro people in the group including experience & types of programming 6 | - Set sessions. Frequency and length. 7 | - Discuss goals and expectations of group members 8 | 9 | ### Interaction with code (10 mins) 10 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 11 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 12 | 1. Colour3 the classes - circle and draw links between classes and their instances 13 | 14 | #### Discuss the results (10 mins) 15 | 1. What patterns are visible from the colors and indentations only? 16 | 1. What parts of the code warrant more attention based on the colors and indentation? 17 | 18 | ### Content 19 | 20 | #### Identify (10 mins) 21 | 1. As a group breifly define what it means to be important and what constitues a line 22 | 1. Independently identify the 5 lines you consider most important 23 | 24 | #### Discuss (10 mins) 25 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 26 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 27 | 1. Discuss in the group: 28 | - lines covered by many people? 29 | - lines named but not by a lot of people 30 | - Agree less than 10 of the most important lines 31 | 32 | #### Summarize in less than 10 sentences (10 mins) 33 | 1. Independently write down the essence of the code in a few sentences 34 | 1. Discuss in the group 35 | - topics covered by many vs few 36 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 37 | 1. Create a summary together 38 | 1. Compare the summary with the available documentation (inside and outside the code) 39 | - identify differences and similarities between the groups findings and the existing 40 | 41 | ## Wash up (5 mins) 42 | - What worked well 43 | - What worked badly 44 | 45 | ## Reminder to note for reflection next session 46 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 47 | -------------------------------------------------------------------------------- /lola-club/agenda-s2.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reminder to note for reflection next session 4 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 5 | 6 | ### Interaction with code (10 mins) 7 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 8 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 9 | 1. Colour3 the classes - circle and draw links between classes and their instances 10 | 11 | #### Discuss the results (10 mins) 12 | 1. What patterns are visible from the colors and indentations only? 13 | 1. What parts of the code warrant more attention based on the colors and indentation? 14 | 15 | ### Content 16 | 17 | #### Identify (10 mins) 18 | 1. As a group breifly define what it means to be important and what constitues a line 19 | 1. Independently identify the 5 lines you consider most important 20 | 21 | #### Discuss (10 mins) 22 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 23 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 24 | 1. Discuss in the group: 25 | - lines covered by many people? 26 | - lines named but not by a lot of people 27 | - Agree less than 10 of the most important lines 28 | 29 | #### Summarize in less than 10 sentences (10 mins) 30 | 1. Independently write down the essence of the code in a few sentences 31 | 1. Discuss in the group 32 | - topics covered by many vs few 33 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 34 | 1. Create a summary together 35 | 1. Compare the summary with the available documentation (inside and outside the code) 36 | - identify differences and similarities between the groups findings and the existing 37 | 38 | ## Wash up (5 mins) 39 | - What worked well 40 | - What worked badly 41 | -------------------------------------------------------------------------------- /lola-club/agenda-s3.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (5 mins) 4 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 5 | 6 | ### Interaction with code (10 mins) 7 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 8 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 9 | 1. Colour3 the classes - circle and draw links between classes and their instances 10 | 11 | #### Discuss the results (10 mins) 12 | 1. What patterns are visible from the colors and connections? 13 | 1. What parts of the code warrant more attention based on the colors and connections? 14 | 15 | ### Content 16 | 17 | #### Identify (10 mins) 18 | 1. If necessary, define / remind in group a meaning of importance 19 | 1. Independently identify the 5 lines you consider most important 20 | 1. Note down which line numbers people selected individually 21 | 22 | #### Discuss (15 mins) 23 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 24 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 25 | 1. Discuss in the group: 26 | - lines covered by many people? 27 | - lines named but not by a lot of people 28 | - Agree less than 10 of the most important lines 29 | 30 | #### Summarize in less than 10 sentences (10 mins) 31 | 1. Independently write down the essence of the code in a few sentences 32 | 1. Discuss in the group 33 | - topics covered by many vs few 34 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 35 | 1. Create a summary together 36 | 1. Compare the summary with the available documentation (inside and outside the code) 37 | - identify differences and similarities between the groups findings and the existing 38 | 39 | ## Wash up (5 mins) 40 | - What worked well 41 | - What worked badly 42 | -------------------------------------------------------------------------------- /lola-club/agenda-s4.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (5 mins) 4 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 5 | 6 | ### Code structure 7 | 8 | #### Examine structure (10 mins) 9 | The goal of this exercise is to be a concrete thing to *do* when looking at new code for the first time. New code can be scary, doing something will help! 10 | 11 | Color variables 12 | * Go through the code and circle all variables in red 13 | * Then draw a link between variables and their uses 14 | 15 | Color method/function calls 16 | * Go through the code and circle all methods in blue 17 | * Then draw a link between methods and their invocations 18 | 19 | Instantiation 20 | * Go through the code and circle all instances of classes in green 21 | * Then draw a link between classes and their instances 22 | 23 | #### Discuss the results (10 mins) 24 | 1. What patterns are visible from the colors and links only? 25 | 1. What parts of the code warrant more attention based on the colors? 26 | 1. What strategy did you use to identify the different types of element? 27 | 28 | ### Content 29 | 30 | #### Identify most important lines (10 mins) 31 | Independently identify the 5 lines you consider most important. 32 | 33 | #### Discussion (10 mins) 34 | Discuss in the group: 35 | 36 | - lines covered by many people? 37 | - lines named but not by a lot of people 38 | - What strategy did you use to identify importance? 39 | - Agree less than 10 of the most important lines 40 | 41 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 42 | 43 | #### Summarize in less than 10 sentences individually (10 mins) 44 | 1. Independently write down the essence of the code in a few sentences 45 | 46 | #### Discussion (10 mins) 47 | - topics covered by many vs few 48 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 49 | 50 | #### Summarize in less than 10 sentences (10 mins) 51 | 1. Create a summary together 52 | 1. Compare the summary with the available documentation (inside and outside the code) 53 | - identify differences and similarities between the groups findings and the existing 54 | 55 | ## Wash up (5 mins) 56 | - What worked well 57 | - What worked badly 58 | -------------------------------------------------------------------------------- /lola-club/agenda-s5.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (5 mins) 4 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 5 | 6 | ### Code structure 7 | 8 | #### Examine structure (10 mins) 9 | The goal of this exercise is to be a concrete thing to *do* when looking at new code for the first time. New code can be scary, doing something will help! 10 | 11 | Color variables 12 | * Go through the code and circle all variables in red 13 | * Then draw a link between variables and their uses 14 | 15 | Color method/function calls 16 | * Go through the code and circle all methods in blue 17 | * Then draw a link between methods and their invocations 18 | 19 | Instantiation 20 | * Go through the code and circle all instances of classes in green 21 | * Then draw a link between classes and their instances 22 | 23 | #### Discuss the results (10 mins) 24 | 1. What patterns are visible from the colors and links only? 25 | 1. What parts of the code warrant more attention based on the colors? 26 | 1. What strategy did you use to identify the different types of element? 27 | 28 | ### Content 29 | 30 | #### Identify most important lines (10 mins) 31 | Independently identify the 5 lines you consider most important. 32 | 33 | #### Discussion (10 mins) 34 | Discuss in the group: 35 | 36 | - lines covered by many people? 37 | - lines named but not by a lot of people 38 | - What strategy did you use to identify importance? 39 | - Agree less than 10 of the most important lines 40 | 41 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 42 | 43 | #### Summarize in less than 10 sentences individually (10 mins) 44 | 1. Independently write down the essence of the code in a few sentences 45 | 46 | #### Discussion (10 mins) 47 | - topics covered by many vs few 48 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 49 | 50 | #### Summarize in less than 10 sentences (10 mins) 51 | 1. Create a summary together 52 | 1. Compare the summary with the available documentation (inside and outside the code) 53 | - identify differences and similarities between the groups findings and the existing 54 | 55 | ## Wash up (5 mins) 56 | - What worked well 57 | - What worked badly 58 | -------------------------------------------------------------------------------- /lola-club/code-s1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s1.pdf -------------------------------------------------------------------------------- /lola-club/code-s2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s2.pdf -------------------------------------------------------------------------------- /lola-club/code-s2.txt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if [[ "$OSTYPE" == "darwin"* ]]; then 6 | realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; } 7 | ROOT=$(dirname "$(dirname "$(realpath "$0")")") 8 | else 9 | ROOT=$(dirname "$(dirname "$(readlink -f $0)")") 10 | if grep -qi Microsoft /proc/version; then 11 | IN_WSL=true 12 | fi 13 | fi 14 | 15 | function code() { 16 | cd "$ROOT" 17 | 18 | if [[ "$OSTYPE" == "darwin"* ]]; then 19 | NAME=`node -p "require('./product.json').nameLong"` 20 | CODE="./.build/electron/$NAME.app/Contents/MacOS/Electron" 21 | else 22 | NAME=`node -p "require('./product.json').applicationName"` 23 | CODE=".build/electron/$NAME" 24 | fi 25 | 26 | # Node modules 27 | test -d node_modules || yarn 28 | 29 | # Get electron 30 | yarn electron 31 | 32 | # Manage built-in extensions 33 | if [[ "$1" == "--builtin" ]]; then 34 | exec "$CODE" build/builtin 35 | return 36 | fi 37 | 38 | # Sync built-in extensions 39 | node build/lib/builtInExtensions.js 40 | 41 | # Build 42 | test -d out || yarn compile 43 | 44 | # Configuration 45 | export NODE_ENV=development 46 | export VSCODE_DEV=1 47 | export VSCODE_CLI=1 48 | export ELECTRON_ENABLE_STACK_DUMPING=1 49 | export ELECTRON_ENABLE_LOGGING=1 50 | export VSCODE_LOGS= 51 | 52 | # Launch Code 53 | exec "$CODE" . --no-sandbox "$@" 54 | } 55 | 56 | function code-wsl() 57 | { 58 | HOST_IP=$(powershell.exe -Command "& {(Get-NetIPAddress | Where-Object {\$_.InterfaceAlias -like '*WSL*' -and \$_.AddressFamily -eq 'IPv4'}).IPAddress | Write-Host -NoNewline}") 59 | export DISPLAY="$HOST_IP:0" 60 | 61 | # in a wsl shell 62 | ELECTRON="$ROOT/.build/electron/Code - OSS.exe" 63 | if [ -f "$ELECTRON" ]; then 64 | local CWD=$(pwd) 65 | cd $ROOT 66 | export WSLENV=ELECTRON_RUN_AS_NODE/w:$WSLENV 67 | local WSL_EXT_ID="ms-vscode-remote.remote-wsl" 68 | local WSL_EXT_WLOC=$(ELECTRON_RUN_AS_NODE=1 "$ROOT/.build/electron/Code - OSS.exe" "out/cli.js" --locate-extension $WSL_EXT_ID) 69 | cd $CWD 70 | if [ -n "$WSL_EXT_WLOC" ]; then 71 | # replace \r\n with \n in WSL_EXT_WLOC 72 | local WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode-dev.sh 73 | $WSL_CODE "$ROOT" "$@" 74 | exit $? 75 | else 76 | echo "Remote WSL not installed, trying to run VSCode in WSL." 77 | fi 78 | fi 79 | } 80 | 81 | if ! [ -z ${IN_WSL+x} ]; then 82 | code-wsl "$@" 83 | fi 84 | code "$@" 85 | -------------------------------------------------------------------------------- /lola-club/code-s3-scribbled.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s3-scribbled.jpg -------------------------------------------------------------------------------- /lola-club/code-s3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s3.pdf -------------------------------------------------------------------------------- /lola-club/code-s3.txt: -------------------------------------------------------------------------------- 1 | import isArray from '../utils/is-array'; 2 | import isObject from '../utils/is-object'; 3 | import isObjectEmpty from '../utils/is-object-empty'; 4 | import isUndefined from '../utils/is-undefined'; 5 | import isNumber from '../utils/is-number'; 6 | import isDate from '../utils/is-date'; 7 | import map from '../utils/map'; 8 | import { createInvalid } from './valid'; 9 | import { Moment, isMoment } from '../moment/constructor'; 10 | import { getLocale } from '../locale/locales'; 11 | import { hooks } from '../utils/hooks'; 12 | import checkOverflow from './check-overflow'; 13 | import { isValid } from './valid'; 14 | 15 | import { configFromStringAndArray } from './from-string-and-array'; 16 | import { configFromStringAndFormat } from './from-string-and-format'; 17 | import { configFromString } from './from-string'; 18 | import { configFromArray } from './from-array'; 19 | import { configFromObject } from './from-object'; 20 | 21 | function createFromConfig(config) { 22 | var res = new Moment(checkOverflow(prepareConfig(config))); 23 | if (res._nextDay) { 24 | // Adding is smart enough around DST 25 | res.add(1, 'd'); 26 | res._nextDay = undefined; 27 | } 28 | 29 | return res; 30 | } 31 | 32 | export function prepareConfig(config) { 33 | var input = config._i, 34 | format = config._f; 35 | 36 | config._locale = config._locale || getLocale(config._l); 37 | 38 | if (input === null || (format === undefined && input === '')) { 39 | return createInvalid({ nullInput: true }); 40 | } 41 | 42 | if (typeof input === 'string') { 43 | config._i = input = config._locale.preparse(input); 44 | } 45 | 46 | if (isMoment(input)) { 47 | return new Moment(checkOverflow(input)); 48 | } else if (isDate(input)) { 49 | config._d = input; 50 | } else if (isArray(format)) { 51 | configFromStringAndArray(config); 52 | } else if (format) { 53 | configFromStringAndFormat(config); 54 | } else { 55 | configFromInput(config); 56 | } 57 | 58 | if (!isValid(config)) { 59 | config._d = null; 60 | } 61 | 62 | return config; 63 | } 64 | 65 | function configFromInput(config) { 66 | var input = config._i; 67 | if (isUndefined(input)) { 68 | config._d = new Date(hooks.now()); 69 | } else if (isDate(input)) { 70 | config._d = new Date(input.valueOf()); 71 | } else if (typeof input === 'string') { 72 | configFromString(config); 73 | } else if (isArray(input)) { 74 | config._a = map(input.slice(0), function (obj) { 75 | return parseInt(obj, 10); 76 | }); 77 | configFromArray(config); 78 | } else if (isObject(input)) { 79 | configFromObject(config); 80 | } else if (isNumber(input)) { 81 | // from milliseconds 82 | config._d = new Date(input); 83 | } else { 84 | hooks.createFromInputFallback(config); 85 | } 86 | } 87 | 88 | export function createLocalOrUTC(input, format, locale, strict, isUTC) { 89 | var c = {}; 90 | 91 | if (format === true || format === false) { 92 | strict = format; 93 | format = undefined; 94 | } 95 | 96 | if (locale === true || locale === false) { 97 | strict = locale; 98 | locale = undefined; 99 | } 100 | 101 | if ( 102 | (isObject(input) && isObjectEmpty(input)) || 103 | (isArray(input) && input.length === 0) 104 | ) { 105 | input = undefined; 106 | } 107 | // object construction must be done this way. 108 | // https://github.com/moment/moment/issues/1423 109 | c._isAMomentObject = true; 110 | c._useUTC = c._isUTC = isUTC; 111 | c._l = locale; 112 | c._i = input; 113 | c._f = format; 114 | c._strict = strict; 115 | 116 | return createFromConfig(c); 117 | } 118 | -------------------------------------------------------------------------------- /lola-club/code-s4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s4.pdf -------------------------------------------------------------------------------- /lola-club/code-s4.txt: -------------------------------------------------------------------------------- 1 | 1 module Main exposing (main) 2 | 2 3 | 3 import Browser 4 | 4 import DoubleSlider as DoubleSlider exposing (..) 5 | 5 import Html exposing (Html, button, div, text) 6 | 6 import Html.Events exposing (onClick) 7 | 7 import RangeSlider as RangeSlider exposing (..) 8 | 8 import SingleSlider exposing (..) 9 | 9 10 | 10 11 | 11 main : Program Flags Model Msg 12 | 12 main = 13 | 13 Browser.element { init = init, update = update, view = view, subscriptions = subscriptions } 14 | 14 15 | 15 16 | 16 17 | 17 -- MODEL 18 | 18 19 | 19 20 | 20 type alias Model = 21 | 21 { singleSlider : SingleSlider.SingleSlider Msg 22 | 22 , doubleSlider : DoubleSlider.DoubleSlider Msg 23 | 23 } 24 | 24 25 | 25 26 | 26 type alias Flags = 27 | 27 {} 28 | 28 29 | 29 30 | 30 init : Flags -> ( Model, Cmd Msg ) 31 | 31 init flags = 32 | 32 let 33 | 33 minFormatter = 34 | 34 \value -> String.fromFloat value 35 | 35 36 | 36 model = 37 | 37 { singleSlider = 38 | 38 SingleSlider.init 39 | 39 { min = 0 40 | 40 , max = 1000 41 | 41 , value = 500 42 | 42 , step = 50 43 | 43 , onChange = SingleSliderChange 44 | 44 } 45 | 45 |> SingleSlider.withMinFormatter minFormatter 46 | 46 , doubleSlider = 47 | 47 DoubleSlider.init 48 | 48 { min = 0 49 | 49 , max = 1000 50 | 50 , lowValue = 500 51 | 51 , highValue = 750 52 | 52 , step = 50 53 | 53 , onLowChange = DoubleSliderLowChange 54 | 54 , onHighChange = DoubleSliderHighChange 55 | 55 } 56 | 56 } 57 | 57 in 58 | 58 ( model, Cmd.none ) 59 | 59 60 | 60 61 | 61 62 | 62 -- UPDATE 63 | 63 64 | 64 65 | 65 type Msg 66 | 66 = NoOp 67 | 67 | DoubleSliderLowChange Float 68 | 68 | DoubleSliderHighChange Float 69 | 69 | SingleSliderChange Float 70 | 70 71 | 71 72 | 72 update : Msg -> Model -> ( Model, Cmd Msg ) 73 | 73 update msg model = 74 | 74 case msg of 75 | 75 NoOp -> 76 | 76 ( model, Cmd.none ) 77 | 77 78 | 78 DoubleSliderLowChange str -> 79 | 79 let 80 | 80 newSlider = 81 | 81 DoubleSlider.updateLowValue str model.doubleSlider 82 | 82 in 83 | 83 ( { model | doubleSlider = newSlider }, Cmd.none ) 84 | 84 85 | 85 DoubleSliderHighChange str -> 86 | 86 let 87 | 87 newSlider = 88 | 88 DoubleSlider.updateHighValue str model.doubleSlider 89 | 89 in 90 | 90 ( { model | doubleSlider = newSlider }, Cmd.none ) 91 | 91 92 | 92 SingleSliderChange str -> 93 | 93 let 94 | 94 newSlider = 95 | 95 SingleSlider.update str model.singleSlider 96 | 96 in 97 | 97 ( { model | singleSlider = newSlider }, Cmd.none ) 98 | 98 99 | 99 100 | 100 101 | 101 -- VIEW 102 | 102 103 | 103 104 | 104 view : Model -> Html Msg 105 | 105 view model = 106 | 106 div [] 107 | 107 [ div [] [ DoubleSlider.view model.doubleSlider ] 108 | 108 , div [] [ SingleSlider.view model.singleSlider ] 109 | 109 ] 110 | 110 111 | 111 112 | 112 subscriptions : Model -> Sub msg 113 | 113 subscriptions model = 114 | 114 Sub.none 115 | -------------------------------------------------------------------------------- /lola-club/code-s5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s5.pdf -------------------------------------------------------------------------------- /lola-club/code-s6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s6.pdf -------------------------------------------------------------------------------- /lola-club/code-s7-notes.md: -------------------------------------------------------------------------------- 1 | # Lola session 7 host notes 2 | 3 | Sample lightly adapted from [Racket's example "Memory" card game](https://github.com/racket/games/tree/master/memory). 4 | 5 | Trimmed down a bit for easier reading (mostly just removed the game timer). 6 | 7 | `code-s7.rkt` can be executed as-is in DrRacket and it will show the game GUI, but it assumes you have a full Racket install with the game assets in `share/games/...` etc. However, if you just want to run the pre-compiled version (with the timer) it is included in [the default Racket bundle](https://download.racket-lang.org) (run the "PLT Games" executable in the download and select "Memory"). 8 | 9 | 10 | ## Hints 11 | 12 | - The `#t` and `#f` values on lines 26, 34, 35 etc. are booleans 13 | - `(+ 1 HEIGHT)` is calling the `(+)` function and passing in 1 and HEIGHT 14 | - `(car)` is a standard function that returns the first element in a list (should really be named `(first)`) 15 | - `(cdr)` returns the remaining elements as a list (should really be named `(rest)`) 16 | - the reasons for these function names are quite literally lost in the mists of time 17 | - lists are recursively defined: they're either `null` or a pair of elements; the first element being the head of the list, the second being either `null` (if it's a single-element list) or a list of the remaining elements 18 | - `(cond)` is a convenience function used to chain **cond**itionals as a series of tests 19 | - square brackets `[]` are interchangeable with parens `()` 20 | - by _convention_ they're used for `(cond)` clauses (along with indentation) to make things a bit more readable 21 | - `(send t stack-cards deck)` 22 | - sending `deck` to the `stack-cards` function in the `t` object (ish) 23 | - The exclamation in `(set!)` [is significant](https://docs.racket-lang.org/guide/set_.html) 24 | 25 | -------------------------------------------------------------------------------- /lola-club/code-s7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s7.pdf -------------------------------------------------------------------------------- /lola-club/code-s7.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | (require games/cards racket/gui racket/class racket/unit) 3 | 4 | ;; Layout width and height: 5 | (define WIDTH 5) 6 | (define HEIGHT 4) 7 | (define MAX-MATCHES (/ (* WIDTH HEIGHT) 2)) 8 | 9 | ;; Randomize 10 | (random-seed (modulo (current-milliseconds) 10000)) 11 | 12 | ;; Set up the table 13 | (define t (make-table "Memory" (+ 2 WIDTH) (+ 1 HEIGHT))) 14 | (send t show #t) 15 | (send t set-double-click-action #f) 16 | 17 | ;; Get table width & height 18 | (define w (send t table-width)) 19 | (define h (send t table-height)) 20 | 21 | ;; Set up the cards 22 | (define deck 23 | (let ([cards (map (lambda (name value) 24 | (let ([bm (make-object 25 | bitmap% 26 | (build-path 27 | (collection-path "games" "memory" "images") 28 | (format "~a.png" name)))]) 29 | (make-card bm #f 0 value))) 30 | '("club" "heart" "spade" "diamond" 31 | "happy" "unhappy" "fish" "two-fish" "jack" "star") 32 | '(1 2 3 4 5 6 7 8 9 10))]) 33 | (append cards (map (lambda (c) (send c copy)) cards)))) 34 | (for-each (lambda (card) 35 | (send card user-can-move #f) 36 | (send card user-can-flip #t)) 37 | deck) 38 | 39 | ;; Card width & height 40 | (define cw (send (car deck) card-width)) 41 | (define ch (send (car deck) card-height)) 42 | 43 | (define dx (/ cw (+ 2 WIDTH))) 44 | (define dy (/ ch (+ 1 HEIGHT))) 45 | 46 | (define match-x (- w cw dx)) 47 | (define match-y dy) 48 | 49 | ;; Put the cards on the table 50 | (send t add-cards deck match-x match-y) 51 | 52 | ;; Setup 53 | (define (setup) 54 | (set! deck (shuffle-list deck 7)) 55 | (send t stack-cards deck) 56 | (send t move-cards deck 0 0 57 | (lambda (pos) 58 | (let ([i (modulo pos WIDTH)] 59 | [j (quotient pos WIDTH)]) 60 | (values (+ dx (* i (+ cw dx))) 61 | (+ dy (* j (+ ch dy)))))))) 62 | 63 | ;; Number of matches found so far: 64 | (define matches 0) 65 | 66 | ;; First card flipped, or #f if non flipped, yet 67 | (define card-1 #f) 68 | 69 | (define (flip-and-match c) 70 | (cond [(eq? c card-1) 71 | ;; Cancel first card 72 | (send t flip-card c) 73 | (set! card-1 #f)] 74 | [(not (send c face-down?)) 75 | ;; Can't click a matched card, unless the game is over, 76 | ;; in which case we reset the game 77 | (when (= matches MAX-MATCHES) 78 | (send t flip-cards deck) 79 | (set! matches 0) 80 | (setup))] 81 | [else 82 | ;; Flip over a card... 83 | (send t flip-card c) 84 | (send t card-to-front c) 85 | (cond [(not card-1) 86 | ;; That was the first card 87 | (set! card-1 c)] 88 | [(and (equal? (send card-1 get-value) (send c get-value)) 89 | (equal? (send card-1 get-suit) (send c get-suit))) 90 | ;; Match 91 | (send t move-cards (list card-1 c) match-x match-y) 92 | (set! card-1 #f) 93 | (set! matches (add1 matches))] 94 | [else 95 | ;; Not a match 96 | (send t pause 0.5) 97 | (send t flip-cards (list card-1 c)) 98 | (set! card-1 #f)])])) 99 | 100 | (send t set-single-click-action flip-and-match) 101 | 102 | ;; Start the game: 103 | (setup) 104 | -------------------------------------------------------------------------------- /lola-club/code-s8-notes.md: -------------------------------------------------------------------------------- 1 | # Lola session 8 host notes 2 | 3 | Snake game — written in Lua for the TIC-80 — made following [this tutorial at infinitelimit.net](https://www.infinitelimit.net/article/tic-80-snake). 4 | 5 | This session is suitable for beginners as the program presented is complete, simple and easily understood. The context of the TIC-80 provides some interesting discussion points for more experienced folks. 6 | 7 | The `code-s8.tic` "cartridge" can be loaded and run as-is in the [TIC-80](https://tic80.com/create). I'd recommend downloading the TIC-80 binary and running it locally, rather than typing everything into the HTML5 version on their site (can't copy/paste into the web version due to browser security restrictions on clipboard access). 8 | 9 | 10 | ## Notes/hints 11 | 12 | (All line numbers refer to `code-s8.pdf`) 13 | 14 | - The `TIC()` function on line 51 is the magic "main" function which is called by the TIC-80 60 times per second 15 | - Lua uses [tables](https://www.lua.org/manual/5.1/manual.html#2.5.7) for its arrays, associative arrays and more… 16 | >Tables are the sole data structuring mechanism in Lua; they can be used to represent ordinary arrays, symbol tables, sets, records, graphs, trees, etc. To represent records, Lua uses the field name as an index. The language supports this representation by providing a.name as syntactic sugar for a["name"]. 17 | - Lua's `#foo` "hashtag" (e.g. line 53) is its [length operator](https://www.lua.org/manual/5.1/manual.html#2.5.5), so `#body` gives you the length of the `body` table 18 | - The `pairs()` function (e.g. line 27) iterates over key/value pairs in a table 19 | - The [trace](https://github.com/nesbox/TIC-80/wiki/trace), [btn](https://github.com/nesbox/TIC-80/wiki/btn), [cls](https://github.com/nesbox/TIC-80/wiki/cls) and [rect](https://github.com/nesbox/TIC-80/wiki/rect) functions are all TIC-80 built-ins 20 | - If you have time, I'd definitely recommend screen sharing and showing the program running in the TIC-80 21 | - Our group enjoyed seeing the instant modify/run behaviour 22 | - You can load another demo cartridge like `quest.tic` to show the sprite and map editor 23 | - The body of the snake (and the food) is drawn with 8x8 blocks 24 | - Changing `*8` to `*4` in the `draw()` function will "double the resolution" 25 | - You'll also need to update the modulo operations on lines 64 and 65 so that the snake still wraps at the screen boundary 26 | - Game speed is controlled on line 21 27 | - The last parameter passed to `rect()` (and the only param to `cls()`) is a colour reference (integer index of the 16-colour palette) -------------------------------------------------------------------------------- /lola-club/code-s8.lua: -------------------------------------------------------------------------------- 1 | -- Created by IntelliJ IDEA. 2 | -- User: henry 3 | -- Date: 12/11/2020 4 | -- Time: 19:57 5 | -- To change this template use File | Settings | File Templates. 6 | -- Made by following this tutorial https://www.infinitelimit.net/article/tic-80-snake 7 | -- script: lua 8 | -- title: Snakey 9 | -- author: @trelemar 10 | -- palette: 1516184424340059ff4e4a4e854c30346524d9213f7571613898ecd27d2c8595a16daa2cd2aa996dc2cadad45edeeed6 11 | 12 | dirs={ 13 | [0]={x= 0,y=-1}, 14 | [1]={x= 0,y= 1}, 15 | [2]={x=-1,y= 0}, 16 | [3]={x= 1,y= 0} 17 | } 18 | 19 | function init() 20 | time=0 21 | count=0 22 | body={ 23 | {x=15,y=8}, 24 | {x=14,y=8}, 25 | {x=13,y=8} 26 | } 27 | target={x=0,y=0} 28 | dir=dirs[0] 29 | end 30 | 31 | function update() 32 | return time%5==0 33 | end 34 | 35 | function setTarget() 36 | target.x=math.random(0,29) 37 | target.y=math.random(0,16) 38 | for i,v in pairs(body) do 39 | if v.x==target.x and v.y==target.y then 40 | setTarget() 41 | end 42 | end 43 | end 44 | 45 | function hitTarget() 46 | if head.x==target.x and head.y==target.y then 47 | return true 48 | end 49 | end 50 | 51 | function draw() 52 | cls(2) 53 | for i,v in pairs(body) do 54 | rect(v.x*8,v.y*8,8,8,15) 55 | end 56 | rect(target.x*8,target.y*8,8,8,6) 57 | end 58 | 59 | init() 60 | setTarget() 61 | 62 | function TIC() 63 | time=time+1 64 | head = body[#body] 65 | join = body[#body-1] 66 | tail = body[1] 67 | if update() then 68 | for i,v in pairs(body) do 69 | if i~=#body and v.x==head.x and v.y==head.y then 70 | trace("Total: "..count) 71 | exit() 72 | end 73 | end 74 | table.insert(body, #body+1, { 75 | x=(head.x+dir.x) % 30, 76 | y=(head.y+dir.y) % 17 77 | }) 78 | if not hitTarget() then 79 | table.remove(body,1) 80 | else 81 | setTarget() 82 | count=count+1 83 | end 84 | end 85 | local last_dir=dir 86 | if btn(0) then dir=dirs[0] 87 | elseif btn(1) then dir=dirs[1] 88 | elseif btn(2) then dir=dirs[2] 89 | elseif btn(3) then dir=dirs[3] 90 | end 91 | 92 | if head.x+dir.x==join.x and head.y+dir.y==join.y then 93 | dir=last_dir 94 | end 95 | draw() 96 | end -------------------------------------------------------------------------------- /lola-club/code-s8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s8.pdf -------------------------------------------------------------------------------- /lola-club/code-s8.tic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/lola-club/code-s8.tic -------------------------------------------------------------------------------- /neontribe-club/retrospective/exercises.md: -------------------------------------------------------------------------------- 1 | ## Exercises 2 | 3 | ### Read and dicuss large code sample (20 mins) 4 | #### Read (Independent) 5 | #### Discuss (Group) 6 | Todo add structure if we think this is worthwhile exercise. 7 | 8 | ### Interaction with code 9 | #### Identify pieces (Independent) 10 | Use 3 different colours to circle and draw links between instantiation/declaration and uses of/calls to variables, methods/functions and classes 11 | 12 | #### Discuss patterns (Group) 13 | What patterns are visible from the colors? What parts of the code warrant more attention based on the colors? 14 | 15 | ### Content 16 | #### Identify 5 most important lines (Independent) 17 | 18 | #### Discuss (Group) 19 | lines covered by many people & lines named but not by a lot of people 20 | Agree less than 10 of the most important lines 21 | 22 | ### Summarize 23 | #### Essence of the code in a few sentences (Independent) 24 | #### Discuss (Group) 25 | topics covered by many vs few 26 | strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 27 | 28 | #### Create a summary (Group) 29 | Compare the summary with the available documentation (inside and outside the code) 30 | identify differences and similarities between the groups findings and the existing 31 | -------------------------------------------------------------------------------- /neontribe-club/retrospective/reflections.md: -------------------------------------------------------------------------------- 1 | ## Reflections 2 | 3 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 4 | - Note a time the past 2 weeks when you used information learned about code in your work 5 | 6 | ------------- 7 | 8 | - Helping people improve interview technique - by using the code club reading technique instead of white board for shared code reading exercise. 9 | - Decisions about order of items - in writing code. 10 | - Telling people it is amazing 11 | - Beginner thinks more about features and less about keywords whereas I think about keywords, not what they are doing. 12 | - Makes me think about comments more. 13 | - Crazy that we used to learn by reading lines Increased my confidence of reading python (beginner) 14 | - not just learning concepts only. 15 | - I'm here to see if there is anything I'm missing 16 | - some of the techniques second nature In terms of teaching me how to code. I don't follow instructions. 17 | - not in work, but talking about/promoting the idea of reading code to other developers who acknowledged that is a great initiative 18 | - making my comments less noisy - not new but a visual reminder of what that can do to a codebase\ 19 | - thinking about a problem I was facing - and I found myself thinking if navigating the whole code base not just a snippet could be useful (e.g. a small application, regardless of the language)\ 20 | - doing refactoring by looking at the core functionality - similar to the exercise where we identif 21 | -------------------------------------------------------------------------------- /neontribe-club/retrospective/wash-ups.md: -------------------------------------------------------------------------------- 1 | ## Wash ups 2 | 3 | ### Worked well 4 | 5 | - line numbers! 6 | - the club and conversations 7 | - This is a sufficiently sized example to have a crack at in the time we have 8 | - Amazing that we had an interesting conversation about simpole bit of code 9 | - Conversation is more about what it is doing and the structure rather than talking about the code syntax line by line (outputs/ comments/ it's messy/ it's noisy not this is a class and how we write it, etc.) 10 | - python which is what I am learaning anyway 11 | - good, clean piece of code, as every week we look at different code (language wise) 12 | - seemingly simple lines of code but more challenging than thought 13 | - reflection brought up quite a few uses about the information/techniques learned from previous sessions 14 | - Interesting code choice, challenged more experienced developers! 15 | 16 | 17 | ### Worked badly 18 | 19 | - ran out of time 20 | - taking notes and facilitating at the same time 21 | - experienced developers were doing most of the talking 22 | - The second bit of code (test output) wasn't looked at 23 | - Is as important and as hard to read as the comments 24 | - We talked about the wrong part of the code, not the interesting part 25 | - we didn't talk about method, class, variable this time 26 | - Not prepared for today - in a sprint week 27 | - didn't stick to the agenda and we tend to spend more time on certain parts (perhaps this tells us something about the group dynamic and maybe the agenda should be tailored to meet the group's needs?) 28 | - for beginners, some technical chat between more experienced developers was confusing/difficult to follow especially when not indicating the number of the code line in reference 29 | - time :-( we always overrun 30 | - no printer! need to have a section on digital marking and colouring code 31 | - prepare feedback comments before session we always struggle to remember 32 | - different formats when printed, maybe provide code samples as pdf with line numbers 33 | -------------------------------------------------------------------------------- /neontribe-club/session1/agenda-s1.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (5 mins) - usually that but first session ARC sample exercise - ID the purpose of each file 4 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 5 | - Note a time the past 2 weeks when you used information learned about code in your work 6 | 7 | ## Exercises 8 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 9 | 10 | You will need: 11 | - two printed copies of the code for today's club 12 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 13 | - coloured pens, crayons or pencils 14 | 15 | ### Interaction with code (10 mins) 16 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 17 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 18 | 1. Colour3 the classes - circle and draw links between classes and their instances 19 | 1. Draw the indentaiton patterns - There are a few ways to do this. Fill over with black sharpie. Trace on graph paper. Trace on acetate. etc? 20 | 21 | #### Discuss the results (10 mins) 22 | 1. What patterns are visible from the colors and indentations only? 23 | 1. What parts of the code warrant more attention based on the colors and indentation? 24 | 25 | ### Content 26 | 27 | #### Identify (10 mins) 28 | 1. Define what it means to be important and independently identify the 5 lines you consider most important 29 | 1. Discuss in the group: 30 | - lines covered by many people? 31 | - lines named but not by a lot of people 32 | - Agree less than 10 of the most important lines 33 | 34 | #### Discuss (10 mins) 35 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 36 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 37 | 38 | #### Summarize in less than 10 sentences (10 mins) 39 | 1. Independently write down the essence of the code in a few sentences 40 | 1. Discuss in the group 41 | - topics covered by many vs few 42 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 43 | 1. Create a summary together 44 | 1. Compare the summary with the available documentation (inside and outside the code) 45 | - identify differences and similarities between the groups findings and the existing 46 | 47 | 48 | ## Wash up (5 mins) 49 | - What worked well 50 | - What worked badly 51 | 52 | ## Follow up (2 weeks of elapsed time) 53 | - Identify code for next session, keaping in mind Wash up and Reflection information 54 | 55 | 56 | -------------------------------------------------------------------------------- /neontribe-club/session1/code-sample-ARCVService-Note.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session1/code-sample-ARCVService-Note.pdf -------------------------------------------------------------------------------- /neontribe-club/session1/code-sample-gbptm-UI-LooListItem.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session1/code-sample-gbptm-UI-LooListItem.pdf -------------------------------------------------------------------------------- /neontribe-club/session1/completedExercises/colouring-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session1/completedExercises/colouring-example.jpg -------------------------------------------------------------------------------- /neontribe-club/session1/completedExercises/what-for-example.txt: -------------------------------------------------------------------------------- 1 | Note model/ object 2 | CentreUser model that can have notes. 3 | Family model that can have notes. 4 | Creates the data store for the Note 5 | Tests for the CentreUser-Note relationship. No tests for Family. 6 | 7 | Curiously - the Note is never used in the app. 8 | -------------------------------------------------------------------------------- /neontribe-club/session1/what-happened-s1.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (5 mins) - usually that but first session ARC sample exercise - ID the purpose of each file 4 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 5 | - Note a time the past 2 weeks when you used information learned about code in your work 6 | 7 | ## Exercises 8 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 9 | 10 | You will need: 11 | - two printed copies of the code for today's club 12 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 13 | - coloured pens, crayons or pencils 14 | 15 | ### Interaction with code (10 mins) 16 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 17 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 18 | 1. Colour3 the classes - circle and draw links between classes and their instances 19 | 1. Draw the indentaiton patterns - There are a few ways to do this. Fill over with black sharpie. Trace on graph paper. Trace on acetate. etc? 20 | 21 | #### Discuss the results (10 mins) 22 | 1. What patterns are visible from the colors and indentations only? 23 | 1. What parts of the code warrant more attention based on the colors and indentation? 24 | 25 | ### Content 26 | 27 | #### Identify (10 mins) 28 | 1. Define what it means to be important and independently identify the 5 lines you consider most important 29 | 1. Discuss in the group: 30 | - lines covered by many people? 31 | - lines named but not by a lot of people 32 | - Agree less than 10 of the most important lines 33 | 34 | #### Discuss (10 mins) 35 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 36 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 37 | 38 | #### Summarize in less than 10 sentences (10 mins) 39 | 1. Independently write down the essence of the code in a few sentences 40 | 1. Discuss in the group 41 | - topics covered by many vs few 42 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 43 | 1. Create a summary together 44 | 1. Compare the summary with the available documentation (inside and outside the code) 45 | - identify differences and similarities between the groups findings and the existing 46 | 47 | 48 | ## Wash up (5 mins) 49 | - What worked well 50 | - What worked badly 51 | 52 | ## Follow up (2 weeks of elapsed time) 53 | - Identify code for next session, keaping in mind Wash up and Reflection information 54 | 55 | 56 | -------------------------------------------------------------------------------- /neontribe-club/session11/agenda.md: -------------------------------------------------------------------------------- 1 | ## Advanced Exercises 2 | 3 | These exercises are more advanced, in the sense that you might need a bit more understanding of the code for these to make sense. This might be because the group is familiar with the code before the session, or because you are doing a second club on the same code snippet. 4 | 5 | ### Code structure 6 | 7 | #### Examine structure (5 mins) 8 | 9 | Use one of the basic exercises to examine the structure of the code (such as circle variables and link them), or reuse the notes from the previous club. Individuallt study the patterns and think about what they tell you. What direction does the code 'flow' in? What parts stand out for lack of, or access of links? 10 | 11 | #### Discussion (10 mins) 12 | 13 | - Parts of the code covered by many vs few 14 | - Strategies used to decide 15 | 16 | ### Content 17 | 18 | #### Central thematic concepts (5 mins) 19 | 20 | Each participant gets 5 minutes to individually name the 5 most central concepts of the code. These could be names, themes, classes, or information found in comments. 21 | 22 | #### Discussion (10 mins) 23 | 24 | - Topics covered by many vs few 25 | - Strategies used to decide (e.g. method names, documentation, variable names, prior knowledge of system) 26 | 27 | #### Central programming concepts (5 mins) 28 | 29 | Each participant gets 5 minutes to individually name the 5 most central computer science concepts of the code. These could be algorithms, data structures, assumptions or techniques. 30 | 31 | #### Discussion (10 mins) 32 | 33 | - Topics covered by many vs few 34 | - Strategies used to decide (e.g. method names, documentation, variable names, prior knowledge of system) 35 | 36 | ### The 'why' of the code 37 | 38 | Reexamine the code snippet and list decisions and intentions of the creator(s) of the code. For example a decision to use a certain design pattern ir use a certain library or API? 39 | 40 | * What decisions were made in the creation of this code? 41 | * What assumptions do these decisions rely on? 42 | 43 | #### Discussion (10 mins) 44 | 45 | Gather all decisions people made individually and discuss: 46 | 47 | - Pros of these decisions 48 | - Possible cons of these decisions 49 | - Alternative solutions 50 | -------------------------------------------------------------------------------- /neontribe-club/session11/marked-up-code.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session11/marked-up-code.jpg -------------------------------------------------------------------------------- /neontribe-club/session11/notes.md: -------------------------------------------------------------------------------- 1 | Central Thematic Concepts 2 | 3 | - const list generate markup for list of patients 4 | - load patients 5 | - search to filter patients 6 | - 7 | 8 | 9 | -looks highly finctional 10 | - bunch of functions 11 | - whole pile of const 12 | 13 | 14 | - component framework of react 15 | - also own made components 16 | - relying on whole load of other stuff 17 | - recent react useEffect 18 | - breaks out complicated UI 19 | - uses REDUx 20 | 21 | 22 | Discussion 23 | - 3 of us picked out structural things about code being built of fuctions 24 | - 2 peolpe talked framework - prior knowledge 25 | - Had not seen before, not idea what does, structure 26 | - WHy is hte code layed out this way, not guess what it does. 27 | - noticable lack of documentation 28 | - used method & variable names 29 | 30 | 31 | Cebtral programming 32 | 33 | - do not repeat yourself, highly modular 34 | - transpolation - virtual language (react) 35 | - type enforcement 36 | - async procedures 37 | - templating 38 | 39 | - declarative - extracts the doing for you (react) e.g. virtual dom 40 | - component driven way of buidling. expect components to have exportable blobs of markup, styles and functions 41 | 42 | - funcitonal programming 43 | - higher order functions 44 | - types 45 | 46 | -react core methods 47 | - events 48 | - async 49 | - html 50 | - html form submit 51 | - mapping 52 | - fetch - wait state - render 53 | - translate key -> string 54 | - state management in objects 55 | 56 | 57 | Discussion 58 | - you 3 went high level 1 went lower 59 | - only crossover was types and componet-y nature 60 | - backed out of code and looked for blocks that were implementing lang features 61 | - got DRY from all the imports 62 | - react - we know is transpiles 63 | - async obvious 64 | - triggered by earlier discusion on functions 65 | - previous stuff not reading now 66 | - looked blocks of code to identify what atterns they used on a low level 67 | - is a .tsx file 68 | - used types to id what htings were maybe that is why not as much docs?) 69 | 70 | 71 | The why of the code 72 | 73 | - React (get state management for free) 74 | - Types 75 | - tsx (html really) 76 | - Components with props to customise 77 | - const for functions to reuse and state info 78 | - translation system to keep copy out 79 | - classes in html 80 | 81 | - offline first (literally says that) 82 | - web tool hybrid development (not native) 83 | - included more libraries because their choice of react was was limiting (e.g. wanted types0 84 | - most modern tecniques they could find 85 | 86 | - Use react! 87 | - To show patients 88 | - No useful comments 89 | - use spinners to make the ui seems more responsive 90 | - reuse components, maybe not v accessible way 91 | 92 | - functional components 93 | - loading spinner for better UI (good idea!) 94 | 95 | 96 | Discussion 97 | - offline first means hybrid 98 | - like assigning functions to const could be less invasive to use named 99 | - prefer named functions directly 100 | 101 | Pros and Cons 102 | - cons of js is library management - need to touch every month at least 103 | - offline choice makes it hard 104 | - where data lives? data management 105 | - developing world aware they need to sync , not expect constant connection 106 | 107 | Wash up: 108 | 109 | Well 110 | - revist used bit of code already marked 111 | - straight into conversatoin 112 | - made us thing more about the architechtue and concepts more 113 | - more about planning and think about why they code is like that vs figuring out what the code does (in easrlier sessoins) 114 | - fun 115 | 116 | Badly 117 | - Questioning is wide, more specific 118 | - Why of the code needs warning that beginners might listen 119 | - Why of the code needs more context maybe more explain 120 | (not why they made decisions, but what they get for free and what rods they have created for backs) 121 | - Programming concepts (for beginners prompy with 'like a for loop') 122 | 123 | Amend resources: 124 | - couple typos 125 | - add 5 mins independant to why of code section 126 | - Central theme needs more clear task 127 | - Examine structure section same as before? 128 | 129 | -------------------------------------------------------------------------------- /neontribe-club/session2/agenda-s2.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (5 mins) 4 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 5 | - Note a time the past 2 weeks when you used information learned about code in your work 6 | 7 | ## Exercises 8 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 9 | 10 | You will need: 11 | - two printed copies of the code for today's club 12 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 13 | - coloured pens, crayons or pencils 14 | 15 | ### Interaction with code (10 mins) 16 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 17 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 18 | 1. Colour3 the classes - circle and draw links between classes and their instances 19 | 1. Draw the indentaiton patterns - There are a few ways to do this. Fill over with black sharpie. Trace on graph paper. Trace on acetate. etc? 20 | 21 | #### Discuss the results (10 mins) 22 | 1. What patterns are visible from the colors and indentations only? 23 | 1. What parts of the code warrant more attention based on the colors and indentation? 24 | 25 | ### Content 26 | 27 | #### Identify (10 mins) 28 | 1. Define what it means to be important and independently identify the 5 lines you consider most important 29 | 1. Discuss in the group: 30 | - lines covered by many people? 31 | - lines named but not by a lot of people 32 | - Agree less than 10 of the most important lines 33 | 34 | #### Discuss (10 mins) 35 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 36 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 37 | 38 | #### Summarize in less than 10 sentences (10 mins) 39 | 1. Independently write down the essence of the code in a few sentences 40 | 1. Discuss in the group 41 | - topics covered by many vs few 42 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 43 | 1. Create a summary together 44 | 1. Compare the summary with the available documentation (inside and outside the code) 45 | - identify differences and similarities between the groups findings and the existing 46 | 47 | 48 | ## Wash up (5 mins) 49 | - What worked well 50 | - What worked badly 51 | 52 | ## Follow up (2 weeks of elapsed time) 53 | - Identify code for next session, keaping in mind Wash up and Reflection information 54 | 55 | 56 | -------------------------------------------------------------------------------- /neontribe-club/session2/completedExercises/colouring-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session2/completedExercises/colouring-example.jpg -------------------------------------------------------------------------------- /neontribe-club/session2/completedExercises/what-for-example.txt: -------------------------------------------------------------------------------- 1 | Base utility classes for google app engine API email functions with specific rules 2 | Functions for sending mail using mailgun in bulk 3 | Tests for the gae services 4 | Tests for the mailgun services 5 | 6 | 7 | -------------------------------------------------------------------------------- /neontribe-club/session2/python_file_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session2/python_file_1.pdf -------------------------------------------------------------------------------- /neontribe-club/session2/python_file_1_test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session2/python_file_1_test.pdf -------------------------------------------------------------------------------- /neontribe-club/session2/python_file_2-tests.py: -------------------------------------------------------------------------------- 1 | # Source: Oppia - https://github.com/oppia/oppia - an online learning tool that enables anyone to easily create and share interactive activities 2 | 3 | """Tests for the Mailgun API wrapper.""" 4 | 5 | from __future__ import absolute_import # pylint: disable=import-only-modules 6 | from __future__ import unicode_literals # pylint: disable=import-only-modules 7 | 8 | from core.platform.email import mailgun_email_services 9 | from core.tests import test_utils 10 | import feconf 11 | import python_utils 12 | 13 | 14 | class EmailTests(test_utils.GenericTestBase): 15 | """Tests for sending emails.""" 16 | 17 | def test_post_to_mailgun(self): 18 | """Test for sending HTTP POST request.""" 19 | swapped_urlopen = lambda x: x 20 | swapped_request = lambda *args: args 21 | swap_urlopen_context = self.swap( 22 | python_utils, 'url_open', swapped_urlopen) 23 | swap_request_context = self.swap( 24 | python_utils, 'url_request', swapped_request) 25 | swap_api = self.swap(feconf, 'MAILGUN_API_KEY', 'key') 26 | swap_domain = self.swap(feconf, 'MAILGUN_DOMAIN_NAME', 'domain') 27 | with swap_urlopen_context, swap_request_context, swap_api, swap_domain: 28 | result = mailgun_email_services.post_to_mailgun({ 29 | 'from': 'a@a.com', 30 | 'to': 'b@b.com', 31 | 'subject': 'Hola 😂 - invitation to collaborate'.encode( 32 | encoding='utf-8'), 33 | 'text': 'plaintext_body 😂'.encode(encoding='utf-8'), 34 | 'html': 'Hi abc,
😂'.encode(encoding='utf-8') 35 | }) 36 | expected = ( 37 | 'https://api.mailgun.net/v3/domain/messages', 38 | ('to=b%40b.com&text=plaintext_body+%F0%9F%98%82&html=Hi+abc' 39 | '%2C%3Cbr%3E+%F0%9F%98%82&from=a%40a.com&subject=Hola+%F0' 40 | '%9F%98%82+-+invitation+to+collaborate'), 41 | {'Authorization': 'Basic YXBpOmtleQ=='}) 42 | self.assertEqual(result, expected) 43 | 44 | def test_send_mail_raises_exception_for_missing_api_key(self): 45 | """Tests the missing Mailgun API key exception.""" 46 | mailgun_api_exception = ( 47 | self.assertRaisesRegexp( 48 | Exception, 'Mailgun API key is not available.')) 49 | 50 | allow_emailing = self.swap(feconf, 'CAN_SEND_EMAILS', True) 51 | with mailgun_api_exception, allow_emailing: 52 | mailgun_email_services.send_mail( 53 | feconf.SYSTEM_EMAIL_ADDRESS, feconf.ADMIN_EMAIL_ADDRESS, 54 | 'subject', 'body', 'html', bcc_admin=False) 55 | 56 | def test_send_mail_raises_exception_for_missing_domain_name(self): 57 | """Tests the missing Mailgun domain name exception.""" 58 | mailgun_api = self.swap(feconf, 'MAILGUN_API_KEY', 'api') 59 | mailgun_domain_name_exception = ( 60 | self.assertRaisesRegexp( 61 | Exception, 'Mailgun domain name is not set.')) 62 | allow_emailing = self.swap(feconf, 'CAN_SEND_EMAILS', True) 63 | with mailgun_api, mailgun_domain_name_exception, allow_emailing: 64 | mailgun_email_services.send_mail( 65 | feconf.SYSTEM_EMAIL_ADDRESS, feconf.ADMIN_EMAIL_ADDRESS, 66 | 'subject', 'body', 'html', bcc_admin=False) 67 | 68 | def test_send_mail_raises_exception_for_invalid_permissions(self): 69 | """Tests the send_mail exception raised for invalid user permissions.""" 70 | send_email_exception = ( 71 | self.assertRaisesRegexp( 72 | Exception, 'This app cannot send emails to users.')) 73 | mailgun_api = self.swap(feconf, 'MAILGUN_API_KEY', 'api') 74 | mailgun_domain = self.swap(feconf, 'MAILGUN_DOMAIN_NAME', 'domain') 75 | with mailgun_api, mailgun_domain, send_email_exception: 76 | mailgun_email_services.send_mail( 77 | feconf.SYSTEM_EMAIL_ADDRESS, feconf.ADMIN_EMAIL_ADDRESS, 78 | 'subject', 'body', 'html', bcc_admin=False) 79 | 80 | def test_send_mail_data_properly_sent(self): 81 | """Verifies that the data sent in send_mail is correct.""" 82 | mailgun_api = self.swap(feconf, 'MAILGUN_API_KEY', 'api') 83 | mailgun_domain = self.swap(feconf, 'MAILGUN_DOMAIN_NAME', 'domain') 84 | allow_emailing = self.swap(feconf, 'CAN_SEND_EMAILS', True) 85 | 86 | # Data we expect to have been sent in the 87 | # mailgun_email_services.post_to_mailgun(). 88 | expected = {'from': feconf.SYSTEM_EMAIL_ADDRESS, 89 | 'to': feconf.ADMIN_EMAIL_ADDRESS, 90 | 'subject': 'subject', 91 | 'text': 'body', 92 | 'html': 'html'} 93 | 94 | # Lambda function, will replace post_to_mailgun(). 95 | req_post_lambda = (lambda data=None: 96 | self.assertDictContainsSubset(expected, data)) 97 | post_request = self.swap( 98 | mailgun_email_services, 'post_to_mailgun', req_post_lambda) 99 | 100 | with mailgun_api, mailgun_domain, post_request, allow_emailing: 101 | mailgun_email_services.send_mail( 102 | feconf.SYSTEM_EMAIL_ADDRESS, feconf.ADMIN_EMAIL_ADDRESS, 103 | 'subject', 'body', 'html', bcc_admin=False) 104 | 105 | def test_bcc_admin_flag(self): 106 | """Verifies that the bcc admin flag is working properly in send_mail. 107 | Note that we replace the mailgun_email_services.post_to_mailgun() 108 | function in send_mail with an alternate lambda that asserts the correct 109 | values were placed in the data dictionary that is then passed to the 110 | mailgun api. 111 | """ 112 | mailgun_api = self.swap(feconf, 'MAILGUN_API_KEY', 'api') 113 | mailgun_domain = self.swap(feconf, 'MAILGUN_DOMAIN_NAME', 'domain') 114 | allow_emailing = self.swap(feconf, 'CAN_SEND_EMAILS', True) 115 | 116 | # Lambda function, will replace post_to_mailgun(). 117 | req_post_lambda = (lambda data=None: 118 | self.assertEqual( 119 | data['bcc'], feconf.ADMIN_EMAIL_ADDRESS)) 120 | post_request = self.swap( 121 | mailgun_email_services, 'post_to_mailgun', req_post_lambda) 122 | 123 | with mailgun_api, mailgun_domain, post_request, allow_emailing: 124 | mailgun_email_services.send_mail( 125 | feconf.SYSTEM_EMAIL_ADDRESS, feconf.ADMIN_EMAIL_ADDRESS, 126 | 'subject', 'body', 'html', bcc_admin=True) 127 | 128 | def test_reply_to_id_flag(self): 129 | """Verifies that the reply_to_id flag is working properly.""" 130 | mailgun_api = self.swap(feconf, 'MAILGUN_API_KEY', 'api') 131 | mailgun_domain = self.swap(feconf, 'MAILGUN_DOMAIN_NAME', 'domain') 132 | allow_emailing = self.swap(feconf, 'CAN_SEND_EMAILS', True) 133 | reply_id = 123 134 | 135 | # Lambda function, will replace post_to_mailgun(). 136 | req_post_lambda = ( 137 | lambda data=None: 138 | self.assertEqual( 139 | data['h:Reply-To'], 140 | 'reply+' + python_utils.UNICODE(reply_id) + '@' + 141 | feconf.INCOMING_EMAILS_DOMAIN_NAME)) 142 | post_request = self.swap( 143 | mailgun_email_services, 'post_to_mailgun', req_post_lambda) 144 | 145 | with mailgun_api, mailgun_domain, post_request, allow_emailing: 146 | mailgun_email_services.send_mail( 147 | feconf.SYSTEM_EMAIL_ADDRESS, feconf.ADMIN_EMAIL_ADDRESS, 148 | 'subject', 'body', 'html', 149 | bcc_admin=False, reply_to_id=reply_id) 150 | 151 | def test_send_bulk_mail_raises_exception_for_missing_api_key(self): 152 | """Test that send_bulk_mail raises exception for missing 153 | mailgun api key. 154 | """ 155 | mailgun_api_exception = ( 156 | self.assertRaisesRegexp( 157 | Exception, 'Mailgun API key is not available.')) 158 | allow_emailing = self.swap(feconf, 'CAN_SEND_EMAILS', True) 159 | with mailgun_api_exception, allow_emailing: 160 | mailgun_email_services.send_bulk_mail( 161 | feconf.SYSTEM_EMAIL_ADDRESS, [feconf.ADMIN_EMAIL_ADDRESS], 162 | 'subject', 'body', 'html') 163 | 164 | def test_send_bulk_mail_raises_exception_for_missing_domain_name(self): 165 | """Tests the missing Mailgun domain name exception for 166 | send_bulk_mail. 167 | """ 168 | mailgun_api = self.swap(feconf, 'MAILGUN_API_KEY', 'api') 169 | allow_emailing = self.swap(feconf, 'CAN_SEND_EMAILS', True) 170 | mailgun_domain_name_exception = ( 171 | self.assertRaisesRegexp( 172 | Exception, 'Mailgun domain name is not set.')) 173 | with mailgun_api, mailgun_domain_name_exception, allow_emailing: 174 | mailgun_email_services.send_bulk_mail( 175 | feconf.SYSTEM_EMAIL_ADDRESS, [feconf.ADMIN_EMAIL_ADDRESS], 176 | 'subject', 'body', 'html') 177 | 178 | def test_send_bulk_mail_exception_for_invalid_permissions(self): 179 | """Tests the send_bulk_mail exception raised for invalid user 180 | permissions. 181 | """ 182 | send_email_exception = ( 183 | self.assertRaisesRegexp( 184 | Exception, 'This app cannot send emails to users.')) 185 | mailgun_api = self.swap(feconf, 'MAILGUN_API_KEY', 'api') 186 | mailgun_domain = self.swap(feconf, 'MAILGUN_DOMAIN_NAME', 'domain') 187 | with mailgun_api, mailgun_domain, send_email_exception: 188 | mailgun_email_services.send_bulk_mail( 189 | feconf.SYSTEM_EMAIL_ADDRESS, [feconf.ADMIN_EMAIL_ADDRESS], 190 | 'subject', 'body', 'html') 191 | 192 | def test_send_bulk_mail_data_properly_sent(self): 193 | """Verifies that the data sent in send_bulk_mail is correct 194 | for each user in the recipient list. 195 | """ 196 | mailgun_api = self.swap(feconf, 'MAILGUN_API_KEY', 'api') 197 | mailgun_domain = self.swap(feconf, 'MAILGUN_DOMAIN_NAME', 'domain') 198 | allow_emailing = self.swap(feconf, 'CAN_SEND_EMAILS', True) 199 | recipients = [feconf.ADMIN_EMAIL_ADDRESS] 200 | 201 | # Data that we expect to have been sent in the post_to_mailgun(). 202 | expected = ({'from': feconf.SYSTEM_EMAIL_ADDRESS, 'to': recipients, 203 | 'subject': 'subject', 'text': 'body', 'html': 'html', 204 | 'recipient-variables': '{}'}) 205 | 206 | # Lambda function, will replace post_to_mailgun(). 207 | req_post_lambda = (lambda data=None: 208 | self.assertDictContainsSubset(expected, data)) 209 | post_request = self.swap( 210 | mailgun_email_services, 'post_to_mailgun', req_post_lambda) 211 | 212 | with mailgun_api, mailgun_domain, post_request, allow_emailing: 213 | mailgun_email_services.send_bulk_mail( 214 | feconf.SYSTEM_EMAIL_ADDRESS, recipients, 215 | 'subject', 'body', 'html') 216 | -------------------------------------------------------------------------------- /neontribe-club/session2/python_file_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session2/python_file_2.pdf -------------------------------------------------------------------------------- /neontribe-club/session2/short-code-option-1-code-format.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session2/short-code-option-1-code-format.pdf -------------------------------------------------------------------------------- /neontribe-club/session2/what-happened-s2.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (10 mins) 4 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 5 | - Note a time the past 2 weeks when you used information learned about code in your work 6 | 7 | Helping people improve interview technique - by using the code club reading technique instead of whote board for shared code reading exercise. 8 | order of items- in writing code. 9 | 10 | ## Exercises 11 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 12 | 13 | You will need: 14 | - two printed copies of the code for today's club 15 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 16 | - coloured pens, crayons or pencils 17 | 18 | ### Read code files (8mins) 19 | This week we had 4 files 20 | 21 | ### Discuss code files (12mins) 22 | Comments helpful and informative - is that right to look at them? 23 | Testing a hypothesis - will the tests tell me what the code is supposed to do 24 | There were a lot of tests - seems like they were tesing the API not only their own 25 | function doc comments are in the functions (can be in there for the ast) - so they ship with code 26 | extra thought - you can use your comments as test 27 | lookslike it is in the way but you get used to it 28 | multiline comments and strings use same syntax - not a problem because of indenting 29 | mailgun vs appengine - do they build on each other 30 | 31 | ### Exercise Interaction with code (10 mins) 32 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 33 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 34 | 1. Colour3 the classes - circle and draw links between classes and their instances 35 | 36 | #### Discuss the results (10 mins) 37 | 1. What patterns are visible from the colors? 38 | 1. What parts of the code warrant more attention based on the colors? 39 | - Confused me more than last week 40 | - was expecting to be procedureal but ended up looking like circles 41 | - wanted to visualise output but didn't have time 42 | - variables/ constants turned out to be functions 43 | - we couldn't find any classes but sometimes under the hood some might be intantiated as objects 44 | - traditional CSc model of oop but this code feels more aiming for pure functional 45 | - using typescript but not types 46 | - uses known and understood conventions (like use- and set-) but this is by practice/ convention and not obvious to new people to write this way 47 | - found myself drawing flux / redux cycles on the page 48 | 49 | ### Content 50 | 51 | #### Identify (10 mins) 52 | 1. Define what it means to be important and independently identify the 5 lines you consider most important 53 | 1. Discuss in the group: 54 | - lines covered by many people? 55 | - lines named but not by a lot of people 56 | - Agree less than 10 of the most important lines 57 | 58 | Votes by line number: count 59 | 7, 17, 18, 28, 41, 45, 50, : 1 60 | 11, 19, 23: 2 61 | 47: 3 62 | 34, 75: 4 63 | 64 | #### Some notes in conversation 65 | - history wasn't history of patients, but browser history - this is an example of convention we take for granted 66 | - where are side effects 67 | - using the patients string in 2 places near each other looks like var but was a translation string 68 | - dispatch event important 69 | - people who write react a lot took export for granted 70 | - people not as familiar with react went there first 71 | - agree that the core markup generator of patient list item and the side effects most important to understand 72 | - thoughts around what is important when reading vs writing the code 73 | 74 | ## Wash up (independent after session) 75 | ### What worked well 76 | - line numbers! 77 | - the club and conversations 78 | 79 | ### What worked badly 80 | - ran out of time 81 | - taking notes and facilitating at the same time 82 | - experienced developers were doing most of the talking 83 | 84 | ## Follow up (2 weeks of elapsed time) 85 | - Identify code for next session, keeping in mind Wash up and Reflection information 86 | - Rob to id some code with comments as tests 87 | - Try to get to the section about independent summary 88 | -------------------------------------------------------------------------------- /neontribe-club/session3/agenda-s3.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | katja, charlie, alin, amanda, nick, rob 3 | 4 | ## Reflection (5 mins) 12:37 5 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 6 | - Note a time the past 2 weeks when you used information learned about code in your work 7 | Telling people it is amazing 8 | Not actual evidence of how it helps but - observations 9 | Beginner things more about features and less about keywords whereas I think about keywords, not what they are doing. Makes me think about comments more. 10 | Crazy that we used to learn by reading lines 11 | Increased my confidence of reading python (beginner) - not just learning concepts only. 12 | Here to see if there is anything I'm missing -some of the techniques second nature 13 | In terms of teaching me how to code. I don't follow instructions. 14 | 15 | ## Exercises 16 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 17 | 18 | You will need: 19 | - two printed copies of the code for today's club 20 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 21 | - coloured pens, crayons or pencils 22 | 23 | ### Interaction with code (10 mins) 12:42 24 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 25 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 26 | 1. Colour3 the classes - circle and draw links between classes and their instances 27 | 1. Draw the indentaiton patterns - There are a few ways to do this. Fill over with black sharpie. Trace on graph paper. Trace on acetate. etc? 28 | 29 | #### Discuss the results (10 mins) 12:52 30 | 1. What patterns are visible from the colors and indentations only? 31 | 1. What parts of the code warrant more attention based on the colors and indentation? 32 | 33 | - Identation shows that import inside of the function. I'm used to languages where imports happen at top of file. 34 | - Import works wherever you use it in python. Like require in js. 35 | - Indentation level scopes stuff the block of code 36 | - Comment very noisy compared to the code 37 | - Looks like it's inside a REPL 38 | - Doc test library needs the syntax for parsing 39 | - Confused me at first - thought it was the code 40 | 41 | ### Content 42 | 43 | #### Identify (10 mins) 13:00 44 | 1. Define what it means to be important and independently identify the 3 lines you consider most important 45 | 1. Discuss in the group: 46 | - lines covered by many people? 47 | 46 (4 people) and 47 (3 people) 48 | - lines named but not by a lot of people 49 | 10, 37, 48, 49 (2 people) and 52,53 (1 person) 50 | - Agree less than 7 of the most important lines 51 | - 46, 47, 38, 40, 42 - interestingly when we only had 3 lines to choose independently, no one chose 38,40,42 52 | 53 | #### Discuss (10 mins) 13:20 54 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 55 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 56 | 57 | - Form is confusing because I don't know python 58 | - I'm a beginner and it doesn't match what I know about python. Is a mess. 59 | - If it didn't have the if block for floats, would not need to import all of `math` 60 | - I like lots of code examples in file don't always see that 61 | - Big numbers in python 300 zeros behind one number 62 | - Python is lovely for big numbers 63 | - You can have too much tests in your comments 64 | -Impression that formatting of comments is not consistant with the """ on same line at start and new line at end. 65 | - There's only one inline comment (catch the big number by using n+1 ==n) 66 | - Now I understand why we have colour coding in our IDEs 67 | 68 | #### Summarize in less than 10 sentences (10 mins) SKIPPED 69 | 1. Independently write down the essence of the code in a few sentences 70 | 1. Discuss in the group 71 | - topics covered by many vs few 72 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 73 | 1. Create a summary together 74 | 1. Compare the summary with the available documentation (inside and outside the code) 75 | - identify differences and similarities between the groups findings and the existing 76 | 77 | 78 | ## Wash up (5 mins) 13:27 79 | ### What worked well 80 | - This is a sufficiently sized example to have a crack at in the time we have 81 | - Amazing that we had an interesting conversation about simpole bit of code 82 | - Conversation is more about what it is doing and the structure rather than talking about the code syntax line by line (outputs/ comments/ it's messy/ it's noisy not this is a class and how we write it, etc.) 83 | - python which is what I am learaning anyway 84 | 85 | ### What worked badly 86 | - The second bit of code (test output) wasn't looked at 87 | - Is as important and as hard to read as the comments 88 | - We talked about the wrong part of the code, not the interesting part 89 | - we didn't talk about method, class, variable this time 90 | - Not prepared for today - in a sprint week 91 | 92 | Finish 13:35 93 | 94 | ## Follow up (2 weeks of elapsed time) 95 | - Identify code for next session, keeping in mind Wash up and Reflection information 96 | 97 | 98 | -------------------------------------------------------------------------------- /neontribe-club/session3/completedExercises/doctest-example-coloured.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session3/completedExercises/doctest-example-coloured.jpg -------------------------------------------------------------------------------- /neontribe-club/session3/doctest-example.py: -------------------------------------------------------------------------------- 1 | """ 2 | This is the "example" module. 3 | 4 | The example module supplies one function, factorial(). For example, 5 | 6 | >>> factorial(5) 7 | 120 8 | """ 9 | 10 | def factorial(n): 11 | """Return the factorial of n, an exact integer >= 0. 12 | 13 | >>> [factorial(n) for n in range(6)] 14 | [1, 1, 2, 6, 24, 120] 15 | >>> factorial(30) 16 | 265252859812191058636308480000000 17 | >>> factorial(-1) 18 | Traceback (most recent call last): 19 | ... 20 | ValueError: n must be >= 0 21 | 22 | Factorials of floats are OK, but the float must be an exact integer: 23 | >>> factorial(30.1) 24 | Traceback (most recent call last): 25 | ... 26 | ValueError: n must be exact integer 27 | >>> factorial(30.0) 28 | 265252859812191058636308480000000 29 | 30 | It must also not be ridiculously large: 31 | >>> factorial(1e100) 32 | Traceback (most recent call last): 33 | ... 34 | OverflowError: n too large 35 | """ 36 | 37 | import math 38 | if not n >= 0: 39 | raise ValueError("n must be >= 0") 40 | if math.floor(n) != n: 41 | raise ValueError("n must be exact integer") 42 | if n+1 == n: # catch a value like 1e300 43 | raise OverflowError("n too large") 44 | result = 1 45 | factor = 2 46 | while factor <= n: 47 | result *= factor 48 | factor += 1 49 | return result 50 | 51 | 52 | if __name__ == "__main__": 53 | import doctest 54 | doctest.testmod() -------------------------------------------------------------------------------- /neontribe-club/session3/doctest-example.py.stdout: -------------------------------------------------------------------------------- 1 | $ python doctest-example.py -v 2 | Trying: 3 | factorial(5) 4 | Expecting: 5 | 120 6 | ok 7 | Trying: 8 | [factorial(n) for n in range(6)] 9 | Expecting: 10 | [1, 1, 2, 6, 24, 120] 11 | ok 12 | Trying: 13 | factorial(30) 14 | Expecting: 15 | 265252859812191058636308480000000 16 | ********************************************************************** 17 | File "doctest-example.py", line 15, in __main__.factorial 18 | Failed example: 19 | factorial(30) 20 | Expected: 21 | 265252859812191058636308480000000 22 | Got: 23 | 265252859812191058636308480000000L 24 | Trying: 25 | factorial(-1) 26 | Expecting: 27 | Traceback (most recent call last): 28 | ... 29 | ValueError: n must be >= 0 30 | ok 31 | Trying: 32 | factorial(30.1) 33 | Expecting: 34 | Traceback (most recent call last): 35 | ... 36 | ValueError: n must be exact integer 37 | ok 38 | Trying: 39 | factorial(30.0) 40 | Expecting: 41 | 265252859812191058636308480000000 42 | ********************************************************************** 43 | File "doctest-example.py", line 27, in __main__.factorial 44 | Failed example: 45 | factorial(30.0) 46 | Expected: 47 | 265252859812191058636308480000000 48 | Got: 49 | 265252859812191058636308480000000L 50 | Trying: 51 | factorial(1e100) 52 | Expecting: 53 | Traceback (most recent call last): 54 | ... 55 | OverflowError: n too large 56 | ok 57 | 1 items passed all tests: 58 | 1 tests in __main__ 59 | ********************************************************************** 60 | 1 items had failures: 61 | 2 of 6 in __main__.factorial 62 | 7 tests in 2 items. 63 | 5 passed and 2 failed. 64 | ***Test Failed*** 2 failures. 65 | -------------------------------------------------------------------------------- /neontribe-club/session4/Signal-iOS-PhoneNumberValidator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2019 Open Whisper Systems. All rights reserved. 3 | // 4 | import Foundation 5 | import SignalServiceKit 6 | 7 | @objc 8 | public enum ValidatedPhoneCountryCodes: UInt { 9 | case unitedStates = 1 10 | case brazil = 55 11 | } 12 | 13 | @objc 14 | public class PhoneNumberValidator: NSObject { 15 | 16 | @objc 17 | public func isValidForRegistration(phoneNumber: PhoneNumber) -> Bool { 18 | guard let countryCode = phoneNumber.getCountryCode() else { 19 | return false 20 | } 21 | 22 | guard let validatedCountryCode = ValidatedPhoneCountryCodes(rawValue: countryCode.uintValue) else { 23 | // no extra validation for this country 24 | return true 25 | } 26 | 27 | switch validatedCountryCode { 28 | case .brazil: 29 | return isValidForBrazilRegistration(phoneNumber: phoneNumber) 30 | case .unitedStates: 31 | return isValidForUnitedStatesRegistration(phoneNumber: phoneNumber) 32 | } 33 | } 34 | 35 | let validBrazilPhoneNumberRegex = try! NSRegularExpression(pattern: "^\\+55\\d{2}9?\\d{8}$", options: []) 36 | private func isValidForBrazilRegistration(phoneNumber: PhoneNumber) -> Bool { 37 | let e164 = phoneNumber.toE164() 38 | return validBrazilPhoneNumberRegex.hasMatch(input: e164) 39 | } 40 | 41 | let validUnitedStatesPhoneNumberRegex = try! NSRegularExpression(pattern: "^\\+1\\d{10}$", options: []) 42 | private func isValidForUnitedStatesRegistration(phoneNumber: PhoneNumber) -> Bool { 43 | let e164 = phoneNumber.toE164() 44 | return validUnitedStatesPhoneNumberRegex.hasMatch(input: e164) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /neontribe-club/session4/agenda-s4.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | - Try to find someone else to take notes. Karl? 4 | - Split into 2 groups for 1st half (either geographical or by coding experience) 5 | - Discuss the independent findings 6 | 7 | ## Reflection (5 mins) 8 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 9 | - Note a time the past 2 weeks when you used information learned about code in your work 10 | 11 | ## Exercises 12 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 13 | 14 | You will need: 15 | - two printed copies of the code for today's club 16 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 17 | - coloured pens, crayons or pencils 18 | 19 | ### Interaction with code (10 mins) 20 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 21 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 22 | 1. Colour3 the classes - circle and draw links between classes and their instances 23 | 1. Draw the indentaiton patterns - There are a few ways to do this. Fill over with black sharpie. Trace on graph paper. Trace on acetate. etc? 24 | 25 | #### Discuss the results (10 mins) 26 | 1. What patterns are visible from the colors and indentations only? 27 | 1. What parts of the code warrant more attention based on the colors and indentation? 28 | 29 | ### Content 30 | 31 | #### Identify (10 mins) 32 | 1. Define what it means to be important and independently identify the 5 lines you consider most important 33 | 1. Discuss in the group: 34 | - lines covered by many people? 35 | - lines named but not by a lot of people 36 | - Agree less than 10 of the most important lines 37 | 38 | #### Discuss (10 mins) 39 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 40 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 41 | 42 | #### Summarize in less than 10 sentences (10 mins) 43 | 1. Independently write down the essence of the code in a few sentences 44 | 1. Discuss in the group 45 | - topics covered by many vs few 46 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 47 | 1. Create a summary together 48 | 1. Compare the summary with the available documentation (inside and outside the code) 49 | - identify differences and similarities between the groups findings and the existing 50 | 51 | 52 | ## Wash up (5 mins) 53 | - What worked well 54 | - What worked badly 55 | 56 | ## Follow up (2 weeks of elapsed time) 57 | - Identify code for next session, keaping in mind Wash up and Reflection information 58 | 59 | 60 | -------------------------------------------------------------------------------- /neontribe-club/session4/neontribe_code_reading_club_session_4_notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session4/neontribe_code_reading_club_session_4_notes.pdf -------------------------------------------------------------------------------- /neontribe-club/session4/neontribe_code_reading_club_session_4_notes.txt: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf2511 2 | \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;\red5\green61\blue204;\red251\green2\blue255;\red0\green0\blue0; 4 | \red102\green0\blue141;} 5 | {\*\expandedcolortbl;;\cssrgb\c0\c33896\c83855;\cssrgb\c100000\c25279\c100000;\cssrgb\c0\c0\c0; 6 | \cssrgb\c48169\c12809\c62212;} 7 | {\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{hyphen\}}{\leveltext\leveltemplateid2\'01\uc0\u8259 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid1} 8 | {\list\listtemplateid2\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid101\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{hyphen\}}{\leveltext\leveltemplateid102\'01\uc0\u8259 ;}{\levelnumbers;}\fi-360\li1440\lin1440 }{\listname ;}\listid2}} 9 | {\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}} 10 | \paperw11900\paperh16840\margl1440\margr1440\vieww21120\viewh21300\viewkind0 11 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 12 | 13 | \f0\b\fs32 \cf0 Session 4 14 | \f1\b0\fs24 \ 15 | 16 | \fs28 \ul Number of participants: 8\ 17 | Code sample language: Swift\ 18 | 19 | \fs24 \ulnone \ 20 | 21 | \fs26 \ul Reflection 22 | \fs24 \ulnone \ 23 | -> not in work, but talking about/promoting the idea of reading code to other developers who acknowledged that is a great initiative\ 24 | -> making my comments less noisy - not new but a visual reminder of what that can do to a codebase\ 25 | -> thinking about a problem I was facing - and I found myself thinking if navigating the whole code base not just a snippet could be useful (e.g. a small application, regardless of the language)\ 26 | -> doing refactoring by looking at the core functionality - similar to the exercise where we identify the the most important lines of code\ 27 | \ 28 | 29 | \fs26 \ul Interaction with code 30 | \fs24 \ulnone \ 31 | - interaction with code - the more experienced devs recognised what this file is about\ 32 | - colouring - some people are not that invested \ 33 | - colouring for others helps clarify the code, make it less fuzzy and draw connections\ 34 | - difference between function and method -> code that warrants more attention\ 35 | - helpful if we can discuss what this code does first before we delve into dissecting it\ 36 | \ 37 | 38 | \fs26 \ul Content 39 | \fs24 \ulnone \ 40 | - lines covered by many people (line - number of people who selected that): \ 41 | \pard\tx940\tx1440\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li1440\fi-1440\pardirnatural\partightenfactor0 42 | \ls1\ilvl1\cf0 {\listtext \uc0\u8259 }8 - 4\ 43 | {\listtext \uc0\u8259 }17 - 4\ 44 | {\listtext \uc0\u8259 }18 - 4\ 45 | {\listtext \uc0\u8259 } 46 | \f0\b\fs28 \cf2 22 - 5 47 | \f1\b0\fs24 \cf0 \ 48 | {\listtext \uc0\u8259 }27 - 4\ 49 | {\listtext \uc0\u8259 } 50 | \f0\b\fs28 \cf3 5 - 1 51 | \fs24 \ 52 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 53 | \cf4 The most important lines: agreed that those covered by many people - 22, 8, 17, 18, and 27 - are the most important ones. \ 54 | \ 55 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 56 | 57 | \f1\b0\fs26 \cf0 \ul \ulc0 Content discussion 58 | \fs24 \ulnone \ 59 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 60 | \cf0 - line 24 - any case that is not Brazil or US - (why are these so special and why are other countries phone number not validated)?\ 61 | - this is code from he Signal messenger app - {\field{\*\fldinst{HYPERLINK "https://signal.org"}}{\fldrslt https://signal.org}} - and that fact that is so well encrypted makes it widely used by those attending public protests\ 62 | - so it might be that these lines are meant to filter out phone numbers from US and Brazil for further encryption/protection against tracking? \ 63 | \ 64 | - line 18 elicits a discussion - what it does, construct - 65 | \f0\b \cf5 \expnd0\expndtw0\kerning0 66 | \outl0\strokewidth0 \strokec4 guard let countryCode = phoneNumber.getCountryCode() else \{return false\} 67 | \f1\b0 \cf0 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 \ 68 | - enums are very useful - analogy with code in games\ 69 | \ 70 | 71 | \fs26 \ul Summary\ 72 | 73 | \fs24 \ulnone - skipped to save time \ 74 | - Uint - data type declaration (unsigned integer)\ 75 | \ 76 | 77 | \fs26 \ul Wash up 78 | \fs24 \ulnone \ 79 | \pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\pardirnatural\partightenfactor0 80 | \ls2\ilvl0\cf0 {\listtext 1. }What worked well \ 81 | \pard\tx940\tx1440\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li1440\fi-1440\pardirnatural\partightenfactor0 82 | \ls2\ilvl1\cf0 {\listtext \uc0\u8259 }good, clean piece of code, as every week we look at different code (language wise) \ 83 | {\listtext \uc0\u8259 }seemingly simple lines of code but more challenging than thought\ 84 | {\listtext \uc0\u8259 }reflection brought up quite a few uses about the information/techniques learned from previous sessions\ 85 | \pard\tx220\tx720\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li720\fi-720\pardirnatural\partightenfactor0 86 | \ls2\ilvl0\cf0 {\listtext 2. }What worked badly\ 87 | \pard\tx940\tx1440\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li1440\fi-1440\pardirnatural\partightenfactor0 88 | \ls2\ilvl1\cf0 {\listtext \uc0\u8259 }didn\'92t stick to the agenda and we tend to spend more time on certain parts (perhaps this tells us something about the group dynamic and maybe the agenda should be tailored to meet the group\'92s needs?); \ 89 | {\listtext \uc0\u8259 }for beginners, some technical chat between more experienced developers was confusing/difficult to follow especially when not indicating the number of the code line in reference\ 90 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 91 | \cf0 \ 92 | 93 | \fs26 \ul Follow up\ 94 | \ulnone - Charlie volunteered to supply next session\'92s code samples} -------------------------------------------------------------------------------- /neontribe-club/session5/agenda-s5.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | - Try to find someone else to take notes. Karl? 4 | - Split into 2 groups for 1st half (either geographical or by coding experience) 5 | - Discuss the independent findings 6 | 7 | ## Reflection (5 mins) 8 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 9 | - Note a time the past 2 weeks when you used information learned about code in your work 10 | 11 | ## Exercises 12 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 13 | 14 | You will need: 15 | - two printed copies of the code for today's club 16 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 17 | - coloured pens, crayons or pencils 18 | 19 | ### Interaction with code (10 mins) 20 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 21 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 22 | 1. Colour3 the classes - circle and draw links between classes and their instances 23 | 1. Draw the indentaiton patterns - There are a few ways to do this. Fill over with black sharpie. Trace on graph paper. Trace on acetate. etc? 24 | 25 | #### Discuss the results (10 mins) 26 | 1. What patterns are visible from the colors and indentations only? 27 | 1. What parts of the code warrant more attention based on the colors and indentation? 28 | 29 | ### Content 30 | 31 | #### Identify (10 mins) 32 | 1. Define what it means to be important and independently identify the 5 lines you consider most important 33 | 1. Discuss in the group: 34 | - lines covered by many people? 35 | - lines named but not by a lot of people 36 | - Agree less than 10 of the most important lines 37 | 38 | #### Discuss (10 mins) 39 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 40 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 41 | 42 | #### Summarize in less than 10 sentences (10 mins) 43 | 1. Independently write down the essence of the code in a few sentences 44 | 1. Discuss in the group 45 | - topics covered by many vs few 46 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 47 | 1. Create a summary together 48 | 1. Compare the summary with the available documentation (inside and outside the code) 49 | - identify differences and similarities between the groups findings and the existing 50 | 51 | 52 | ## Wash up (5 mins) 53 | - What worked well 54 | - What worked badly 55 | 56 | ## Follow up (2 weeks of elapsed time) 57 | - Identify code for next session, keaping in mind Wash up and Reflection information 58 | 59 | 60 | -------------------------------------------------------------------------------- /neontribe-club/session5/completedExercises/code-club-5-marked.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session5/completedExercises/code-club-5-marked.jpg -------------------------------------------------------------------------------- /neontribe-club/session5/completedExercises/code-club-5-marked2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session5/completedExercises/code-club-5-marked2.jpg -------------------------------------------------------------------------------- /neontribe-club/session5/ssh_key.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 | # Copyright (c) 2017 Mozilla Corporation 7 | 8 | from lib.alerttask import AlertTask 9 | from mozdef_util.query_models import SearchQuery, TermMatch 10 | import re 11 | import os 12 | 13 | # This alert consumes data produced by the MIG sshkey module and mig-runner. 14 | # ssh key related events are compared against a whitelist which is the 15 | # alerts configuration file (sshkey.conf). The format of this whitelist 16 | # is as follows: 17 | # 18 | # 19 | # 20 | # If a host matches the regex, and the detected key matches the path, the 21 | # alert will not generate an alert event. If the detected key is not in 22 | # the whitelist, an alert will be created. 23 | 24 | 25 | class SSHKey(AlertTask): 26 | def __init__(self): 27 | # _whitelist contains all whitelisted key paths, loaded from the 28 | # configuration file for the alert plugin 29 | self._whitelist = [] 30 | 31 | AlertTask.__init__(self) 32 | self._parse_whitelist('ssh_key.conf') 33 | 34 | def main(self): 35 | search_query = SearchQuery(minutes=30) 36 | 37 | search_query.add_must([ 38 | TermMatch('category', 'event'), 39 | TermMatch('tags', 'mig-runner-sshkey') 40 | ]) 41 | 42 | self.filtersManual(search_query) 43 | 44 | self.searchEventsSimple() 45 | self.walkEvents() 46 | 47 | # Load whitelist from file system and store in object, path specifies the 48 | # path to load the whitelist from 49 | def _parse_whitelist(self, path): 50 | full_config_filename = os.path.join(os.path.dirname(__file__), path) 51 | with open(full_config_filename) as fd: 52 | lns = [x.strip() for x in fd.readlines()] 53 | for entry in lns: 54 | try: 55 | pindex = entry.index(' ') 56 | except ValueError: 57 | continue 58 | self._whitelist.append({ 59 | 'hostre': entry[:pindex], 60 | 'path': entry[pindex + 1:] 61 | }) 62 | 63 | # Return false if the key path is present in the whitelist, otherwise return 64 | # true 65 | def _whitelist_check(self, hostname, privkey): 66 | for went in self._whitelist: 67 | try: 68 | rem = re.compile(went['hostre']) 69 | except: 70 | continue 71 | if rem.match(hostname) is None: 72 | continue 73 | if privkey['path'] == went['path']: 74 | return False 75 | return True 76 | 77 | def onEvent(self, event): 78 | # Each event could potentially contain a number of identified private keys, since 79 | # mig-runner will send an event per host. Compare the private keys in the event 80 | # to the keys in the whitelist, if any are missing from the whitelist we will include 81 | # the paths in an alert and return the alert, otherwise no alert is returned. 82 | ev = event['_source'] 83 | 84 | if 'details' not in ev: 85 | return None 86 | if 'private' not in ev['details'] or 'agent' not in ev['details']: 87 | return None 88 | hostname = ev['details']['agent'] 89 | alertkeys = [x for x in ev['details']['private'] if self._whitelist_check(hostname, x)] 90 | if len(alertkeys) == 0: 91 | return None 92 | 93 | category = 'sshkey' 94 | tags = ['sshkey'] 95 | severity = 'WARNING' 96 | summary = 'Private keys detected on {} missing from whitelist'.format(hostname) 97 | ret = self.createAlertDict(summary, category, tags, [event], severity) 98 | ret['details'] = { 99 | 'private': alertkeys 100 | } 101 | return ret -------------------------------------------------------------------------------- /neontribe-club/session6/agenda-s6.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | - Try to find someone else to take notes. Karl? 4 | - Split into 2 groups for 1st half (either geographical or by coding experience) 5 | - Discuss the independent findings 6 | 7 | ## Reflection (5 mins) 8 | - Note a time the past 2 weeks when you used one of the techniques from the club in your work 9 | - Note a time the past 2 weeks when you used information learned about code in your work 10 | 11 | ## Exercises 12 | At the start everyone should look at the same code, but as the club evolves you can tackle a bigger bit of code by splitting into sections. These exercises are best carried out when the code can fit on one or two pages but with it being the norm to split in many ways - we hope to invent and discover different exercises. 13 | 14 | You will need: 15 | - two printed copies of the code for today's club 16 | - some graph paper - or coloured paper and scissors - or acetate and something to write on it with 17 | - coloured pens, crayons or pencils 18 | 19 | ### Interaction with code (10 mins) 20 | 1. Colour1 the variables - circle and draw links between instatiation and all uses 21 | 1. Colour2 the method/ function calls - circle and draw links between declarations and calls 22 | 1. Colour3 the classes - circle and draw links between classes and their instances 23 | 1. Draw the indentaiton patterns - There are a few ways to do this. Fill over with black sharpie. Trace on graph paper. Trace on acetate. etc? 24 | 25 | #### Discuss the results (10 mins) 26 | 1. What patterns are visible from the colors and indentations only? 27 | 1. What parts of the code warrant more attention based on the colors and indentation? 28 | 29 | ### Content 30 | 31 | #### Identify (10 mins) 32 | 1. Define what it means to be important and independently identify the 5 lines you consider most important 33 | 1. Discuss in the group: 34 | - lines covered by many people? 35 | - lines named but not by a lot of people 36 | - Agree less than 10 of the most important lines 37 | 38 | #### Discuss (10 mins) 39 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 40 | [Save the last word for me protocol](https://lead.nwp.org/knowledgebase/save-the-last-word-for-me-protocol/) 41 | 42 | #### Summarize in less than 10 sentences (10 mins) 43 | 1. Independently write down the essence of the code in a few sentences 44 | 1. Discuss in the group 45 | - topics covered by many vs few 46 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 47 | 1. Create a summary together 48 | 1. Compare the summary with the available documentation (inside and outside the code) 49 | - identify differences and similarities between the groups findings and the existing 50 | 51 | 52 | ## Wash up (5 mins) 53 | - What worked well 54 | - What worked badly 55 | 56 | ## Follow up (2 weeks of elapsed time) 57 | - Identify code for next session, keaping in mind Wash up and Reflection information 58 | -------------------------------------------------------------------------------- /neontribe-club/session6/completedExercises/code-sample-marked-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session6/completedExercises/code-sample-marked-1.jpg -------------------------------------------------------------------------------- /neontribe-club/session6/completedExercises/code-sample-marked-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session6/completedExercises/code-sample-marked-2.jpg -------------------------------------------------------------------------------- /neontribe-club/session6/example_code.html.haml: -------------------------------------------------------------------------------- 1 | .icon-bar.seven-up 2 | = link_to edit_admin_workshop_path(@workshop), class: 'item' do 3 | %i.fa.fa-pencil 4 | %label Edit 5 | - if !@workshop.date_and_time.future? 6 | = link_to '#', class: 'item disabled', title: 'The event has already taken place' do 7 | %i.fa.fa-send-o 8 | %label Invite 9 | - elsif (@workshop.has_valid_host? || @workshop.virtual?) and @workshop.invitable? 10 | = link_to admin_workshop_send_invites_path(@workshop), class: 'item' do 11 | %i.fa.fa-send-o 12 | %label Invite 13 | - else 14 | = link_to '#', class: 'item disabled', title: t('admin.workshop.not_invitable.') do 15 | %i.fa.fa-send-o 16 | %label Invite 17 | = link_to admin_workshop_path(format: 'csv'), class: 'item', title: 'CSV for pairing' do 18 | %i.fa.fa-users 19 | %label Pairing CSV 20 | = link_to admin_workshop_path(type: 'labels', format: 'csv'), class: 'item', title: 'CSV for labels' do 21 | %i.fa.fa-users 22 | %label Labels 23 | = link_to admin_workshop_attendees_checklist_path(@workshop, format: 'text'), title: 'Attendee checklist', class: 'item' do 24 | %i.fa.fa-list-ul 25 | %label Attendees 26 | = link_to admin_workshop_attendees_emails_path(@workshop, format: 'text'), title: 'Attendee emails', class: 'item' do 27 | %i.fa.fa-at 28 | %label Emails 29 | = link_to admin_workshop_path(@workshop), method: :delete, data: { confirm: 'Are you sure you want to delete this workshop?' }, title: 'Destroy workshop', class: 'item' do 30 | %i.fa.fa-remove 31 | %label Destroy 32 | 33 | 34 | %section 35 | .stripe.reverse 36 | .row 37 | .medium-12.columns 38 | %h2 39 | = @workshop.to_s 40 | = link_to [:admin, @workshop.chapter] do 41 | %small=@workshop.chapter.name 42 | %h3 43 | %small #{l(@workshop.date_and_time, format: :dashboard)} #{@workshop.start_and_end_time} 44 | - if @workshop.rsvp_opens_at 45 | RSVPs will open at 46 | = @workshop.rsvp_opens_at.strftime('%H:%M on %d/%m/%Y.') 47 | %br 48 | %br 49 | - if @workshop.venue.present? || @workshop.virtual? 50 | %strong.label.round.primary #{@workshop.student_spaces} student spots, #{@workshop.coach_spaces} coach spots 51 | - unless @workshop.spaces? 52 | %label.label.round.warning Full 53 | - if !@workshop.invitable? 54 | %br 55 | %p 56 | %label.label.info= t('admin.workshop.not_invitable') 57 | %p.description 58 | %br 59 | = sanitize(@workshop.description) 60 | - if @workshop.virtual? 61 | .row 62 | .large-12.small-6.columns#slack-details 63 | .panel.callout 64 | %h5= t('admin.workshop.virtual.details.title') 65 | %p 66 | %strong="#{t('admin.workshop.virtual.details.slack')}:" 67 | #{link_to("##{@workshop.slack_channel}", @workshop.slack_channel_link)} 68 | %br 69 | %strong="#{t('admin.workshop.virtual.details.discord')}:" 70 | #{link_to(t('social_media_links.discord_invitation'), t('social_media_links.discord_invitation'))} 71 | %br 72 | %br 73 | #{t('admin.workshop.virtual.details.more_html', slack_channel: link_to('#organisers', 'https://codebar.slack.com/archives/G08CQ5KFD'))} 74 | 75 | %br 76 | .row 77 | .large-3.small-6.columns#host 78 | - if @workshop.venue.present? 79 | %h4 Venue 80 | %strong= @workshop.venue.name 81 | %br 82 | %small= @workshop.address.to_html 83 | .large-3.small-6.columns#sponsors 84 | - if (@workshop.sponsors - [@workshop.host]).any? 85 | %h4 Sponsors 86 | %ul.no-bullet 87 | - (@workshop.sponsors - [@workshop.host]).each do |sponsor| 88 | %li 89 | %span 90 | = link_to sponsor.name, [:admin, sponsor] 91 | .large-6.small-12.columns 92 | %h4 Team 93 | - @workshop.organisers.each do |organiser| 94 | %span.has-tip{ 'data-tooltip': '', 'aria-haspopup': 'true', title: organiser.full_name } 95 | = image_tag(organiser.avatar(40), alt: organiser.full_name) 96 | 97 | .stripe.reverse#invitations 98 | = render partial: 'invitation_management' 99 | -------------------------------------------------------------------------------- /neontribe-club/session6/washup: -------------------------------------------------------------------------------- 1 | ## Good 2 | - Interesting code choice, challenged more experienced developers! 3 | 4 | ## Bad 5 | - time :-( we always overrun 6 | 7 | ## Ugly 8 | - no printer! need to have a section on diigtal marking and colouring code 9 | -------------------------------------------------------------------------------- /neontribe-club/session7/Example.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityStandardAssets.CrossPlatformInput; 4 | 5 | namespace UnityStandardAssets.Characters.ThirdPerson 6 | { 7 | [RequireComponent(typeof (ThirdPersonCharacter))] 8 | public class ThirdPersonUserControl : MonoBehaviour 9 | { 10 | private ThirdPersonCharacter m_Character; // A reference to the ThirdPersonCharacter on the object 11 | private Transform m_Cam; // A reference to the main camera in the scenes transform 12 | private Vector3 m_CamForward; // The current forward direction of the camera 13 | private Vector3 m_Move; 14 | private bool m_Jump; // the world-relative desired move direction, calculated from the camForward and user input. 15 | 16 | 17 | private void Start() 18 | { 19 | // get the transform of the main camera 20 | if (Camera.main != null) 21 | { 22 | m_Cam = Camera.main.transform; 23 | } 24 | else 25 | { 26 | Debug.LogWarning( 27 | "Warning: no main camera found. Third person character needs a Camera tagged \"MainCamera\", for camera-relative controls.", gameObject); 28 | // we use self-relative controls in this case, which probably isn't what the user wants, but hey, we warned them! 29 | } 30 | 31 | // get the third person character ( this should never be null due to require component ) 32 | m_Character = GetComponent(); 33 | } 34 | 35 | 36 | private void Update() 37 | { 38 | if (!m_Jump) 39 | { 40 | m_Jump = CrossPlatformInputManager.GetButtonDown("Jump"); 41 | } 42 | } 43 | 44 | 45 | // Fixed update is called in sync with physics 46 | private void FixedUpdate() 47 | { 48 | // read inputs 49 | float h = CrossPlatformInputManager.GetAxis("Horizontal"); 50 | float v = CrossPlatformInputManager.GetAxis("Vertical"); 51 | bool crouch = Input.GetKey(KeyCode.C); 52 | 53 | // calculate move direction to pass to character 54 | if (m_Cam != null) 55 | { 56 | // calculate camera relative direction to move: 57 | m_CamForward = Vector3.Scale(m_Cam.forward, new Vector3(1, 0, 1)).normalized; 58 | m_Move = v*m_CamForward + h*m_Cam.right; 59 | } 60 | else 61 | { 62 | // we use world-relative directions in the case of no main camera 63 | m_Move = v*Vector3.forward + h*Vector3.right; 64 | } 65 | #if !MOBILE_INPUT 66 | // walk speed multiplier 67 | if (Input.GetKey(KeyCode.LeftShift)) m_Move *= 0.5f; 68 | #endif 69 | 70 | // pass all parameters to the character control script 71 | m_Character.Move(m_Move, crouch, m_Jump); 72 | m_Jump = false; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /neontribe-club/session7/agenda-s7.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ### Reflection (5 mins) 4 | 5 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 6 | 7 | ## Code structure 8 | 9 | ### First glance 10 | 11 | The goal of this exercise is to practice to get a first impression of code and to act upon that. 12 | 13 | #### Look at the code (1 min) 14 | 15 | Look at the code at a glance, really not more than 1 minute. Then try to answer these questions: 16 | 17 | - What is the first thing that catches your eye? Why is that? 18 | 19 | - What is the *second* think that you see? Why? 20 | 21 | - Are these two things (variables, classes, programming concepts) related? 22 | 23 | #### Discuss the results (5 mins) 24 | 25 | Discuss the results as a group. What lines of facts or concepts were chosen by everyone versus by only a few people? 26 | 27 | Reflect also on what kind of knowledge did you use in this exercise? Knowledge of the domain, of the programming language? Of a framework? What knowledge do you think might be needed to better understand this code? 28 | 29 | 30 | ### Examine structure (10 mins) 31 | The goal of this exercise is to be a concrete thing to *do* when looking at new code for the first time. New code can be scary, doing something will help! 32 | 33 | Color variables 34 | 35 | * Go through the code and circle all variables in red 36 | * Then draw a link between variables and their uses 37 | 38 | Color method/function calls 39 | 40 | * Go through the code and circle all methods in blue 41 | * Then draw a link between methods and their invocations 42 | 43 | Instantiation 44 | 45 | * Go through the code and circle all instances of classes in green 46 | * Then draw a link between classes and their instances 47 | 48 | #### Discuss the results (10 mins) 49 | 1. What patterns are visible from the colors and links only? 50 | 1. What parts of the code warrant more attention based on the colors? 51 | 1. What strategy did you use to identify the different types of element? 52 | 53 | ## Content 54 | 55 | ### All variable/class/method names (5 mins) 56 | 57 | Go through the code mechanically and create a list of all identifier names in the snippet. Of you have done the "examine structure" exercise before, this should be relatively quick and easy. 58 | 59 | #### Discussion (5 mins) 60 | 61 | Discuss in the group: 62 | 63 | - What can we learn from these names? 64 | - Which names are related to each other, from the names only? 65 | - Are there names that are ambiguous when looked at without context? 66 | 67 | ### Identify most important lines (5 mins) 68 | Independently identify the 5 lines you consider most important. 69 | 70 | #### Discussion (10 mins) 71 | Discuss in the group: 72 | 73 | - lines covered by many people? 74 | - lines named but not by a lot of people 75 | - What strategy did you use to identify importance? 76 | - Agree less than 10 of the most important lines 77 | 78 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 79 | 80 | #### Summarize in less than 10 sentences individually (5 mins) 81 | 82 | 1. Independently write down the essence of the code in a few sentences 83 | 84 | #### Discussion (10 mins) 85 | 86 | - topics covered by many vs few 87 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 88 | 89 | #### Summarize in less than 10 sentences (5 mins) 90 | 91 | 1. Create a summary together 92 | 1. Compare the summary with the available documentation (inside and outside the code) 93 | 94 | - identify differences and similarities between the groups findings and the existing 95 | 96 | ## Wash up (5 mins) 97 | 98 | - What worked well 99 | - What worked badly 100 | -------------------------------------------------------------------------------- /neontribe-club/session8/Example.rs: -------------------------------------------------------------------------------- 1 | //! # Bump frame allocator 2 | //! Some code was borrowed from [Phil Opp's Blog](http://os.phil-opp.com/allocating-frames.html) 3 | 4 | use crate::paging::PhysicalAddress; 5 | 6 | use super::{Frame, FrameAllocator, MemoryArea, MemoryAreaIter}; 7 | 8 | 9 | pub struct BumpAllocator { 10 | next_free_frame: Frame, 11 | current_area: Option<&'static MemoryArea>, 12 | areas: MemoryAreaIter, 13 | kernel_start: Frame, 14 | kernel_end: Frame 15 | } 16 | 17 | impl BumpAllocator { 18 | pub fn new(kernel_start: usize, kernel_end: usize, memory_areas: MemoryAreaIter) -> Self { 19 | let mut allocator = Self { 20 | next_free_frame: Frame::containing_address(PhysicalAddress::new(0)), 21 | current_area: None, 22 | areas: memory_areas, 23 | kernel_start: Frame::containing_address(PhysicalAddress::new(kernel_start)), 24 | kernel_end: Frame::containing_address(PhysicalAddress::new(kernel_end)) 25 | }; 26 | allocator.choose_next_area(); 27 | allocator 28 | } 29 | 30 | fn choose_next_area(&mut self) { 31 | self.current_area = self.areas.clone().filter(|area| { 32 | let address = area.base_addr + area.length - 1; 33 | Frame::containing_address(PhysicalAddress::new(address as usize)) >= self.next_free_frame 34 | }).min_by_key(|area| area.base_addr); 35 | 36 | if let Some(area) = self.current_area { 37 | let start_frame = Frame::containing_address(PhysicalAddress::new(area.base_addr as usize)); 38 | if self.next_free_frame < start_frame { 39 | self.next_free_frame = start_frame; 40 | } 41 | } 42 | } 43 | } 44 | 45 | impl FrameAllocator for BumpAllocator { 46 | #[allow(unused)] 47 | fn set_noncore(&mut self, noncore: bool) {} 48 | 49 | fn free_frames(&self) -> usize { 50 | let mut count = 0; 51 | 52 | for area in self.areas.clone() { 53 | let start_frame = Frame::containing_address(PhysicalAddress::new(area.base_addr as usize)); 54 | let end_frame = Frame::containing_address(PhysicalAddress::new((area.base_addr + area.length - 1) as usize)); 55 | for frame in Frame::range_inclusive(start_frame, end_frame) { 56 | if frame >= self.kernel_start && frame <= self.kernel_end { 57 | // Inside of kernel range 58 | } else if frame >= self.next_free_frame { 59 | // Frame is in free range 60 | count += 1; 61 | } else { 62 | // Inside of used range 63 | } 64 | } 65 | } 66 | 67 | count 68 | } 69 | 70 | fn used_frames(&self) -> usize { 71 | let mut count = 0; 72 | 73 | for area in self.areas.clone() { 74 | let start_frame = Frame::containing_address(PhysicalAddress::new(area.base_addr as usize)); 75 | let end_frame = Frame::containing_address(PhysicalAddress::new((area.base_addr + area.length - 1) as usize)); 76 | for frame in Frame::range_inclusive(start_frame, end_frame) { 77 | if frame >= self.kernel_start && frame <= self.kernel_end { 78 | // Inside of kernel range 79 | count += 1 80 | } else if frame >= self.next_free_frame { 81 | // Frame is in free range 82 | } else { 83 | count += 1; 84 | } 85 | } 86 | } 87 | 88 | count 89 | } 90 | 91 | fn allocate_frames(&mut self, count: usize) -> Option { 92 | if count == 0 { 93 | None 94 | } else if let Some(area) = self.current_area { 95 | // "Clone" the frame to return it if it's free. Frame doesn't 96 | // implement Clone, but we can construct an identical frame. 97 | let start_frame = Frame{ number: self.next_free_frame.number }; 98 | let end_frame = Frame { number: self.next_free_frame.number + (count - 1) }; 99 | 100 | // the last frame of the current area 101 | let current_area_last_frame = { 102 | let address = area.base_addr + area.length - 1; 103 | Frame::containing_address(PhysicalAddress::new(address as usize)) 104 | }; 105 | 106 | if end_frame > current_area_last_frame { 107 | // all frames of current area are used, switch to next area 108 | self.choose_next_area(); 109 | } else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end) 110 | || (end_frame >= self.kernel_start && end_frame <= self.kernel_end) { 111 | // `frame` is used by the kernel 112 | self.next_free_frame = Frame { 113 | number: self.kernel_end.number + 1 114 | }; 115 | } else { 116 | // frame is unused, increment `next_free_frame` and return it 117 | self.next_free_frame.number += count; 118 | return Some(start_frame); 119 | } 120 | // `frame` was not valid, try it again with the updated `next_free_frame` 121 | self.allocate_frames(count) 122 | } else { 123 | None // no free frames left 124 | } 125 | } 126 | 127 | fn deallocate_frames(&mut self, _frame: Frame, _count: usize) { 128 | //panic!("BumpAllocator::deallocate_frame: not supported: {:?}", frame); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /neontribe-club/session8/Notes.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club Session Notes 2 | 3 | ## Intro: Reflection 4 | ### Has code reading club has helped you in your other projects or conversations? 5 | Not much except from suggesting to a colleague to join the Club due to his practise. 6 | 7 | ## Exercise 1: First glance 8 | ### Look at the code and discuss 9 | 10 | A piece of prep code. 11 | It looks like an object orientated code due to the existence of classes or objects, functions, constructors. 12 | Using familiarity, only one participant guessed it was Rust. 13 | One participant acknowledged that the bump was allocated twice (defined, implemented) which appeared to be important as the frame allocator was imported for the bump allocator. 14 | 15 | ## Exercise 2: Examine the structure 16 | ### Highlight the code and discuss 17 | 18 | - Due to the tool (Miro) some participants struggled to finish the exercise. 19 | - The code seems to consist only of 5 functions but each reference something. 20 | - It is a dynamically constructed object. 21 | - Lots of static things. 22 | - Some participants started the exercise by trying to find variables by looking for keywords. 23 | - It seems it contains a lot of variables. 24 | - Classes seem to be called similar way as PHP with double colon. 25 | - Functions are interesting due to the way they are being called which is inside of themselves. 26 | - For one participant there was not enough time to understand what the code was doing. 27 | - The code has been described by all as “very wordy”. 28 | 29 | ## Exercise 3: Most important lines 30 | ### Identify the most important lines of the code 31 | 32 | Easy agreement on the following lines: 33 | 9 34 | 18 35 | 45 36 | 56 (bounce check of line 55’s validity) 37 | 91 38 | 128 (Comment. If it were to be present in a parent it would mean don’t do anything if you are in panic) 39 | 40 | ### Summarize in less than 10 sentences the essence of the code 41 | Memory allocation. Bump allocator defines how to choose next physical memory area. Frame allocator has functions to help the bump allocator find & make areas it can use. 42 | 43 | ## Wash Up 44 | - Miro – Seems to be a good tool but still is a good tool if we know how to use it 45 | - Layout is good (i.e. each participant has its own frame with its own code sheet and agenda) 46 | - First exercise of glancing the code was pushed to 2min. For one participant it was too long, for another one it was enough. 47 | - For accessibility matter, PDF seems better than Jpeg. 48 | - Facilitator has removed the exercise “create a list of all identifier names in the snippet” due to not knowing how to make it work and ensuring there was time for a wash up. 49 | 50 | ## Code Source 51 | https://gitlab.redox-os.org/redox-os/kernel/-/commit/fe705d9b63173c8e8f31bd6b5bfde8349779df61 52 | -------------------------------------------------------------------------------- /neontribe-club/session8/agenda-s8.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Intro 4 | *{7 min}* 5 | 6 | ### Set up (Facilitator, 2 min) 7 | - Board 8 | - Agenda 9 | 10 | ### Reflection (Group, 5 mins) 11 | *[ 0'50 / 1'00 / 1'25 per person ]* 12 | 13 | - Has code reading club has helped you in your other projects or conversations? 14 | 15 | ## Code structure 16 | *{22 min}* 17 | 18 | ### Exercise 1: First glance (7 min) 19 | 20 | #### Look at the code (Solo, 2 min) 21 | 22 | Look at the code at a glance and try to answer these questions: 23 | 24 | - What is the **first thing** that catches your eye? Why? 25 | - What is the **second thing** that you see? Why? 26 | - Are these two things **related** (variables, classes, programming concepts)? 27 | 28 | #### Discuss the results (Group, 5 mins) 29 | *[ 0'50 / 1'00 / 1'25 per person ]* 30 | 31 | - Everyone vs a few: What lines of facts or concepts were chosen ? 32 | 33 | - What knowledge did you use in this exercise? 34 | 35 | 36 | *Domain, programming language? a framework? What knowledge do you think might be needed to better understand this code?* 37 | 38 | 39 | ### Exercise 2: Examine the structure (15 mins) 40 | 41 | #### Highlight the code (Solo, 5 min) 42 | 43 | * Red for Varibales: Circle and draw links between instatiation and all uses 44 | 45 | * Blue for Method/function calls: Circle and draw links between declarations and calls 46 | 47 | * Green for Classes: Circle and draw links between classes and their instances 48 | 49 | 50 | 51 | #### Discuss the results (Group, 10 mins) 52 | *[ 1'30 / 2'00 / 2'30 per person ]* 53 | 54 | 1. What patterns are visible from the colors and links only? 55 | 2. What parts of the code warrant more attention based on the colors? 56 | 3. What strategy did you use to identify the different types of element? 57 | 58 | ## Content 59 | *{30 min}* 60 | 61 | ### Exercise 3: Most important lines (30 mins) 62 | 63 | #### Identify the most important lines (Solo, 5 mins) 64 | 65 | Independently identify the 5 lines you consider most important. 66 | 67 | #### Discuss the results (Group, 10 mins) 68 | *[ 1'30 / 2'00 / 2'30 per person ]* 69 | 70 | - lines covered by many people? 71 | - lines named but not by a lot of people 72 | - What strategy did you use to identify importance? 73 | - Agree less than 10 of the most important lines 74 | 75 | 76 | #### Summarize in less than 10 sentences (Solo, 5 mins) 77 | 78 | Independently write down the essence of the code in a few sentences 79 | 80 | #### Discuss the results (Group, 10 mins) 81 | *[ 1'30 / 2'00 / 2'30 per person ]* 82 | 83 | - topics covered by many vs few 84 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 85 | 86 | #### Summarize in less than 10 sentences (Group, 5 mins) 87 | *[ 0'50 / 1'00 / 1'25 per person ]* 88 | 89 | 1. Create a summary together 90 | 2. Compare the summary with the available documentation (inside and outside the code) 91 | 92 | 3. identify differences and similarities between the groups findings and the existing 93 | 94 | ## Wash up (16 mins) 95 | 96 | - What worked well 97 | - What worked badly 98 | -------------------------------------------------------------------------------- /neontribe-club/session8/example_code.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session8/example_code.pdf -------------------------------------------------------------------------------- /neontribe-club/session8/example_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/session8/example_code.png -------------------------------------------------------------------------------- /neontribe-club/sessionX/agenda-s10.md: -------------------------------------------------------------------------------- 1 | # Code Reading Club agenda 2 | 3 | ## Reflection (4 mins) 4 | 5 | - Between sessions, note times when you notice that code reading club has helped you in your other projects or conversations. 6 | 7 | ## First glance (6 minutes) 8 | 9 | The goal of this exercise is to practice to get a first impression of code and to act upon that. 10 | 11 | ### Look at the code (1 min) 12 | 13 | Look at the code at a glance, really not more than 1 minute. Then try to answer these questions: 14 | 15 | - What is the first thing that catches your eye? Why is that? 16 | 17 | - What is the *second* think that you see? Why? 18 | 19 | - Are these two things (variables, classes, programming concepts) related? 20 | 21 | ### Discuss the results (5 mins) 22 | 23 | Discuss the results as a group. What lines of facts or concepts were chosen by everyone versus by only a few people? 24 | 25 | Reflect also on what kind of knowledge did you use in this exercise? Knowledge of the domain, of the programming language? Of a framework? What knowledge do you think might be needed to better understand this code? 26 | 27 | ## Code structure (20 minutes) 28 | 29 | ### Examine structure (10 minutes) 30 | The goal of this exercise is to be a concrete thing to *do* when looking at new code for the first time. New code can be scary, doing something will help! 31 | 32 | Color variables 33 | 34 | * Go through the code and circle all variables in red 35 | * Then draw a link between variables and their uses 36 | 37 | Color method/function calls 38 | 39 | * Go through the code and circle all methods in blue 40 | * Then draw a link between methods and their invocations 41 | 42 | Instantiation 43 | 44 | * Go through the code and circle all instances of classes in green 45 | * Then draw a link between classes and their instances 46 | 47 | ### Discuss the results (10 mins) 48 | 1. What patterns are visible from the colors and links only? 49 | 1. What parts of the code warrant more attention based on the colors? 50 | 1. What strategy did you use to identify the different types of element? 51 | 52 | ## Content (30 minutes) 53 | 54 | ### A random line (5 mins) 55 | 56 | Select a random line from the code in whatever way you like. Examine this line individually. What is the main idea of this line? What lines does it relate to and why? 57 | 58 | ### Discussion (10 mins) 59 | 60 | Discuss in the group: 61 | 62 | * What is the 'scope' of the random line? What part of the code was seen as related? 63 | * How does the line fit into the rest of the code base? 64 | 65 | ### Identify most important lines (5 mins) 66 | Independently identify the 5 lines you consider most important. 67 | 68 | #### Discussion (10 mins) 69 | Discuss in the group: 70 | 71 | - lines covered by many people? 72 | - lines named but not by a lot of people 73 | - What strategy did you use to identify importance? 74 | - Agree less than 10 of the most important lines 75 | 76 | Take turns in the group, and let every member talk about the code for 30 seconds (or less/more, could also be one sentence each). Try to add new information and not repeat things that have been said, and repeat until people do not know new things anymore. 77 | 78 | ## Summary (15 minutes) 79 | 80 | ### Summarize in less than 10 sentences individually (5 mins) 81 | 82 | 1. Independently write down the essence of the code in a few sentences 83 | 84 | ### Discussion (10 mins) 85 | 86 | - topics covered by many vs few 87 | - strategies used to create the summary (e.g. method names, documentation, variable names, prior knowledge of system) 88 | 89 | ### Summarize in less than 10 sentences (5 mins) 90 | 91 | 1. Create a summary together 92 | 1. Compare the summary with the available documentation (inside and outside the code) 93 | 94 | - identify differences and similarities between the groups findings and the existing 95 | 96 | ## Wash up (5 mins) 97 | 98 | - What worked well 99 | - What worked badly 100 | -------------------------------------------------------------------------------- /neontribe-club/sessionX/agenda_s10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/sessionX/agenda_s10.pdf -------------------------------------------------------------------------------- /neontribe-club/sessionX/code_sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neontribe/code-reading-club/c3baf98c0d517ec7c7b9f09addee7f0cd3cca71f/neontribe-club/sessionX/code_sample.pdf -------------------------------------------------------------------------------- /neontribe-club/sessionX/example.rb: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # Copyright (C) 2011 - present Instructure, Inc. 4 | # 5 | # This file is part of Canvas. 6 | # 7 | # Canvas is free software: you can redistribute it and/or modify it under 8 | # the terms of the GNU Affero General Public License as published by the Free 9 | # Software Foundation, version 3 of the License. 10 | # 11 | # Canvas is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU Affero General Public License for more 14 | # details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License along 17 | # with this program. If not, see . 18 | # 19 | 20 | class QuestionBanksController < ApplicationController 21 | before_action :require_context, :except => :bookmark 22 | add_crumb(proc { t('#crumbs.question_banks', "Question Banks") }, :except => :bookmark) { |c| c.send :named_context_url, c.instance_variable_get("@context"), :context_question_banks_url } 23 | 24 | include Api::V1::Outcome 25 | 26 | def index 27 | if @context == @current_user || authorized_action(@context, @current_user, :read_question_banks) 28 | @question_banks = @context.assessment_question_banks.active.except(:preload).to_a 29 | if params[:include_bookmarked] == '1' 30 | @question_banks += @current_user.assessment_question_banks.active 31 | end 32 | if params[:inherited] == '1' && @context != @current_user 33 | @question_banks += @context.inherited_assessment_question_banks.active 34 | end 35 | @question_banks = @question_banks.select{|b| b.grants_right?(@current_user, :manage) } if params[:managed] == '1' 36 | @question_banks = Canvas::ICU.collate_by(@question_banks.uniq) { |b| b.title || CanvasSort::Last } 37 | respond_to do |format| 38 | format.html 39 | format.json { render :json => @question_banks.map{ |b| b.as_json(methods: [:cached_context_short_name, :assessment_question_count]) }} 40 | end 41 | end 42 | end 43 | 44 | def questions 45 | find_bank(params[:question_bank_id], params[:inherited] == '1') do 46 | @questions = @bank.assessment_questions.active 47 | url = polymorphic_url([@context, :question_bank_questions], :question_bank_id => @bank) 48 | @questions = Api.paginate(@questions, self, url, default_per_page: 50) 49 | render :json => {:pages => @questions.total_pages, :questions => @questions} 50 | end 51 | end 52 | 53 | def reorder 54 | @bank = @context.assessment_question_banks.find(params[:question_bank_id]) 55 | if authorized_action(@bank, @current_user, :update) 56 | @bank.assessment_questions.active.first.update_order(params[:order].split(',')) 57 | render :json => {:reorder => true} 58 | end 59 | end 60 | 61 | def show 62 | @bank = @context.assessment_question_banks.find(params[:id]) 63 | js_env({ 64 | :CONTEXT_URL_ROOT => polymorphic_path([@context]), 65 | :ROOT_OUTCOME_GROUP => outcome_group_json(@context.root_outcome_group, @current_user, session) 66 | }) 67 | rce_js_env 68 | 69 | add_crumb(@bank.title) 70 | if authorized_action(@bank, @current_user, :read) 71 | @alignments = Canvas::ICU.collate_by(@bank.learning_outcome_alignments) { |a| a.learning_outcome.short_description } 72 | @questions = @bank.assessment_questions.active.paginate(:per_page => 50, :page => 1) 73 | end 74 | 75 | js_bundle :quizzes_bundle, :question_bank 76 | css_bundle :quizzes, :learning_outcomes, :tinymce, :question_bank 77 | @page_title = @bank.title 78 | end 79 | 80 | def move_questions 81 | @bank = @context.assessment_question_banks.find(params[:question_bank_id]) 82 | @new_bank = AssessmentQuestionBank.find(params[:assessment_question_bank_id]) 83 | if authorized_action(@bank, @current_user, :update) && authorized_action(@new_bank, @current_user, :manage) 84 | ids = [] 85 | params[:questions].each do |key, value| 86 | ids << key.to_i if value != '0' && key.to_i != 0 87 | end 88 | @questions = @bank.assessment_questions.where(:id => ids) 89 | if params[:move] != '1' 90 | attributes = @questions.columns.map(&:name) - %w{id created_at updated_at assessment_question_bank_id} 91 | connection = @questions.connection 92 | attributes = attributes.map { |attr| connection.quote_column_name(attr) } 93 | now = connection.quote(Time.now.utc) 94 | connection.insert( 95 | "INSERT INTO #{AssessmentQuestion.quoted_table_name} (#{(%w{assessment_question_bank_id created_at updated_at} + attributes).join(', ')})" + 96 | @questions.select(([@new_bank.id, now, now] + attributes).join(', ')).to_sql) 97 | else 98 | @questions.update_all(:assessment_question_bank_id => @new_bank.id) 99 | end 100 | 101 | [ @bank, @new_bank ].each(&:touch) 102 | 103 | render :json => {} 104 | end 105 | end 106 | 107 | def create 108 | if authorized_action(@context.assessment_question_banks.temp_record, @current_user, :create) 109 | @bank = @context.assessment_question_banks.build(bank_params) 110 | respond_to do |format| 111 | if @bank.save 112 | @bank.bookmark_for(@current_user) 113 | flash[:notice] = t :bank_success, "Question bank successfully created!" 114 | format.html { redirect_to named_context_url(@context, :context_question_banks_url) } 115 | format.json { render :json => @bank } 116 | else 117 | flash[:error] = t :bank_fail, "Question bank failed to create." 118 | format.html { redirect_to named_context_url(@context, :context_question_banks_url) } 119 | format.json { render :json => @bank.errors, :status => :bad_request } 120 | end 121 | end 122 | end 123 | end 124 | 125 | def bookmark 126 | @bank = AssessmentQuestionBank.find(params[:question_bank_id]) 127 | 128 | if params[:unbookmark] == "1" 129 | render :json => @bank.bookmark_for(@current_user, false) 130 | elsif authorized_action(@bank, @current_user, :update) 131 | render :json => @bank.bookmark_for(@current_user) 132 | end 133 | end 134 | 135 | def update 136 | @bank = @context.assessment_question_banks.find(params[:id]) 137 | if authorized_action(@bank, @current_user, :update) 138 | if @bank.update(bank_params) 139 | @bank.reload 140 | render :json => @bank.as_json(:include => {:learning_outcome_alignments => {:include => {:learning_outcome => {:include_root => false}}}}) 141 | else 142 | render :json => @bank.errors, :status => :bad_request 143 | end 144 | end 145 | end 146 | 147 | def destroy 148 | @bank = @context.assessment_question_banks.find(params[:id]) 149 | if authorized_action(@bank, @current_user, :delete) 150 | @bank.destroy 151 | render :json => @bank 152 | end 153 | end 154 | 155 | private 156 | 157 | def bank_params 158 | params.require(:assessment_question_bank).permit(:title, :alignments => strong_anything) 159 | end 160 | end --------------------------------------------------------------------------------