├── .gitignore ├── README.md ├── _notes ├── 2017-06 │ ├── 30-000.md │ ├── 30-001.md │ ├── 30-003.md │ ├── 30-004.md │ ├── 30-005.md │ ├── 30-006.md │ ├── 30-007.md │ ├── 30-008.md │ ├── 30-009.md │ ├── 30-010.md │ ├── 30-011.md │ ├── 30-012.md │ ├── 30-013.md │ ├── 30-014.md │ ├── 30-015.md │ ├── 30-016.md │ ├── 30-017.md │ ├── 30-018.md │ ├── 30-019.md │ ├── 30-020.md │ ├── 30-021.md │ ├── 30-022.md │ ├── 30-023.md │ ├── 30-024.md │ ├── 30-025.md │ ├── 30-026.md │ ├── 30-027.md │ ├── 30-028.md │ ├── 30-029.md │ ├── 30-030.md │ ├── 30-031.md │ ├── 30-032.md │ ├── 30-033.md │ ├── 30-034.md │ ├── 30-035.md │ ├── 30-036.md │ ├── 30-037.md │ ├── 30-038.md │ ├── 30-039.md │ ├── 30-040.md │ ├── 30-041.md │ ├── 30-042.md │ ├── 30-043.md │ ├── 30-044.md │ ├── 30-045.md │ ├── 30-046.md │ ├── 30-047.md │ ├── 30-048.md │ ├── 30-049.md │ ├── 30-050.md │ ├── 30-051.md │ ├── 30-052.md │ ├── 30-053.md │ ├── 30-054.md │ ├── 30-055.md │ ├── 30-056.md │ ├── 30-057.md │ ├── 30-058.md │ ├── 30-059.md │ ├── 30-060.md │ ├── 30-061.md │ ├── 30-062.md │ ├── 30-063.md │ ├── 30-064.md │ ├── 30-065.md │ ├── 30-066.md │ ├── 30-067.md │ ├── 30-068.md │ ├── 30-069.md │ ├── 30-070.md │ ├── 30-071.md │ ├── 30-072.md │ ├── 30-073.md │ ├── 30-074.md │ └── 30-075.md ├── 2017-07 │ ├── 01-000.md │ ├── 03-001.md │ ├── 03-002.md │ ├── 04-003.md │ ├── 04-004.md │ ├── 04-005.md │ ├── 04-007.md │ ├── 04-008.md │ ├── 05-009.md │ ├── 24-012.md │ ├── 24-013.md │ ├── 25-013.md │ ├── 25-014.md │ ├── 26-015.md │ ├── 26-016.md │ ├── 26-017.md │ └── 31-018.md ├── 2017-08 │ ├── 03-000.md │ ├── 04-001.md │ ├── 04-002.md │ ├── 04-003.md │ ├── 07-004.md │ ├── 08-005.md │ ├── 10-006.md │ ├── 10-007.md │ ├── 10-008.md │ ├── 11-009.md │ ├── 11-010.md │ ├── 11-011.md │ ├── 14-012.md │ ├── 15-013.md │ ├── 15-014.md │ ├── 17-015.md │ ├── 17-016.md │ ├── 18-017.md │ └── 21-019.md ├── 2017-09 │ ├── 01-000.md │ ├── 01-001.md │ ├── 01-002.md │ ├── 01-003.md │ ├── 01-004.md │ ├── 01-005.md │ ├── 01-006.md │ ├── 04-007.md │ ├── 04-009.md │ ├── 04-010.md │ ├── 04-011.md │ ├── 12-012.md │ ├── 12-013.md │ ├── 12-014.md │ ├── 12-015.md │ ├── 12-016.md │ ├── 12-017.md │ ├── 12-018.md │ ├── 12-019.md │ ├── 12-020.md │ ├── 12-021.md │ ├── 12-022.md │ ├── 20-023.md │ └── 25-024.md ├── 2017-10 │ ├── 11-004.md │ ├── 12-005.md │ ├── 17-007.md │ └── 19-008.md └── 2017-11 │ └── 01-000.md ├── babel.md ├── code-viz.md ├── coding-with-kids.md ├── collaboration.md ├── cooking.md ├── creative-process.md ├── css.md ├── docker.md ├── docs.md ├── electron.md ├── emacs.md ├── ffmpeg.md ├── flowtype.md ├── gardening.md ├── git.md ├── github-prs.md ├── images └── ballmer-developers.gif ├── jest.md ├── node.md ├── npm.md ├── open-source.md ├── portfolios.md ├── productivity.md ├── react.md ├── reason.md ├── teams.md ├── tech-goals-for-2017.md ├── ui.md └── writing.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # knowledge 2 | 3 | Repository for recording knowledge about things I'm learning and things I'm interested in. Inspired by @yoshuawuyts [knowledge repository](https://github.com/yoshuawuyts/knowledge) 4 | 5 | ## web ring 6 | 7 | There are a few other knowledge lists. Join us here: https://github.com/RichardLitt/meta-knowledge/blob/master/README.md 8 | 9 | ## License 10 | 11 | [MIT](https://tldrlegal.com/license/mit-license) 12 | -------------------------------------------------------------------------------- /_notes/2017-06/30-000.md: -------------------------------------------------------------------------------- 1 | reading [A story of a woman in the tech industry](https://medium.com/@fox/a-story-of-a-woman-in-the-tech-industry-5637ea19788) 2 | 3 | I have to ask myself: when that moment arrives and I am faced with the opportunity to either add to this problem or to fight it, what will I do? How can I make myself prepared? 4 | -------------------------------------------------------------------------------- /_notes/2017-06/30-001.md: -------------------------------------------------------------------------------- 1 | problem: often I have multiple things to cover with a person, but because of timezone difference I have to do it via text. I am mindful of overloading people and things being missed as a result. There's a limit to the number of questions you can ask in one go. 2 | 3 | So I need to find a way to open (and continue) several ongoing topics / threads 4 | 5 | ## possible solutions 6 | 7 | - private gists? 8 | - self-hosted etherpad? (is this still a thing?) 9 | -------------------------------------------------------------------------------- /_notes/2017-06/30-003.md: -------------------------------------------------------------------------------- 1 | # bottlenecks 2 | 3 | I'm realizing over & again that my biggest bottlenecks to productivity are: 4 | 5 | - being able to prototype a solution, without necessarily coding something. 6 | - being able to pass on a vision, high-level goals and constraints to a group. 7 | -------------------------------------------------------------------------------- /_notes/2017-06/30-004.md: -------------------------------------------------------------------------------- 1 | # Clarity 2 | 3 | What is the number 1 most important thing you need to be productive? Clarity. 4 | 5 | One hour with a clear vision in your head is more valuable than a whole day of wandering around unable to grasp the bigger picture. 6 | 7 | ## Planning 8 | 9 | Planning is the task of gaining clarity. A good plan literally allows us to see into the future and visualize something that doesn't exist yet. 10 | 11 | A good plan is also the primary way that more than 1 person can share the same vision. Writing it down forces articulation and maturing of half-formed thoughts, and allows others to collaborate and give feedback. 12 | 13 | ## Journaling 14 | 15 | Keeping a journal is complementary to writing a plan, and will enrich the planning process. Where a plan looks forward, a journal looks back. It is a reflective activity that evaluates past planns & executions with the benefit of hindsight. 16 | 17 | If the journal is shared with the team, it also provides a window into your brain so that others can see how you are approaching the plan, and understand how to collaborate better. 18 | 19 | ## Interruptions 20 | 21 | Interruptions and distractions are a big clarity-killer. You can recover from one or two, but beyond that your brain won't focus because it will be always half-anticipating the next one. 22 | 23 | If you're trying to focus and you know there's a possibility of being interrupted, it's often better to not even start. Just do something else, something more mechanical that you can pick up and put down. 24 | 25 | Then when you know you'll have 1 hour free from interruptions: 26 | 27 | - close down all email, slack, phone 28 | - put a sign on the door saying _"I'll be out at 11:30"_ 29 | - put a timer on the phone, and avoid responding to anything short of a house fire before the timer goes off. 30 | - re-read the high level goals and recent journal entries as a way of picking up those loose threads. 31 | -------------------------------------------------------------------------------- /_notes/2017-06/30-005.md: -------------------------------------------------------------------------------- 1 | # scratch: Code with Anna and Elsa 2 | 3 | 4 | 5 | - started this with my daughter (6), and she is really loving it after the first few puzzles. 6 | - there's some nice intro to geometry & angles, as well as thinking in patterns. 7 | - i like how it works with experimental play (eg. "What happens if i change this?") as well as encouraging to run the simulation in your head, and then use the computer to confirm your expectations. 8 | 9 | ## summary 10 | 11 | - I was helping my daughter at first, but after the first few I just let her experiment with it. When she got stuck, rather than telling her what to do, I gave her an idea of a different way to experiment (eg. "what if you change _that_ value?") 12 | - by the end she was figuring out the solutions without any help from me at all, and was so excited and proud of the achievement. 13 | -------------------------------------------------------------------------------- /_notes/2017-06/30-006.md: -------------------------------------------------------------------------------- 1 | # computed fields in javascript 2 | 3 | Situation: we are fetching documents from a database, operating on them, making changes and storing them back in the database. 4 | 5 | Let's say we have a document like this: 6 | 7 | ``` 8 | const doc = { 9 | tastesLikeBacon: true, 10 | usesArtificialFlavours: false 11 | } 12 | ``` 13 | 14 | And we have a definition of "delicious" that means: 15 | 16 | - it tastes like bacon 17 | - it doesn't use artifical flavours 18 | 19 | Rather than duplicating information and adding an `isDelicious` field, we want to calculate the value from the other 2 fields. 20 | 21 | ## Option 1. create a class 22 | 23 | ``` 24 | const a = new Food(doc) 25 | a.isDelicious() ? ... : ... 26 | ``` 27 | 28 | - pros: familiar pattern for a lot of developers 29 | - cons: now we have to keep track of whether we have a class instance or a plain js object, and handling the marshalling for db reads & writes 30 | 31 | ### Option 2. just use functions 32 | 33 | ``` 34 | foodFuncs.isDelicious(doc) ? ... : ... 35 | ``` 36 | 37 | - pros: no temptation to form an inheritance hierarchy 38 | - con: ? 39 | -------------------------------------------------------------------------------- /_notes/2017-06/30-007.md: -------------------------------------------------------------------------------- 1 | # core values 2 | 3 | Everybody has "core values". 4 | 5 | These values are what you _optimise your life towards_, and they influence every decision you make, though often subconsciously. Most of the time I am privileged to live in a performance surplus, so optimisation is not even a question. But when the chips come down I'm forced to choose: what is more important to me? A or B? These are the times you begin to see clearly what your core values are. 6 | 7 | _"Wisdom is proved right by her actions"_ 8 | 9 | **Experiment:** you probably have an idea of what your core values are, as they are wrapped up in what you aspire to and call "best". Think about some decisions you made today, or recently. Do they align with the values you expected them to? If not, this may be a time to learn something new about yourself. 10 | -------------------------------------------------------------------------------- /_notes/2017-06/30-008.md: -------------------------------------------------------------------------------- 1 | # principles of css modules 2 | 3 | ## unique names 4 | 5 | - it doesn't matter what the name is, as long as it's guaranteed to be unique 6 | - unique names mean that we always know what a name means. A name never has 2 meanings, or a meaning which is different depending on context. 7 | - css modules achieves this by namespacing each classname (based on the module file path) 8 | 9 | ## think in components 10 | 11 | - css modules is to traditional css as functional composition is to object-oriented inheritance 12 | - composition & inheritance are both ways to define reusable components 13 | - the big difference is that with inheritance we are "extending" the meaning of something, and overriding parts of it. With functional composition we define immutable atoms and group them together to create the meaning we want. 14 | 15 | ## css modules approach is a mix of traditional css and inline styles 16 | 17 | - traditional css approach: 18 | - define the css style guide as a bunch of classes 19 | - write your dom elements, and decorate them with css 20 | 21 | - inline styles approach: 22 | - write your dom elements 23 | - apply whatever styles are neccesary to make it look right 24 | 25 | - css modules approach: 26 | - every element in a component has a name 27 | - apply styles, or style-guide classes, to those elements 28 | 29 | 30 | ## style child-components by setting props, not adding classes 31 | 32 | Instead of: 33 | 34 | ``` 35 | .ParentComponent .ChildComponent { 36 | /* overrides for color / layout / etc */ 37 | } 38 | ``` 39 | 40 | Prefer: 41 | 42 | ``` 43 |
44 | 45 |
46 | ``` 47 | 48 | That way it's up to `ChildComponent` to provide an API that determines how it can be customized. 49 | -------------------------------------------------------------------------------- /_notes/2017-06/30-009.md: -------------------------------------------------------------------------------- 1 | # css-modulesify with postcss-copy-assets 2 | 3 | Goal: combine [css-modulesify](https://github.com/css-modules/css-modulesify/) with [postcss-copy-assets](https://github.com/shutterstock/postcss-copy-assets) so that any assets (like svg, images, fonts) referenced from css files can be automatically copied to the output directory. 4 | 5 | After a quick trial it looks like this will work, but we need to update `loader-core` to set a proper `from` and `to` when running the postcss chain (these are necessary to rewrite asset urls). 6 | 7 | ## other things to check 8 | 9 | - [ ] interop with watchify (updating an asset should trigger a re-copy) 10 | -------------------------------------------------------------------------------- /_notes/2017-06/30-010.md: -------------------------------------------------------------------------------- 1 | # debugging node 2 | 3 | Recent node versions (eg. v7.9.0) have some great debugging tools built in: https://nodejs.org/api/debugger.html 4 | 5 | You can run `node --inspect=9222 my-script.js` and use the interactive debugger in chrome devtools. 6 | 7 | You can also use the `--inspect-brk` flag which sets a breakpoint on the first line. For example, if you want to debug a monobrow build: 8 | 9 | ``` 10 | node --inspect-brk=9222 node_modules/.bin/monobrow 11 | ``` 12 | 13 | Once you have the devtools open, you can search the source and set new breakpoints, inspect values, etc. Really helpful way to see what is happening under the hood. 14 | -------------------------------------------------------------------------------- /_notes/2017-06/30-011.md: -------------------------------------------------------------------------------- 1 | # discipline 2 | 3 | - there is "skill" and then there is "discipline" 4 | - as with any habit-forming, consistency is greater than quantity. Everyone can start with _something_ and build upon that. 5 | - just like in physical training there are things we can do to help people form that discipline. A clear guideline that's easy to follow, and someone who will check up on you, that you are accountable to. 6 | - these 2 things (clear guideline & accountability) will also help us to avoid "the slump". As a project matures or deadlines encroach, disciplines can slip. Or a dev might spend 8 hours debugging something, which only equates to 1 line of code. Somebody needs to be there alongside them pushing through the tough patch. But the end result is growth. 7 | -------------------------------------------------------------------------------- /_notes/2017-06/30-012.md: -------------------------------------------------------------------------------- 1 | # builder pattern 2 | 3 | Reading about the docker "builder pattern": 4 | 5 | - http://blog.alexellis.io/mutli-stage-docker-builds/ 6 | - https://github.com/adobe-platform/porter/blob/master/docs/detailed_design/docker-builder-pattern.md 7 | - https://codefresh.io/blog/node_docker_multistage/ 8 | -------------------------------------------------------------------------------- /_notes/2017-06/30-013.md: -------------------------------------------------------------------------------- 1 | # docker npm3 issue 2 | 3 | [Using Node with Docker](http://blog.cloud66.com/using-node-with-docker) 4 | 5 | Has a solution for the `EXDEV: cross-device link not permitted` error that you might see from an `npm install` 6 | -------------------------------------------------------------------------------- /_notes/2017-06/30-014.md: -------------------------------------------------------------------------------- 1 | # volumes in docker-compose.yml 2 | 3 | - when you specify a `volumes` field it creates a mapping between a directory on the host, and a counterpart directory in the container 4 | - 2-way sync: any changes to files are reflected in both places, regardless of where they originated 5 | -------------------------------------------------------------------------------- /_notes/2017-06/30-015.md: -------------------------------------------------------------------------------- 1 | # what's the `version: '2'` bit I sometimes see at the top of a `docker-compose.yml`? 2 | 3 | At first I was confused by this. Is "version 2" an upgrade, or a downgrade, from where I am now?? 4 | 5 | Answer: version 3 is the latest, and is the default if you don't specify a version. So don't worry about version 2. 6 | 7 | Ref: 8 | -------------------------------------------------------------------------------- /_notes/2017-06/30-016.md: -------------------------------------------------------------------------------- 1 | # efficient process 2 | 3 | One of the ways I know about improving efficiency is to batch operations. So if you have to make 10 sandwiches you don't make 1 sandwich then start on the next. You slice 20 pieces of bread, butter 20 pieces of bread, etc. 4 | 5 | This leads to less context switching, and also highlights opportunities for automation or abstraction. Like what if there was such a thing as pre-sliced bread? That would be the best thing ever. 6 | -------------------------------------------------------------------------------- /_notes/2017-06/30-017.md: -------------------------------------------------------------------------------- 1 | # electron: Executing js in a BrowserWindow 2 | 3 | ### with `executeJavaScript` 4 | 5 | If you just want to run js in a page there is 6 | 7 | However if you want to read some information or get a result you need to use `ipc`. Example here of using `ipc` with `executeJavaScript` together: 8 | 9 | There's a small helper module for this too: 10 | 11 | ### with a `preload` script 12 | 13 | When creating a `BrowserWindow` you can specify a js file in the `webPreferences.preload` option: 14 | 15 | This file is run before any js, and has access to the electron API so you can set up communication over `ipc`. 16 | -------------------------------------------------------------------------------- /_notes/2017-06/30-018.md: -------------------------------------------------------------------------------- 1 | # opening files with `sudo` 2 | 3 | When you open a file, if you start the path with `/sudo:root@localhost:` you'll get a prompt for your user's `sudo` password. After entering a correct password, you enter the file path. 4 | 5 | So `/sudo:root@localhost:/some/protected/file` is a more convenient way to edit the file, rather than quitting and running `sudo emacs /some/protected/file`. 6 | 7 | ## bookmarking with `sudo` 8 | 9 | You can also use `/sudo:` in bookmarks. I've got a bookmark called "hosts" which jumps to `/sudo:root@localhost:/etc/hosts` 10 | -------------------------------------------------------------------------------- /_notes/2017-06/30-019.md: -------------------------------------------------------------------------------- 1 | # erase a cdrw 2 | 3 | I had to erase a CD-RW in MacOs today, and Disk Utility was not giving an option to do it. Finally found there's a way to do it via command line. Even better! 4 | 5 | ``` 6 | drutil -drive 1 erase quick 7 | ``` 8 | 9 | There's also the option to use `full` instead of `quick`. Not 100% sure what that means, I guess maybe you want it if there is any sensitive data on the CD. 10 | -------------------------------------------------------------------------------- /_notes/2017-06/30-020.md: -------------------------------------------------------------------------------- 1 | # allocating VS estimating 2 | 3 | Here's the idea: stop _estimating_ how long software will take to build. _Allocate_ time instead. It's not a new idea, I'm just thinking through it :) 4 | 5 | It's sleight-of-hand in one sense. You still have to estimate how much time to allocate. But the vibe has totally changed now: 6 | 7 | - when we estimate something, we're saying _"I think it will take this long"_. Then if it takes longer, we say _"Oh well, looks like I didn't account for everything in my estimate"_. Solution: get better at guessing! 8 | - when we allocate time for something, we're saying _"This is how much time you've got to deliver"_. If it's going to take longer, we say _"Better figure out how to make this work"_. Solution: get better at reaching compromises and communicating. 9 | 10 | It might sound too strict, like you're choosing the box first and then deciding what to put in it. But developers are actually very good at doing that! By saying "make it fit" you're actually granting them some creative licence. If corners have to be cut, there's the beginning of a conversation from which the whole team can benefit. Maybe time needs to be extended to avoid cutting necessary features. Or maybe the developers have come up with a creative way to build your product in a shorter time. 11 | -------------------------------------------------------------------------------- /_notes/2017-06/30-021.md: -------------------------------------------------------------------------------- 1 | # Extreme separation of business rules 2 | 3 | Often the business rules and the boilerplate of an application get mixed & intertwined. 4 | 5 | **Litmus test:** When you review a PR, is it obvious whether the core business logic has changed, or whether it's just a re-jigging of the implementation? 6 | 7 | If we could separate the two completely it would make these diffs stand out clearly. 8 | 9 | ## Proposal 10 | 11 | Store all business rules in "business modules". 12 | 13 | For example, make a directory like `src/rules/` that contains modules describing different parts of the system (I'm using nodejs as the example platform). 14 | 15 | These modules are kind of like documentation, but where possible we should be describing business rules in well-commented code. 16 | 17 | ### Q. What kinds of things can these business modules export? 18 | 19 | - **constants**: this is the easiest place to start. Most of the time we do this anyway, via a config file. 20 | - **algorithms**: export a function that encapsulates a certain business rule. Eg. If you have different shipping rates in months beginning with "J", wrap that up in a function. 21 | - **types**: if you're using flowtype this is a good location for type definitions. 22 | - **pseudocode**: sometimes it's just not possible / practical to express a business rule as a function independent from boilerplate. In that case pseudocode is fine. 23 | 24 | Keep these values & functions as implementation-agnostic as possible. You don't want implementation-specific stuff leaking into your business rules. A little bit is ok but avoid it where practical. 25 | 26 | Also a good idea to use a lot of comments that explain the reasons behind these things, and how different parts of the system relate to each other. This makes it feel like a hybrid betweeen code & docs. If you're into literate programming this is probably a good use case. 27 | 28 | If all goes well, your implementation code should have an overall declarative / boilerplatey flavour to it, with most (if not all) of the decision-making happening inside the business modules. 29 | -------------------------------------------------------------------------------- /_notes/2017-06/30-022.md: -------------------------------------------------------------------------------- 1 | # Wrapping a function with falafel 2 | 3 | ```js 4 | function walk (node) { 5 | if (node.type === 'FunctionDeclaration') { 6 | if (node.id.name === 'findWord') { 7 | const orig = node.source.toString() 8 | node.body.update('{ return 99 }') 9 | } 10 | } 11 | } 12 | ``` 13 | -------------------------------------------------------------------------------- /_notes/2017-06/30-023.md: -------------------------------------------------------------------------------- 1 | # fission & fusion 2 | 3 | I don't know heaps about particle physics, but I know enough to glean a metaphor from it. Someone will surely correct my understanding of how this stuff works, but bear with me. Here we go :) 4 | 5 | We know about 2 ways of generating energy from messing with atoms: fission and fusion. 6 | 7 | **fission** is where an atom is split. We start with something big, and we split it into smaller pieces. The key is that the smaller pieces are more stable than the 1 big piece, so they require less energy to hold together. That means there is leftover energy that isn't needed anymore. Yay, we can use that energy. 8 | 9 | **fusion** is where you take 2 atoms and put them together to form 1 atom. Again, the resulting atom requires less energy than the sum total of the original 2, so there's some leftovers. 10 | 11 | Now here's the metaphory part: this is a bit like software development. The atoms are the languages, tools, libraries & frameworks. The energy produced by fission or fusion equates to productivity. 12 | 13 | Sometimes tech is pushed forwward when things are split apart into smaller pieces. Now we can get those small pieces really stable, and use them in ways we couldn't easily do when they were all clumped together. 14 | 15 | Other times, we have so many little pieces that there is waste in the sum total of energy required to hold them all together. If they can be clumped together in a sensible way, we save all of that time we used to spend on boilerplate. 16 | 17 | With this in mind, I think `react` is nearing the edge of an interesting precipice. The number of packages & tools needed to work with react effectively in a large scale project is becoming cumbersome. Projects like `create-react-app` are proof that there is a lot of energy to be released if you can find a good way to clump. 18 | -------------------------------------------------------------------------------- /_notes/2017-06/30-024.md: -------------------------------------------------------------------------------- 1 | # flow: add definitions for common libraries 2 | 3 | 4 | 5 | - install the cli: `npm install -g flow-typed` 6 | - then in your project directory, run `flow-typed install` 7 | -------------------------------------------------------------------------------- /_notes/2017-06/30-025.md: -------------------------------------------------------------------------------- 1 | # FORC 2 | 3 | _"Fear of Removing CSS"_ 4 | 5 | - Q. why is it often difficult to delete css code? 6 | - global scope 7 | - cross-module cascading 8 | 9 | - "how easy will this be to remove?" is a helpful question to ask when considering technical debt 10 | 11 | - It's vastly easier to add complexity than it is to remove it 12 | - [Joe Armstrong: "the mess we're in"](https://vimeo.com/97408239) 13 | 14 | - golden rule: **you can remove code easily if you know where all of the dependencies are**, and can confirm that nothing depends on it. 15 | 16 | - what kinds of things can make it easier? 17 | - you can remove code easily if you know precisely where all of the dependencies are, and can confirm that nothing depends on it. 18 | - we already have a dependency tree of js modules, so if we consider css modules as part of this tree it's easy to prove the existence or absence of dependencies 19 | - avoid cascading from one module to another. Separate concerns so that we put display-logic in js, leaving css for pure styles 20 | - think about "hidden dependencies". When an html adds something to its `class` attribute, it depends on the css being there. When you write a cascade rule in css, there's a dependency, possibly between multiple css files. 21 | -------------------------------------------------------------------------------- /_notes/2017-06/30-026.md: -------------------------------------------------------------------------------- 1 | # free speech 2 | 3 | Some post-berkeley-riot thoughts & discussion with others 4 | 5 | - http://www.foxnews.com/us/2017/02/02/milo-yiannopoulos-berkeley-riot-self-defeating-for-social-justice-left.html 6 | - http://www.9news.com.au/world/2017/02/03/15/50/alt-right-agitator-milo-yiannopoulos-the-berkeley-riots-and-donald-trump 7 | 8 | > Well, once again they have proven me right," Yiannopoulos said 9 | 10 | > Being "proven right" after lighting the fuse is central to Yiannopoulos's rhetorical MO. He riles his enemies into a frenzy with speeches like "How Feminism Hurts Women", or by declaring his birthday "World Patriarchy Day", and then sits back and gloats when the inevitable backlash comes. 11 | 12 | ## Q. Should milo censor himself, to avoid offending others? 13 | 14 | Here's how I approach this question: rather than saying _"milo shouldn't say those things"_ or _"protestors shouldn't use violence"_, we can take a step back and consider motives. 15 | 16 | TL;DR: measure someone by what you perceive as their motives, rather than by how closely they match a "good" or "bad" abstract ideal. 17 | 18 | ### Q. What kinds of things motivate people? 19 | 20 | These are, in my opinion, the main ones: 21 | 22 | - fear 23 | - self-interest (money / status / honour) 24 | - duty 25 | - love 26 | 27 | Here's my hypothesis: anything that does not have love at the foundation is destructive in the long run. 28 | 29 | ### Q. What do you think Milo's motive is? 30 | 31 | - is there any evidence of love in his actions? 32 | - are his actions constructive or destructive? 33 | 34 | You can ask the same thing about the people smashing stuff and pepper-spraying. 35 | -------------------------------------------------------------------------------- /_notes/2017-06/30-027.md: -------------------------------------------------------------------------------- 1 | # fundamentalist 2 | 3 | I have a theory: everyone is a fundamentalist. 4 | 5 | Your fundamentals are your inner-most core values. In fact they go so deep that, until they are threatened, you often don't even identify what they are exactly. 6 | 7 | Yet they nonetheless shape one's actions, and are the lens through which one sees the world and fits it into a narrative. 8 | 9 | Being a "fundamentalist" is usually associated with being at best uptight, and at worst dangerous. But I'd like to suggest that it's neither good nor bad in itself - that is entirely determined by what one's fundamentals are. 10 | -------------------------------------------------------------------------------- /_notes/2017-06/30-028.md: -------------------------------------------------------------------------------- 1 | # git: create a branch from a tag 2 | 3 | `git checkout -b ` 4 | 5 | where: 6 | 7 | - `` is the name of the branch you want to create 8 | - `` is the name of the tag. (Must match something from the output of `git tag`) 9 | -------------------------------------------------------------------------------- /_notes/2017-06/30-029.md: -------------------------------------------------------------------------------- 1 | # working with github pull requests locally 2 | 3 | Useful if someone submits a PR on your github project, and you want to try it out locally. Append this line to the `[remote "origin"]` section in your `.git/config` file: 4 | 5 | ``` 6 | fetch = +refs/pull/*/head:refs/remotes/origin/pr/* 7 | ``` 8 | 9 | So the whole section will now look something like this: 10 | 11 | ``` 12 | [remote "origin"] 13 | url = git@github.com:joshwnj/monobrow.git 14 | fetch = +refs/heads/*:refs/remotes/origin/* 15 | fetch = +refs/pull/*/head:refs/remotes/origin/pr/* 16 | ``` 17 | 18 | Now when you `git pull`, you'll see a bunch of "pr" branches. You can switch to a PR branch with it's ID, like this: 19 | 20 | ``` 21 | git checkout pr/9 22 | ``` 23 | -------------------------------------------------------------------------------- /_notes/2017-06/30-030.md: -------------------------------------------------------------------------------- 1 | # github: show a diff without whitespace 2 | 3 | Add `?w=0` to the URL 4 | -------------------------------------------------------------------------------- /_notes/2017-06/30-031.md: -------------------------------------------------------------------------------- 1 | # octolinker 2 | 3 | 4 | 5 | Browser extension that turns js packages (in `package.json` or `require / import`) into clickable links. 6 | -------------------------------------------------------------------------------- /_notes/2017-06/30-032.md: -------------------------------------------------------------------------------- 1 | # growing salad 2 | 3 | I had a bunch of rocket (arugula for my american buddies) plants growing over the summer. Got a few nice salads, and made some spicy garlic bread by blending up the leaves into a paste with butter & garlic. Rocket-butter is :100: on a steak btw. 4 | 5 | The leaves were significantly hotter (as in, peppery) than ones you get from the shops, and I'm wondering why. 6 | 7 | A clue came more recently: after letting all of the old plants go to seed, I cut them and hung to dry (they were pretty huge by this time), turned the soil and re-sowed. The second round took off quickly, and I noticed that the leaves had a much milder and more pleasant flavour this time. 8 | 9 | So I'm wondering what the difference was? 10 | 11 | - maybe it had something to do with the re-seeding? 12 | - maybe the soil had mellowed by the time of the second batch? 13 | - maybe it was weather related? (the second batch was in significantly cooler and wetter weather than the first). 14 | 15 | If I had to take a guess I'd say that higher heat / dryer ground was the main influencer of the leaves. Will try again next time and see if I can repeat it :) 16 | -------------------------------------------------------------------------------- /_notes/2017-06/30-033.md: -------------------------------------------------------------------------------- 1 | # idea: headless backend 2 | 3 | - create the data models and business logic etc, and then step through all functionality 4 | - at each step it asks you questions: 5 | - _"has the user exceeded their quota?"_ 6 | - _"was there a payment error?"_ 7 | - and the response can also contain new URLs to complete various follow-up actions 8 | - the goal is that we present a graph of possible next-steps and outcomes 9 | -------------------------------------------------------------------------------- /_notes/2017-06/30-034.md: -------------------------------------------------------------------------------- 1 | # Immutable CSS 2 | 3 | _The "C" is for "Composable"._ 4 | 5 | An approach to css which favours composition over cascading. 6 | 7 | ## media queries 8 | 9 | This is one of the big questions around immutable css. If we can't change the meaning of a class, how do we get it to display adaptively to different screen sizes? 10 | 11 | Here's what I've been trying lately: 12 | 13 | - define atoms for various style aspects 14 | - compose them together 15 | - we can also compose atoms media queries 16 | 17 | eg. 18 | 19 | ```js 20 | const cmz = require('cmz') 21 | 22 | const mediumText = cmz(` 23 | font-size: 3rem 24 | `) 25 | 26 | const largeText = cmz(` 27 | font-size: 5rem 28 | `) 29 | 30 | const c = cmz([ 31 | mediumText, 32 | atMedia({ min-width: 550 }, largeText) 33 | ]) 34 | 35 | //
...
36 | ``` 37 | 38 | `atMedia` above actually generates a new css class on-demand, wrapped in a media query: 39 | 40 | ```css 41 | @media (min-width: 550px) { 42 | .largeTextWhenMinWidth550 { 43 | font-size: 5rem; 44 | } 45 | } 46 | ``` 47 | 48 | Inspecting the DOM, it looks like this: 49 | 50 | ```html 51 |
...
52 | ``` 53 | 54 | So we can still have "conditional application" of atoms, without mutating them. 55 | -------------------------------------------------------------------------------- /_notes/2017-06/30-035.md: -------------------------------------------------------------------------------- 1 | [Frank Zappa - Dupree's Paradise (1973)](https://www.youtube.com/watch?v=qr6mTloYJJs) 2 | -------------------------------------------------------------------------------- /_notes/2017-06/30-036.md: -------------------------------------------------------------------------------- 1 | # jest snapshot testing 2 | 3 | I've tried using jest on 2 separate occasions before, and both times found it was either too weird or buggy. This was a while back. 4 | 5 | Seems to be a lot more stable now, so maybe 3rd time's the charm? I'm most interested in incorporating snapshot testing into my workflow. 6 | 7 | - https://facebook.github.io/jest/docs/tutorial-react.html 8 | - works with plain functions as well as react components. nice. 9 | 10 | - ava also has support for snapshot tests (uses jest-snapshot under the hood): https://github.com/avajs/ava#snapshot-testing 11 | - works well too, although when I tried to compare a snapshot I got an error with no stacktrace: `[TypeError: Cannot read property 'split' of null]` 12 | - worthwhile digging into this more later on. But for now might try jest some more and see where that leads. 13 | -------------------------------------------------------------------------------- /_notes/2017-06/30-037.md: -------------------------------------------------------------------------------- 1 | # junk food ui 2 | 3 | - 4 | - why it's important to spend time getting the UI right, even when it's a non-graphical UI intended for programmers to use. 5 | - this is still just as much a design task requiring design exploration. 6 | -------------------------------------------------------------------------------- /_notes/2017-06/30-038.md: -------------------------------------------------------------------------------- 1 | # left and right 2 | 3 | Q. What are some of the ways that both sides fail? These things aren't so obvious in the middle, but become more apparent as you get to the edges. 4 | 5 | ## right 6 | 7 | - emphasis on objective moral code means that some are inevitably born into positions of power, while others into positions of seemingly inescapable vulnerability. 8 | - the more confident we become in the idea of absolute "right and wrong" ways to live, the more we set ourselves up for hypocrisy. 9 | 10 | ## left 11 | 12 | - the left avoids hypocrisy by avoiding the idea of an objective moral code. 13 | - But this leads to absurdity. We recognise evil in the world, but who are we to judge "good" from "evil"? By what standard? 14 | -------------------------------------------------------------------------------- /_notes/2017-06/30-039.md: -------------------------------------------------------------------------------- 1 | # idea: mdx 2 | 3 | A variant of markdown which can include jsx components. 4 | 5 | the vision: modular web pages which export both content and data 6 | 7 | ## why? 8 | 9 | - might be a useful way to write documents that contain a mixture of prose & data, and that can be used in rich visualizations. 10 | - i always run into walls when trying to stretch markdown too far. In a lot of cases I'd rather just use plain markdown, and use jsx for more complicated things. 11 | -------------------------------------------------------------------------------- /_notes/2017-06/30-040.md: -------------------------------------------------------------------------------- 1 | # modeling drafts 2 | 3 | When modeling "drafts" of something (eg. a form with a "save draft" / "resume draft" feature), consider making a _separate model_ altogether for the draft. Rather than adding a `isDraft` flag to the original model. 4 | 5 | ## Reasons 6 | 7 | - validation is different. A draft doesn't need to include required fields, or have intact relationships with linked entities 8 | - you want to be able to safely save the model without accidentally triggering an action you shouldn't. Eg. if there's an `afterSave` hook which sends an email, or adds the model to a processing queue, you probably don't want to do that for drafts. Case in point is Bugwolf. There was logic which said _"when a project model is saved, send email invitations to all testers."_ 9 | -------------------------------------------------------------------------------- /_notes/2017-06/30-041.md: -------------------------------------------------------------------------------- 1 | # multistream 2 | 3 | 4 | 5 | > A stream that emits multiple other streams one after another (streams2) 6 | 7 | Handy for concating several files together, eg. 8 | 9 | ```js 10 | const fs = require('fs') 11 | const multistream = require('multistream') 12 | 13 | // concat file1.txt and file2.txt, and write the result to all.txt 14 | const streams = ['file1.txt', 'file2.txt'].map(filename => fs.createReadStream(filename)) 15 | multistream(streams) 16 | .pipe(fs.createWriteStream('all.txt')) 17 | ``` 18 | -------------------------------------------------------------------------------- /_notes/2017-06/30-042.md: -------------------------------------------------------------------------------- 1 | # passing args into npm run-scripts 2 | 3 | If you've got a package.json like: 4 | 5 | ``` 6 | ... 7 | "scripts": { 8 | "lint": "eslint src" 9 | } 10 | ... 11 | ``` 12 | 13 | and you want to run `eslint` with a different formatter, use the `--` separator followed by the args you want to run `eslint` with: 14 | 15 | ``` 16 | npm run lint -- --format unix 17 | ``` 18 | -------------------------------------------------------------------------------- /_notes/2017-06/30-043.md: -------------------------------------------------------------------------------- 1 | # opinions in opensource 2 | 3 | one of the things I've been learning over the last few years is the importantance of opinions in opensource. Especially as you move from lower-level libraries to higher-level applications. 4 | 5 | I think this is one of the secrets of opensource: 6 | 7 | - don't build "for everyone", build "for yourself" 8 | - spend time crafting your opinions about how things should work, until they are strong opinions 9 | - make your opinions very clear. put them in the readme 10 | - then sometimes, others will see them and say _"hey, i can get behind those opinions"_. It's the seed from which a community grows. 11 | -------------------------------------------------------------------------------- /_notes/2017-06/30-044.md: -------------------------------------------------------------------------------- 1 | # orchestral music 2 | 3 | - [Britten - Four Sea Interludes](https://www.youtube.com/watch?v=ht9mQE6X0C0) 4 | - [Saint-Saens: Symphony No. 3 "Organ" - Finale](https://youtu.be/eW-7S9fjyfU?t=32s) 5 | -------------------------------------------------------------------------------- /_notes/2017-06/30-045.md: -------------------------------------------------------------------------------- 1 | # Product Owner / Tech Lead interactions 2 | 3 | I recently set out to scope some new features for a project. As I was hoping to delegate the majority of coding I wanted to remain within a "product owner" role, and leave technical decisions to a tech lead. So I created some "UX stories" to describe a user's goals and how the system operates from their point of view, without going into detail of how I thought it should be implemented. I wrote each scenario as a github issue, and added them all to a new milestone so they could be read as a group. 4 | 5 | Here's what I'm finding: in a dev's mind there is often a 1:1 mapping of issue:task. We think _"I will write some code and close that issue"_. But that doesn't work when we're talking about UX stories, because multiple stories might all reference the same feature. 6 | 7 | ## Proposed workflow 8 | 9 | (PO is "product owner", TL is "tech lead") 10 | 11 | Here's the kind of workflow I'm trying to get to: 12 | 13 | - PO writes Stories 14 | - TL writes as many Tasks as necessary to complete the Stories. 15 | - At this point, there's a discussion between PO and TL. We need to agree that the Tasks adequately describe a journey from A to B (from where we are now, to where we are ready to ship). 16 | - Upon agreement the Tasks can be moved from Backlog to Ready queue for the team to work on 17 | 18 | When it comes to prioritizing, there is also a clear split: 19 | 20 | - PO determines priority for Stories, with a goal of maximising business value 21 | - TL determines priority for Tasks, with a goal of maximising dev efficiency 22 | -------------------------------------------------------------------------------- /_notes/2017-06/30-046.md: -------------------------------------------------------------------------------- 1 | # Projects in Github 2 | 3 | ## Using github issues to discuss features 4 | 5 | Often features are discussed in multiple places like slack, google docs, or in-person meetings. It's important to have a primary location where all of the info and relevant discussion points are stored. 6 | 7 | Here's one way to do it using github issues: 8 | 9 | - When you want to propose a new feature, create a github issue with a special "feature" label. 10 | - discuss the feature and ask questions in github comments. Any out-of-band discussion can also be added or linked. 11 | - when all questions are answered and requirements finalized, edit the top-level description of the issue to reflect the final version. 12 | 13 | Using github issues has a couple of advantages: 14 | 15 | - per-issue subscriptions, so you are notified of updates 16 | - easy to embed images when needed (drag and drop files, or paste from clipboard) 17 | - easy to create cross-reference links between the feature & bug reports or pull-requests 18 | -------------------------------------------------------------------------------- /_notes/2017-06/30-047.md: -------------------------------------------------------------------------------- 1 | # custom elements in react 2 | 3 | To make a custom jsx element, one easy way is to wrap it as a single-function component: 4 | 5 | ```js 6 | const React = require('react') 7 | 8 | const MyTag = function (props) { 9 | return React.createElement(props.inline ? 'span' : 'div', props) 10 | } 11 | 12 | // then we can use it in jsx: 13 | 14 |
15 | This is rendered as a div 16 | This is rendererd as a span 17 |
18 | ``` 19 | 20 | I like the approach of declaring a react component as a set of custom meaningful elements. Eg. 21 | 22 | ```js 23 | 24 | 25 | 26 | 27 | ``` 28 | 29 | is much better to work with than: 30 | 31 | ```js 32 |
33 | 34 |
35 |
36 | ``` 37 | -------------------------------------------------------------------------------- /_notes/2017-06/30-048.md: -------------------------------------------------------------------------------- 1 | # react: conditions in jsx 2 | 3 | Let's say we have a submit button. It normally displays _"Submit"_, and if the form is currently being submitted the label changes to _"Checking..."_. 4 | 5 | We could do it like this: 6 | 7 | ```js 8 | const button = props.isSubmitting ? 9 | : 14 | 20 | } 21 | ``` 22 | 23 | But there's a lot of duplication there. In abstract, the code says _"depending on Condition, render 1 Element or another"_. 24 | 25 | We could rewrite it to say _"Render an Element, with varying props based on Condition"_: 26 | 27 | ```js 28 | const buttonProps = { 29 | disabled: props.isSubmitting || props.isButtonDisabled, 30 | value: props.isSubmitting ? 'Checking...' : 'Submit' 31 | } 32 | 33 | const button = ( 34 | 39 | ) 40 | ``` 41 | 42 | Now it's easy to see the common props and the props that change. 43 | 44 | A variation on this would be to separate the normal case from the edge case, and move towards a slightly more declarative form. That can make the conditional parts stand out even a little more: 45 | 46 | ```js 47 | const submittingProps = props.isSubmitting ? { 48 | disabled: true, 49 | value: 'Checking...' 50 | } : {} 51 | 52 | const button = ( 53 | 60 | ) 61 | ``` 62 | 63 | Here we can easily see the default state in `button`, and see what changes when it is submitting. 64 | -------------------------------------------------------------------------------- /_notes/2017-06/30-049.md: -------------------------------------------------------------------------------- 1 | # reason noob 2 | 3 | ^ it me 4 | 5 | ## modules and functions 6 | 7 | Coming from a node background, I'm used to thinking of a module as the basic building block of a program. Reason has modules, but it seems slightly different in concept: https://facebook.github.io/reason/modules.html 8 | 9 | From what I can see so far, a good place to start is to just declare functions straight up. I mayb find a need for "reason modules" later, but not there yet :) 10 | 11 | Looking at the bucklescript output, this: 12 | 13 | ```reason 14 | let sayHi name => "hello " ^ name ^ "!"; 15 | ``` 16 | 17 | produces this: 18 | 19 | ```js 20 | function sayHi(name) { 21 | return "hello " + (name + "!"); 22 | } 23 | 24 | exports.sayHi = sayHi; 25 | ``` 26 | -------------------------------------------------------------------------------- /_notes/2017-06/30-050.md: -------------------------------------------------------------------------------- 1 | # redux 2 | 3 | ## atomic actions 4 | 5 | - each action represents an atomic change to the state 6 | - rather than naming by what makes most sense from a user's point of view, name the action according to the atomic change it makes 7 | - atomic, meaning that the state "makes sense" before and after 8 | - sometimes atomic also means "smallest possible". In this case I think it's ok to start with bigger atoms and split them later. 9 | 10 | ## binding action creators 11 | 12 | - tip: always bind action creators 13 | - [Idiomatic Redux: Why use action creators?](http://blog.isquaredsoftware.com/2016/10/idiomatic-redux-why-use-action-creators/) 14 | 15 | ## prefer flat stores 16 | 17 | I usually find if I have to nest a lot of stuff in a store, it really belongs in multiple stores 18 | -------------------------------------------------------------------------------- /_notes/2017-06/30-051.md: -------------------------------------------------------------------------------- 1 | # Requirements 2 | 3 | ## Record the facts 4 | 5 | - one way to gather requirements is to make a list of "facts" about how the system works. 6 | - these might also have accompanying notes to clarify edge cases 7 | - then whenever developing a feature, writing a QA script, or reporting a bug, try to refer to as many of these facts as possible 8 | - need a good way to search for them 9 | - should make it really easy to add new facts, even if there is some overlap 10 | - too confusing to try and describe the entire system in prose, but this way of describing the system is like pointalism: as we add more and more of these points, the whole picture begins to emerge 11 | - still useful to categorise things into sections / screens 12 | 13 | ## Annotate screenshots 14 | 15 | - ather than having to manually name each thing when you describe it, we need to be able to say "this thing" and point to an area in an image file. 16 | -------------------------------------------------------------------------------- /_notes/2017-06/30-052.md: -------------------------------------------------------------------------------- 1 | # screenshots 2 | 3 | - does a good job of waiting until the page has loaded / redirected before taking the screenshot 4 | - doesn't give a way to set request headers or cookies, so adding that myself 5 | 6 | - [nightmare](https://github.com/segmentio/nightmare) also looks good, need to compare. 7 | - nice companion: 8 | -------------------------------------------------------------------------------- /_notes/2017-06/30-053.md: -------------------------------------------------------------------------------- 1 | # sitespeed 2 | 3 | https://github.com/sitespeedio/sitespeed.io 4 | 5 | Using docker it's really easy to create a sitespeed report: 6 | 7 | ``` 8 | docker run --privileged --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io --video --speedIndex https://www.sitespeed.io/ 9 | ``` 10 | -------------------------------------------------------------------------------- /_notes/2017-06/30-054.md: -------------------------------------------------------------------------------- 1 | # generosity in scarcity 2 | 3 | 4 | 5 | talk by [Tim Keller](http://www.timothykeller.com/) 6 | 7 | - "where your treasure is, there your heart will be also" ([matthew 6:21](https://www.biblegateway.com/passage/?search=Matthew+6&version=NIV)) 8 | - the things we most easily give our resources to are the things we treasure the most. 9 | - if someone considers themselves a christian: 10 | - you are called to give first and then figure out the practicality (rather than giving out of leftovers, after securing your own comfort). 11 | - you are called to check your privilege: you didn't earn money or status with hard work, it was given to you. 12 | -------------------------------------------------------------------------------- /_notes/2017-06/30-055.md: -------------------------------------------------------------------------------- 1 | # meaning of christmas 2 | 3 | 4 | 5 | talk by [Tim Keller](http://www.timothykeller.com/) 6 | 7 | **tl;dr** christmas tells us that: 8 | 9 | - we have freedom from striving to live a good life 10 | - imperfect people can be in a love relationship with a perfect god, without fear 11 | - love matters, it's not just an accident 12 | 13 | ## notes 14 | 15 | - every other religion is founded by a prophet or wise person who said _"this is the way"_. Christianity is the only one founded by someone who said "I _am_ the way". 16 | - Christ doesn't speak the words of God, he _is_ the word of God. 17 | - he didn't come and say "here's what you need to do", he said "I've come to do for you what you could never do for yourself" 18 | - he didn't come to say "here's how to live a good life", he said "I _am_ the eternal life". 19 | 20 | - secular view is: _"doctrine doesn't matter, what matters is that you live a good life"_. 21 | - this is a doctrine itself: a religion where your "salvation" comes from your own good works. 22 | - this kind of religion can have no true humility (because if you are good enough, you earned it) and no true peace (because there is no guarantee that your good outweighs your bad). 23 | 24 | - you can't look directly at the sun, it will destroy your eyes. If you want to see the full awesomeness of the sun, you need to look through a filter. 25 | - the meaning of Christmas is that we have a way to see God and know him personally. Jesus is the way that imperfect people can come near to a perfect God, without being burned up. 26 | 27 | - christmas is historical evidence that love really matters 28 | - if this world is all that there is, we came from nothing and will end as nothing 29 | - [Francis Crick](https://en.wikipedia.org/wiki/Francis_Crick) "The Astonishing Universe": "everything about you, your entire concept of identity, is no more than nerves and chemical responses" 30 | - christmas gives us a different narrative. It tells us that love is an eternal and foundational element of the universe. Love was there even before time began, and is the reason for everything that followed. 31 | 32 | - [Yuri Gagarin](https://en.wikipedia.org/wiki/Yuri_Gagarin) was the first cosmonaut to orbit the earth, and russia issued a statement: "we have been to heaven and there was no god there" 33 | - [C.S. Lewis](https://en.wikipedia.org/wiki/C._S._Lewis): "hamlet won't find shakespeare in the rafters above the stage". The only way hamlet can know anything about shakespeare is if the author wrote himself in to the story. 34 | 35 | - we feel intrinsically that love is timeless. We say "I'll love you forever" even though this defies the way we think about the world. 36 | -------------------------------------------------------------------------------- /_notes/2017-06/30-056.md: -------------------------------------------------------------------------------- 1 | # tcomb: custom fail handler 2 | 3 | By default, when a type validation fails `tcomb` throws a `TypeError`. In local development it can be useful to override this behaviour and start the debugger instead. Then we can easily browse up the stack to identify where the data came from: 4 | 5 | ```js 6 | const t = require('tcomb') 7 | 8 | t.fail = function fail (message) { 9 | debugger 10 | } 11 | ``` 12 | -------------------------------------------------------------------------------- /_notes/2017-06/30-057.md: -------------------------------------------------------------------------------- 1 | # TIL 2 | 3 | For those who keep a dev journal like I do, I'd like to introduce a new type of journal entry: the "TIL". 4 | 5 | These can be really short posts that show one thing you learned while working on a project. 6 | 7 | Sometimes it's something very specific to the project, like a significant requirement that you found while digging through some docs. Sometimes it's more general knowledge that you discovered or remembered along the way, like a debugging technique or handy bash trick. 8 | 9 | ## How to write a TIL 10 | 11 | Start looking for those little "learning moments" in your day, and quickly jot down some notes in your journal. Remember, keep it quick & raw. If others read it and have questions, they can ask for more info. 12 | 13 | Try to keep it down to a couple of sentances and maybe a code snippet or screenshot. 14 | 15 | **Exercise:** try making a couple of TIL posts during your working day. 16 | 17 | ## Why do we often avoid this? 18 | 19 | It's easy to fall into the trap of thinking _"I won't share that TIL, because everybody probably knows it already and then I will seem dumb! Or what if I'm wrong and there's actually a better way to do it??"_ 20 | 21 | As a wise commander once pointed out, _"It's a trap"_. 22 | 23 | Just do it, and everyone will thank you later. 24 | 25 | ## Why should we do this? 26 | 27 | Let me address those 2 fears: 28 | 29 | - _**"everybody probably knows it already"**_: Who cares :) Maybe they do, but maybe they don't. Only someone very arrogant will think badly of you at this point. That's their problem, not yours. 30 | 31 | - _**"what if I'm wrong and there's actually a better way to do it?"**_: Again, don't let this stop you. If somebody else knows a better way, this may be your golden opportunity to learn it! They might have been avoiding sharing this knowledge for the very same reason described above! This is your chance to break the cycle. 32 | 33 | ## Example 34 | 35 | The other day I was reviewing pull requests on a github project, I and remembered a handy way to review them locally. I wrote it as a quick "TIL" entry, and since there's no sensitive businesss info there I also posted it to twitter: https://twitter.com/joshwnj/status/855215578042073088 36 | 37 | In a couple of days it had 13 retweets and 9 likes. That's nothing groundbreaking, but if there's a handful of people that found it useful, it's totally worth the 2 minutes it took me to write. 38 | -------------------------------------------------------------------------------- /_notes/2017-06/30-058.md: -------------------------------------------------------------------------------- 1 | # Time limit on tasks 2 | 3 | idea: when starting a task, set a time limit (and use an actual timer). 4 | 5 | - Remove as many distractions as possible during that time 6 | - when the time is up, you're not allowed to keep going or start the clock again. Must change to some other task. 7 | - the purpose of this constraint is to condition myself to work deliberately, thinking about the cost before going into it. If something turns out to take longer than I expected, it shifts the emphasis from _"just keep going until it's done"_ to _"spend the remaining time organising things better, so that when I next come to this task I'll be able to approach it more predictably"_. 8 | 9 | - 30 minutes is a good starting place for new tasks that I'm not sure about. That's enough time to either complete a short task, or prepare myself for a longer one. 10 | 11 | - it's ok to go past the timer if you're just doing final stages of wrapup, sending email, etc. But shouldn't go beyond a couple of minutes, and shouldn't introduce anything new. 12 | 13 | ## context switching 14 | 15 | I do a lot of context switching on a daily basis. Many projects that I need to juggle and keep moving. 16 | 17 | One way to approach this is: 18 | 19 | - start of the day, write a list of each project that needs some attention. 20 | - before diving into any of them, give each one a 30 minute block. 21 | - 30 minutes is not usually enough time to "finish", so the focus is on discovery and planning. Spend the time writing a plan of what to accomplish today, and how long to devote to that. 22 | 23 | This helps to avoid the situation of getting to the end of the day and realizing that too many important topics are untouched. 24 | 25 | In an asynchronous team, even moving just 1 thing forward can make all the difference. 26 | 27 | ## draining & recharging 28 | 29 | I've noticed that certain activities are very draining. It's probably different for everybody, but for me it's things like writing long emails, preparing documents, etc. It's not that I hate doing them, in fact I get a lot of satisfaction when I see that I can help people in this way. But I find them taxing and if I spend too long doing these things all at once, I'll be mentally exhausted before the day is over. These are also the kinds of tasks I tend to procrastinate the most. 30 | 31 | Other activities are the opposite: I look forward to them and feel energised for having done them. Like working on a favourite open source project, for example. 32 | 33 | So there's a balance to be found between these two, and I think order is significant. If I do the fun stuff first, I won't be able to put myself into it as much when I have the lurking thought that I ought to not be putting off the others. Having something hanging over your head is an absolute flow-killer. 34 | 35 | Something I've noticed: On days where I've consciously fought procrastination and done the "draining-but-important" stuff first, I've often felt a weight lift off, and been able to go into the second half of the day with a much clearer head. 36 | 37 | I'm going to try this and see what I find: When planning tasks for the day ahead, 38 | 39 | - identify some "procrastination prone" things and charge into them before they have a chance to be delayed. Get them out of the way first. 40 | - identify some "energising" things and schedule them for strategic points in the day 41 | - don't try to fit too much into one day, otherwise it builds a habit of procrastination-by-default. Much better for personal discipline to deliberately schedule something for tomorrow, or next monday 42 | -------------------------------------------------------------------------------- /_notes/2017-06/30-059.md: -------------------------------------------------------------------------------- 1 | # Today VS Tomorrow 2 | 3 | I can categorise my work between **today stuff** and **tomorrow stuff**. In other words: 4 | 5 | - **today**: everyday management, admin, followups, checkins, etc. Small-picture details to keep things moving. 6 | - **tomorrow**: planning, investigating new opportunities. Big-picture value. 7 | 8 | Ideally I want to be spending the majority of my time in tomorrow-land. And that means finding ways to deal with the today-stuff so I'm not bogged down. 9 | 10 | This is where "creating time" comes in. The time I can create is _time for tomorrow stuff_. Time is created by reducing today stuff: 11 | 12 | - **do it more efficiently.** Can things be batched or automated? 13 | - **do less.** Are these things really necessary? What is their value in relation to other things? 14 | - **delegate.** Can someone else do it? 15 | -------------------------------------------------------------------------------- /_notes/2017-06/30-060.md: -------------------------------------------------------------------------------- 1 | # travis ci 2 | 3 | 4 | 5 | ## detecting the travis environment 6 | 7 | `process.env.TRAVIS` is a handy way to tell whether your code is running on travis 8 | 9 | ## running karma tests in chrome 10 | 11 | Previously I only knew how to run karma tests in phantomjs, when using travis. This is fine for some things but falls apart when you need a more realistic browser environment. 12 | 13 | Turns out there's a way to use chrome in travis. 14 | 15 | - First you need to [add a `before_install` section in the `.travis.yml` config](https://github.com/joshwnj/react-visibility-sensor/pull/54/files#diff-354f30a63fb0907d4ad57269548329e3R7) 16 | - [Tell karma to use chrome when running on the travis environment](https://github.com/joshwnj/react-visibility-sensor/pull/54/files#diff-a2a3b7b0c9c3b4b93b4aebf4e3ec3cfbR52) 17 | - [Configure the `Chrome_travis_ci` browser](https://github.com/joshwnj/react-visibility-sensor/pull/54/files#diff-a2a3b7b0c9c3b4b93b4aebf4e3ec3cfbR55) 18 | 19 | Thanks to for introducing me to this! 20 | -------------------------------------------------------------------------------- /_notes/2017-06/30-061.md: -------------------------------------------------------------------------------- 1 | # types of work 2 | 3 | In my day-to-day work I observe 4 main types of work, and I try to plan my day so that there will be elements of each, with a time of context-switch in between (even like a 5 minute walk is good). 4 | 5 | ## big-picture 6 | 7 | - planning, brainstorming, creating proposals 8 | 9 | ## small-picture 10 | 11 | - implementing & executing 12 | - can still be exploratory work: you don't always know exactly what needs to be done at this point, but you're getting into the details of a single aspect of a plan. 13 | 14 | ## review 15 | 16 | - taking stock of new information 17 | - searching for patterns 18 | 19 | ## social 20 | 21 | - following up people 22 | - meetings 23 | -------------------------------------------------------------------------------- /_notes/2017-06/30-062.md: -------------------------------------------------------------------------------- 1 | Variations on a structure 2 | 3 | There is a common problem in javascript where you have to convert a data structure from one form to another. However it's complicated as you often run out of names. 4 | 5 | eg. `var foo = { a: [1,2,3] }` is known as a "foo" object. And we have a function that expects a "foo" object. 6 | 7 | But what if we, for some reason have something that is _almost_ a foo object: `var foo = { a: '1,2,3' }`. 8 | We could just convert inline like `foo.a = foo.a.split(',')`. But if this is a common conversion we will have a lot of duplicated logic and will quickly lead to confusion. 9 | 10 | To me this is a naming problem. If we had a system of saying this is a `foo`, `foo_1`, or `foo_N` we could define more descriptively what those variations entail. And provide functions to convert from `foo_1 -> foo`. 11 | 12 | Then it becomes possible to make a rule where structures are only ever converted from one form to another via a function. And to put in checks to say "i expect this object to be of this particular form" 13 | 14 | First step is to define the "natural" structure. So in js that means date objects for dates, arrays for lists and ints / floats for number values. 15 | 16 | Now say we fetch an object over a json api. Most things should be in their natural structure, except for date objects. So the api gives us a `foo1` and we have to convert that to `foo`. 17 | 18 | Now we want to populate an edit-form with the object. Date objects are still fine, but arrays need to be serialized to comma-separated strings. And maybe some nested objects need to be flatten. So this will be `foo -> foo2`. 19 | 20 | When the form is submitted we just need a function `foo2 -> foo` and then we can also have a `foo -> foo1` to send back to the api. 21 | -------------------------------------------------------------------------------- /_notes/2017-06/30-063.md: -------------------------------------------------------------------------------- 1 | # idea: walkthroughs 2 | 3 | A `walkthrough` is an experimental approach for producing _verifiable documentation_. That is, the documentation tells us how the software is expected to work, and also gives a way to confirm whether it is working as described. 4 | 5 | The style of documentation is to describe a user's interaction with the software using a combination of text, graphics and data. 6 | 7 | ## How is this different from automated testing 8 | 9 | Unit tests and other forms of automated tests also provide a form of verifiable documentation, in that you can the tests to understand how the software should behave and you can run the tests to tell whether it's working as expected. 10 | 11 | Walkthroughs aren't intended to replace this style of testing, just to offer an alternative for certain cases where you're testing higher-level functionality and you want something more human-friendly. 12 | 13 | A key difference: unit tests and the like work by first setting up the state-of-the-world, then triggering an interaction, and then comparing the actual result to an expected result. With walkthroughs the focus is on capturing artefacts from the system (whether screenshots or data) and then comparing those reference artefacts to subsequent recordings, to see what changed. So they are less black-and-white and more difficult to fully automate, but require less overhead to create or refactor as requirements change. 14 | -------------------------------------------------------------------------------- /_notes/2017-06/30-064.md: -------------------------------------------------------------------------------- 1 | mucking around with some ideas for non-repeating audio, within a set of constraints: 2 | -------------------------------------------------------------------------------- /_notes/2017-06/30-065.md: -------------------------------------------------------------------------------- 1 | # webm quirk 2 | 3 | it seems that chrome will show a blank video if a webm has a height that is not divisible by 2? 4 | -------------------------------------------------------------------------------- /_notes/2017-06/30-066.md: -------------------------------------------------------------------------------- 1 | # wireframing 2 | 3 | The purpose of a wireframe is not so much to tell us how something will look, but to give an idea of: 4 | 5 | - what data will be present 6 | - how the data is grouped and prioritized 7 | 8 | So obviously the visual aspect is an important one (grouping and prioritizing is achieved visually) but we can still express a lot of this with text. 9 | 10 | ## Example 11 | 12 | If we wanted to describe a `Tweet` (subcomponent of a `TwitterTimeline`) we might start by listing the data we need to display: 13 | 14 | ``` 15 | - Author avatar 16 | - Author name 17 | - Author handle 18 | - Time 19 | - Body 20 | - Number of replies 21 | - Number of retweets 22 | - Number of likes 23 | ``` 24 | 25 | Next we might split into primary / secondary, to show which fields should be given visual prominance. The split between primary / secondary is dependent on use-case, and we might need to cater for a few of these at once. In this case let's say our user is browsing a timeline, so the "primary" fields should be those which help to scan for interest: 26 | 27 | ``` 28 | primary: 29 | 30 | - Author avatar 31 | - Author name 32 | - Body 33 | 34 | secondary: 35 | 36 | - Author handle 37 | - Time 38 | - Number of replies 39 | - Number of retweets 40 | - Number of likes 41 | ``` 42 | -------------------------------------------------------------------------------- /_notes/2017-06/30-067.md: -------------------------------------------------------------------------------- 1 | # Work journals 2 | 3 | Keeping a work journal is a foundational part of working in any team, but especially when the team is distributed across timezones. 4 | 5 | ## Types of entries 6 | 7 | To be really effective, a journal must be much more than just a list of stuff you did. They are a way to get behind the scenes and share your insight and process with the rest of the team. 8 | 9 | Think about the things you did, or are currently doing. For each one, see if you can describe it in the following ways: 10 | 11 | **Activity:** literal description of the thing you did. 12 | 13 | - in most cases "thing you did" should relate to 1 or more project requirements. Make sure the requirements are documented somewhere and link to them (write the docs if they don't exist, and this becomes part of the activity). 14 | 15 | **TIL:** something you learned during the activity. 16 | 17 | - Maybe it's not brand new knowledge, but you were reminded of something you learned in the past. Maybe you brushed up your knowledge with some googling / stackoverflowing. Maybe you were given some helpful advice from someone else. In any case, write about it here. 18 | 19 | **Blockers:** things that might slow or stop future progress. 20 | 21 | - Whenever you talk about a blocker, also write about what you will do in the meantime. Unless you're completely 100% blocked, make sure you don't give that impression. 22 | 23 | - Try to list potential blockers as well, like a "known unknown" or a grey-area which you're not certain about yet. 24 | 25 | - Don't be shy to talk about blockers, even if you're still making gradual progress. If something is taking you significantly longer than you expected, this is a good place to bring it up. Try to identify the reasons why it's taking longer. 26 | 27 | **Reflection:** notes arising from your experience of doing the work. 28 | 29 | - Think about future maintainers of the code, or other people doing similar activities in future. Are there things they'll need to keep in mind, or things that will make their job easier? 30 | 31 | - If you were to implement this feature again in future, are there things you would do differently? 32 | 33 | - Any known tradeoffs or pros/cons of the approach you took, especially if it has impact on other parts of the system. 34 | -------------------------------------------------------------------------------- /_notes/2017-06/30-068.md: -------------------------------------------------------------------------------- 1 | # writing a postcss plugin 2 | 3 | - 4 | 5 | - Tutorial: 6 | -------------------------------------------------------------------------------- /_notes/2017-06/30-069.md: -------------------------------------------------------------------------------- 1 | # writing tool comparison 2 | 3 | ## factors 4 | 5 | - **close-at-hand**: can I quickly send a note or a message, without much setup overhead? 6 | - **casual VS official**: is the medium suited to writing causal messages, as well as official announcements / docs? 7 | - **access granularity**: how detailed can we get with access rules, eg. public / invite-only / predefined groups? 8 | - **clear authorship**: when you view a note or message, is it clear to see who wrote each line? 9 | - **scaling / refactoring**: does the medium become unwieldy with larger groups or longer-term threads? 10 | 11 | ## scenario: write a message to someone 12 | 13 | - could be a question, an FYI, etc 14 | 15 | ### email 16 | 17 | - pro: close at hand 18 | - con: you have to know their email address, and they will get yours 19 | - con: bad for formatting (because you can't predict their client) 20 | - con: bad for long threads and large groups 21 | 22 | ### slack 23 | 24 | - pro: close at hand (assuming recipients are in the same slack) 25 | - con: if starting off as a DM, can't easily invite new people to the discussion. And creating a new private channel for every message is not scalable. 26 | - con: bad for long threads 27 | - con: bad for official docs 28 | 29 | ### google doc 30 | 31 | - pro: you can theme it if you want something "official" looking 32 | - pro: access granularity is mostly ok (assuming everyone has a google login) 33 | - con: takes a few more steps to create a doc, a few more to invite people, a few more if you want to theme it 34 | 35 | ### github issue 36 | 37 | - pro: slightly better for long threads than some others (because you can refactor the original message) but still not great 38 | - con: no granular access. It's either public to the world, or public to people who have access 39 | 40 | ## scenario: contribute to a group discussion 41 | 42 | ### email 43 | 44 | - con: ok for small things, but quickly becomes unusable with scale 45 | - con: there's no way to keep track of where the discussion is at, without regular "stocktake" messages 46 | 47 | ### slack 48 | 49 | - con: as soon as you reach multiple threads, or nested threads, things get buried 50 | - con: same "stocktake" problem as email 51 | 52 | ### google doc 53 | 54 | - pro: everyone can edit the doc to collab. Unstructured, so you can solve threading issues in a variety of ways (subheadings, etc) 55 | - con: "who said what" problem, unless everyone follows a formatting convention 56 | -------------------------------------------------------------------------------- /_notes/2017-06/30-070.md: -------------------------------------------------------------------------------- 1 | # writing 2 | 3 | I've recently set a goal to do more writing as part of my day-job. Not because it's a natural thing for me, but because I want to get better at it. Not only because writing stuff down forces me to articulate what I think about it, but it's also a way I can share that journey with others. 4 | 5 | ## format 6 | 7 | I think a blog format is most suitable for this (more than a wiki / knowledgebase format) because it lends itself more to ongoing discovery, and figuring things out on the go. 8 | 9 | ## tools 10 | 11 | What simple tools will make it easier? 12 | 13 | - quickly create a post file. Shouldn't have to look around for where to put it. Just write. 14 | - quickly link to other posts, and quote them. 15 | - lint markdown for broken links, so we can safely refactor if we need to. 16 | 17 | So far I'm leaning towards this: 18 | 19 | - every post file follows a pattern of `posts/YYYY/MM/DD/{name}.md` 20 | - sometimes a post will reference a previous post. Editor shortcut is good for creating links. 21 | - can be useful to also have `topics/{name}.md` for a long-running topic summary. Kind of link an anchor, and easy to link to. 22 | - here's a simple bash script to start: you give it a name, it creates the file and opens in your favourite editor: https://gist.github.com/joshwnj/58e3cdac8b7ccf4c41fcff2b3ad3189e 23 | -------------------------------------------------------------------------------- /_notes/2017-06/30-071.md: -------------------------------------------------------------------------------- 1 | # ffmpeg with concatdemuxer 2 | 3 | Stitch together frames to make a video: 4 | 5 | ``` 6 | file '/path/to/dog.png' 7 | duration 5 8 | file '/path/to/cat.png' 9 | duration 1 10 | file '/path/to/rat.png' 11 | duration 3 12 | file '/path/to/tapeworm.png' 13 | duration 2 14 | file '/path/to/tapeworm.png' 15 | ``` 16 | 17 | https://ffmpeg.org/ffmpeg-formats.html#concat 18 | https://trac.ffmpeg.org/wiki/Slideshow#Concatdemuxer 19 | 20 | Thanks to [@zhewison](https://github.com/zhewison) for this nice tip :) 21 | -------------------------------------------------------------------------------- /_notes/2017-06/30-072.md: -------------------------------------------------------------------------------- 1 | # js arrow functions 2 | 3 | TIL: arrow functions have no `arguments`: 4 | 5 | eg. 6 | 7 | ```js 8 | const arrowFunc = (a, b) => { 9 | // this doesn't work! 10 | console.log(arguments) 11 | } 12 | 13 | arrowFunc(1, 2) 14 | 15 | // ReferenceError: arguments is not defined 16 | ``` 17 | 18 | However, sometimes you might be tricked into thinking it _does_ exist, if your arrow function is inside a normal function: 19 | 20 | ```js 21 | function normalFunc (arg1) { 22 | const arrowFunc = (a, b) => { 23 | // this does work, but gives arguments of `func1`! 24 | console.log(arguments) 25 | } 26 | 27 | arrowFunc(1, 2) 28 | } 29 | 30 | normalFunc('yay') 31 | // { '0': 'yay' } 32 | ``` 33 | -------------------------------------------------------------------------------- /_notes/2017-06/30-073.md: -------------------------------------------------------------------------------- 1 | [Modern Jazz Quartet - Live in Japan (1981)](https://www.youtube.com/watch?v=v4ZWw9X2EMM) 2 | -------------------------------------------------------------------------------- /_notes/2017-06/30-074.md: -------------------------------------------------------------------------------- 1 | # keeping up 2 | 3 | Lately I've been realising something: I can't keep up. 4 | 5 | Maybe some people have the brains and the time to stay on top of all of the latest technology and innovation. But not me. What began as a lurking suspicion has now come into focus as a looming certainty: keeping up is not an option. 6 | 7 | It makes me look back and wonder. Because years ago I felt like, despite considerable effort, I could just about stay ahead of that curve. I never felt like I could know everything, but I was under the clear impression that _knowing enough_ was within my reach. 8 | 9 | So what changed? It often seems like things used to be simpler than they are now. Maybe they were. More likely I've just gained a better appreciation of how little I know. 10 | 11 | But at least now I can put illusions to rest. Even if I could know enough today, every year there are more people entering the industry. More talented people, each bringing their own perspective and innovation. This is a wonderful thing. But it makes the pace unsustainable. 12 | 13 | There are more competing ideas, more industry leaders, more paradigm-shifting innovations. Many of which will fail despite their brilliance, simply because it's not the right time. Trying to keep up with all of this is exhausting. 14 | 15 | Now, maybe I'm in the minority to feel this way, and most people will keep up with ease. I'm ok with that. I'll figure out what works for me. 16 | 17 | This is still an area I'm learning about, but some helpful things I'm finding are: 18 | 19 | 1. Cut out the noise. Have regular time away from twitter / rss / whatever. It's too much to be constantly bombarded with "new" and FOMO. 20 | 21 | 2. Focus on the underlying principles. It's cool to follow the herd and see where they go, but the principles don't change nearly as fast as the latest shiny things do. 22 | 23 | The best thing about gaining a deeper understanding of principles is that it gives you a better reference from which to evaluate new ideas and innovations, and understand whether the tradeoffs are worthwhile for your particular situation. 24 | -------------------------------------------------------------------------------- /_notes/2017-06/30-075.md: -------------------------------------------------------------------------------- 1 | # Team communication 2 | 3 | Asking for direction is great, but always look for opportunities to become more self-sufficient. Then you'll be able to help the next person. 4 | 5 | Consider this progression: 6 | 7 | ## _what should I do next?_ 8 | 9 | Asking what to do next is fine, but think about the extra burden this puts on your team mates. You might be unintentionally setting the expectation that they are responsible for your productivity. 10 | 11 | ## _should I do {{thing}} next?_ 12 | 13 | Better, because even though you're somewhat reliant on others for direction, you're letting them know you've thought about it. 14 | 15 | You've also potentially lowered the effort for your team members to respond. If you're on the money they can just say "yep". 16 | 17 | ## _I'll start doing {{thing}} next because of {{reasons}}._ 18 | 19 | ![](http://i3.kym-cdn.com/entries/icons/square/000/022/266/brain.png) 20 | -------------------------------------------------------------------------------- /_notes/2017-07/01-000.md: -------------------------------------------------------------------------------- 1 | # laptop research 2 | 3 | - what do I mostly do? 4 | - writing 5 | - web 6 | - video conf 7 | - video / audio recording 8 | 9 | - probably want a power pack for flights / trips with no power: 10 | - http://www.macworld.com/article/3028132/consumer-electronics/best-usb-c-battery-pack-review.html 11 | - http://www.techradar.com/news/mobile-computing/a-laptop-battery-pack-is-your-dream-travel-companion-1309777 12 | 13 | - what's the diff between macbook, macbook-pro and macbook-air 14 | - i think out of the 3 mbp base model (don't care about touchbar) is going to be the best option 15 | 16 | - to find out: does extended applecare count if you're traveling overseas? 17 | -------------------------------------------------------------------------------- /_notes/2017-07/03-001.md: -------------------------------------------------------------------------------- 1 | # idea: personal docket system 2 | 3 | - not only keeping track of stuff that needs to be done, but also looking for patterns, ways to batch & optimise 4 | -------------------------------------------------------------------------------- /_notes/2017-07/03-002.md: -------------------------------------------------------------------------------- 1 | # high-brain, low-brain 2 | 3 | tip: have some things set aside that you can do even when you're tired and uninspired. Don't waste your high-brain time on these. 4 | -------------------------------------------------------------------------------- /_notes/2017-07/04-003.md: -------------------------------------------------------------------------------- 1 | # css-modulesify windows bug 2 | 3 | - taking a look at this issue: https://github.com/css-modules/css-modulesify/issues/74 4 | - the problem (or at least part of it) is that we're using `newPath[0] !== '/'` to tell if a path is absolute, but this is a false assumption on windows (as pointed out here https://github.com/css-modules/css-modulesify/issues/74#issuecomment-193521440) 5 | - WIP branch: `fix-windows-abs-path` using the `path-is-absolute` package 6 | - running `npm test` shows a failing test... output is correct, but order is different. 7 | - doing a clean install on master to track it down. 8 | - it's the upgrade to `css-modules-loader-core` behind it. Downgrading to 1.0.0 sees tests passing again 9 | - weird: upgraded back to 1.1.0 but now the bug is gone. maybe a phantom bug caused by a version mismatch 10 | - PR: https://github.com/css-modules/css-modulesify/pull/117 11 | -------------------------------------------------------------------------------- /_notes/2017-07/04-004.md: -------------------------------------------------------------------------------- 1 | # testing reducers in a react app 2 | 3 | I worked on a project in 2015 which involved a fairly complex frontend built in react. We wanted to be able to move quickly and implement new features without breaking old ones, so it would be important to have tests in place that could tell us that all of the old features were still working correctly. 4 | 5 | What we found was that a very good place for unit tests in a react app is in the reducers. In a well-architected react frontend using redux, all of the business logic should be in the reducers, rather than in the components. So there's some good isolation there and it's easy to write unit tests that: 6 | 7 | - set up a certain state 8 | - simulate an action with certain arguments 9 | - compare the final state after the reducer has run, and assert that it is as expected. 10 | 11 | These tests were also very fast to execute, meaning we could easily run them often. With this in place we could get some continual feedback about any regressions introduced by new behaviour. 12 | 13 | An example, in pseudocode: 14 | 15 | - we have a "activity feed" component that should display the last 3 items. 16 | - If there are 3 items in the list, and 1 more is added, it should still display 3 items (with the 4th item being bumped off the end of the visible list) 17 | 18 | Our unit test looks like this: 19 | 20 | ``` 21 | import activityFeedReducer 22 | 23 | setup initial state with 3 items in the feed: [C, B, A] 24 | trigger action on activityFeedReducer: (ADD_ITEM, D) 25 | assert state shows the new item, and still only 3: [D, C, B] 26 | ``` 27 | -------------------------------------------------------------------------------- /_notes/2017-07/04-005.md: -------------------------------------------------------------------------------- 1 | # agile methodology 2 | 3 | I've worked in a few teams that followed "agile" or "scrum" processes, and I completed scrum-master certification in 2010. I think there are a lot of good ideas there, but it seems that every team I've been in has a slightly different way of doing things :) And when I talk to other people in other companies, this seems to be a common experience. 4 | 5 | One of the main takeaway principles that has helped me in the past is to have a strong focus on iterative prototyping. Rather than approaching a software problem and thinking "we've got the requirements, let's build it", I find it very helpful to find some aspect of the requirements to prototype. By this I mean: something that can be quickly built, to give interactive feedback about one or 2 individual aspects of the requirements. 6 | 7 | For example, if the app has a form with a file-upload element, I might focus on building a prototype of *just* the file upload, before building the rest of the form. Since this involves a few more moving-parts than the rest, if we build this bit first we can gain some more insight, which may affect our decision of what components to use for the rest of the form. 8 | 9 | I've also worked in teams before where we have done the whole "planning poker", sprints, and backlog grooming sessions too. I'm not certain how dogmatic I would be about it, if I were the project manager. But I think there's a lot of value to the concepts behind it, and can see the value it can bring to a team. 10 | -------------------------------------------------------------------------------- /_notes/2017-07/04-007.md: -------------------------------------------------------------------------------- 1 | very helpful screencast to get your head around css variables and how they change the way we structure css: https://www.youtube.com/watch?v=bpo1WwKa9bg 2 | 3 | [source](https://twitter.com/MikeRiethmuller/status/881747451253735424) 4 | -------------------------------------------------------------------------------- /_notes/2017-07/04-008.md: -------------------------------------------------------------------------------- 1 | # portfolio self-critique 2 | 3 | Here are a couple I wrote awhile back: 4 | 5 | - [Testing reducers](04-004.md) 6 | - [Agile methodology](04-005.md) 7 | 8 | To give more context on what I look for in a portfolio piece, the big difference between these 2 is that the "testing reducers" one gives a specific example from a project I worked on, whereas the "agile" one only gives a hypothetical example. 9 | 10 | This is what I mean when I talk about portfolio pieces that connect knowledge with experience. he more specific detail you can add about solving a real problem, the stronger it speaks of your experience. 11 | -------------------------------------------------------------------------------- /_notes/2017-07/05-009.md: -------------------------------------------------------------------------------- 1 | [Francis Chan: what is up with the number 666?](https://www.youtube.com/watch?v=ZLVAQ3EsrjI) 2 | 3 | - Revelation 13 has captured the imagination of the world. 4 | - the church is full of people who intellectually agree with what is said, but have never made an ongoing personal commitment to follow Jesus. 5 | - symbols pointing back to ancient empires, and of an empire to come which is stronger than all of them combined. 6 | - Q. what would it take for the whole world to be astonished, to the degree that people follow? 7 | - this all-powerful world leader will command war against followers of Jesus. 8 | - "had horns like a lamb, but spoke like a dragon". Looks like Jesus on the outside, but they speak the words of the devil. 9 | - Q. when everyone else in the world is doing things a certain way, and you'll be killed if you don't, will you still then choose your actions rationally, based on what you know to be true? 10 | -------------------------------------------------------------------------------- /_notes/2017-07/24-012.md: -------------------------------------------------------------------------------- 1 | webaudio pain points 2 | 3 | - creating a source, and then multiple filters / gains / etc. 4 | - you have to create each one in turn, and then connect them all together. And then elsewhere in code you have to remember which one was the last, so you can connect to the ac destination 5 | - would be easier if you could just create-and-connect in one operation 6 | - could also have a convention of `volumeIn` and `volumeOut` gains at either end of the pipe. Could be useful, could be wasteful, not sure yet. 7 | -------------------------------------------------------------------------------- /_notes/2017-07/24-013.md: -------------------------------------------------------------------------------- 1 | # functions that know how to do one thing 2 | 3 | I came across some code like this today: 4 | 5 | ```js 6 | handleSubmit (formData) { 7 | const { actions, doc } = this.props 8 | actions.save({ 9 | ...formData, 10 | someField: parseInt(formData.someField, 10) 11 | }, doc) 12 | } 13 | ``` 14 | 15 | and while it's not terrible, it stands out that this function is doing more than it should. It knows how to: 16 | 17 | 1. normalize the form data (convert `someField` to an int) 18 | 1. call the `save` action 19 | 20 | If we rewrite those two things as separate functions: 21 | 22 | ```js 23 | normalizeFormData (data) { 24 | return { 25 | ...data, 26 | someField: parseInt(data.someField, 10) 27 | } 28 | } 29 | 30 | handleSubmit (formData) { 31 | const { actions, doc } = this.props 32 | actions.save(this.normalizeFormData(formData), doc) 33 | } 34 | ``` 35 | 36 | Now it reads more clearly, and we have an easy place to unit-test some edge cases in the `normalizeFormData` pure function. 37 | 38 | We've also gained some useful encapsulation. The `handleSubmit` function only needs to know about forwarding the data to the right place. All of the knowledge of the nature of that data is contained in the `normalizeFormData` function. 39 | -------------------------------------------------------------------------------- /_notes/2017-07/25-013.md: -------------------------------------------------------------------------------- 1 | # gwen 2 | 3 | Trying it out: 4 | 5 | - installed latest binary following these instructions: https://github.com/gwen-interpreter/gwen-web/wiki/Installation 6 | - installed geckodriver: https://github.com/mozilla/geckodriver/releases/tag/v0.18.0 7 | - configured gwen to use it: https://github.com/gwen-interpreter/gwen-web/wiki/Runtime-Settings 8 | - ran the example: 9 | 10 | ``` 11 | ./gwen -b features/todo/tables/TodoTable.feature 12 | ``` 13 | 14 | seems to work well 15 | -------------------------------------------------------------------------------- /_notes/2017-07/25-014.md: -------------------------------------------------------------------------------- 1 | # john cleese on creativity 2 | 3 | [listen](https://soundcloud.com/londonscreenwriters/john-cleese-on-creativity) 4 | 5 | - "open and closed" 6 | - creativity thrives when we are "open" and playful, not stressed and time-constrained 7 | 8 | - alfred hitchcock mistrusted working under pressure: "we're pressing, we're working too hard" 9 | - co-writer: when we came to a blocker, hitchcock would suddenly stop and tell a story that was almost completely unrelated. He did this deliberately! 10 | 11 | - switching between "open" and "closed" is a way to be both creative & productive, for optimal efficiency 12 | - open: play, experiment, go on tangents 13 | - closed: focus on 1 thing 14 | - open: review how that went, look at the big picture 15 | - closed: refine and refocus 16 | 17 | - the problem is, we all too often get stuck in the closed mode. Creativity is not possible in the closed mode 18 | 19 | - a laugh happens when 2 ideas are connected in a new way, that generates some unexpected meaning or significance 20 | - computers can generate billions of possible connections and juxtapositions, but they will not be able to tell which ones "smell interesting" (intuition) 21 | -------------------------------------------------------------------------------- /_notes/2017-07/26-015.md: -------------------------------------------------------------------------------- 1 | # Q. how to get the most out of docker build cache? 2 | 3 | Thoughts: 4 | 5 | - each line in the Dockerfile can be considered a cache-layer. If something changes and causes a layer to require rebuild, all following layers need a rebuild too. 6 | 7 | - structure the file so that more-expensive-and-less-likely-to-change things are as close to the top of the file as possible. 8 | 9 | - think about scenarios where things do change, and look at which expensive layers are invalidated. 10 | 11 | - say we have 2 costly (time-consuming) layers, A and B. 12 | - in scenario 1, only A needs to be rebuilt 13 | - in scenario 2, only B needs to be rebuilt 14 | 15 | - the problem here is that no matter which way you order it, you always end up doing some unnecessary rebuilding. (check: is this assumption correct?!) 16 | 17 | - it might be possible in this situation to improve by splitting A and B into 2 separate Dockerfiles 18 | -------------------------------------------------------------------------------- /_notes/2017-07/26-016.md: -------------------------------------------------------------------------------- 1 | > A nail is driven out by another nail; habit is overcome by habit. 2 | ― Erasmus 3 | -------------------------------------------------------------------------------- /_notes/2017-07/26-017.md: -------------------------------------------------------------------------------- 1 | > You can make anything by writing. 2 | ― C.S. Lewis 3 | -------------------------------------------------------------------------------- /_notes/2017-07/31-018.md: -------------------------------------------------------------------------------- 1 | # pull down a directory of files over ssh 2 | 3 | ``` 4 | rsync -arv host:/path/to/files . 5 | ``` 6 | -------------------------------------------------------------------------------- /_notes/2017-08/03-000.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: Thu Aug 03 2017 11:39:21 GMT+1000 (AEST) 3 | --- 4 | 5 | # spectacle 6 | 7 | [source](https://github.com/FormidableLabs/spectacle) 8 | 9 | - using boilerplate, seems like a great way to get started 10 | 11 | - I wonder if there's a way to hook into forward / backward events, so I could for example add a css class instead of the usual `` behaviour 12 | 13 | ## styling 14 | 15 | I'm finding the builtin styling approach a bit confusing, but starting to see the rationale behind it: 16 | 17 | designed to be adaptive: https://github.com/FormidableLabs/spectacle/issues/172 18 | 19 | > Your base content area is 1000px x 700px. If you go below that, in width or height, it begins to scale the content using css transforms. 20 | 21 | The problem is that this appears to be sometimes happening unintentionally, which results in my base font sizes jumping around. 22 | 23 | I'm trying out adding `.spectacle-slide { max-height: 700px }` and see if I get more control that way. 24 | 25 | So far so good 26 | 27 | ``` 28 | cmz('spectacle-slide', ` 29 | max-height: 700px 30 | `).toString() 31 | ``` 32 | 33 | ## thoughts 34 | 35 | - I like a lot of the things that it does, but I can't help feeling it's doing a lot more than what I want... 36 | -------------------------------------------------------------------------------- /_notes/2017-08/04-001.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: Fri Aug 04 2017 09:55:28 GMT+1000 (AEST) 3 | --- 4 | 5 | https://github.com/s3ththompson/md-directory looks like just what I need for publishing journals. 6 | 7 | also should try https://github.com/cerebral/marksy to see whether it's an easier way to parse / manipulate. 8 | -------------------------------------------------------------------------------- /_notes/2017-08/04-002.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: Fri Aug 04 2017 10:38:04 GMT+1000 (AEST) 3 | --- 4 | 5 | - trying [`react-json-graph`](https://github.com/antonKalinin/react-json-graph) for journal viz 6 | - I really like the look of it but haven't been able to get it working after a few quick tries, so I'll move on for now, and maybe try again later. 7 | -------------------------------------------------------------------------------- /_notes/2017-08/04-003.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: Fri Aug 04 2017 10:43:26 GMT+1000 (AEST) 3 | --- 4 | 5 | [Kevlin Henney - Seven Ineffective Coding Habits of Many Programmers](https://vimeo.com/97329157) 6 | 7 | - "weird ways of looking at code, to understand it better". Some cool ideas about how visualising code. 8 | - I like this idea of a tag cloud as a way of surfacing information. Not sure if it's useful for every case, but there's something there... 9 | -------------------------------------------------------------------------------- /_notes/2017-08/07-004.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: Mon Aug 07 2017 15:38:36 GMT+1000 (AEST) 3 | --- 4 | 5 | # learning about electron & chrome remote debugger 6 | 7 | - trying to use `chrome-remote-interface` to dynamically update js source at runtime, following example here: https://github.com/cabul/electron-hot/blob/master/lib/index.js 8 | 9 | - I can see the script ID, it appears to be the same each time I run (although I do expect it will change at some point in future) 10 | 11 | - calling `client.Debugger.setScriptSource` 12 | - seems to be firing the error callback with an arg of `true` 13 | - ahh ok looks like `scriptId` needs to be a string, not an int 14 | 15 | - found this example here too: https://gist.github.com/paulirish/920a260cadfe05e8388c 16 | 17 | - `getScriptSource` is working, not seeing any change after calling `setScriptSource` though 18 | 19 | - but if I call `getScriptSource` a second time, I do see the new source. So it was set, it just didn't do anything in the browser window 20 | 21 | - one big roadblock here: as soon as I open the debugger console in the electron BrowserWindow, my remote debugger websocket requests all fail 22 | - looks like someone else found this too: https://gitter.im/mattdesl/wtch?at=54dceedde0d4eb7f0a49b6c1 23 | 24 | - at some point I'll try to make a small demo showing this stuff. 25 | 26 | - there seems to be some aggressive caching of `