Wednesday, December 07, 2022

Writing software is all about mastering abstraction.

 Writing software is all about mastering abstraction.

When modelling a problem in software you are always ignoring some details and representing others. Hopefully capturing all the ones that influence the desired behaviour of the system.
eg. Does Github need the weight of each developer? Will it behave differently for people based on that data? no? then no.. don't capture that aspect of the world.When modelling a problem domain, we frequently see a way we can 'think about the problem' ... usually some sort of analogy. Typically we do this to remove duplication (which is one indication that a useful abstraction may exist).
eg. So... when the users save the reports we could think of those as "save-requests" and "queue" them and have a "worker" "process" them all.
When we introduce that analogy to the code, then when someone is reading the code they have to now understand the intended behaviour of the system, and the abstraction we have chosen to use to help solve the problem.Every step we take away from describing the actual problem in code is a mental step the reader has to take to understand the solution. This is extra work paid every time you reason about the code. So... the abstraction has to have enough value to be worth including. eg. it make the code easier to think about or much faster to execution or more composeable....When we pick the wrong abstraction, the code is harder to read, harder to think about, and the building blocks are hard to assemble into the behaviour we want. They tend to have unintended side effects, and do extra work in-case it's needed, the slows down performance.Refactoring verbose code into some sort of abstraction is fairly easy.
Refactoring abstract code from the wrong abstraction to a better one is usually much harder.So... what abstractions do we have in our code? What do they make easy? What do they make hard? Are they helping us or getting in the way?

Thursday, August 18, 2022

There's something inherently satisfying about 'putting in the plumbing'

I think it's one of the things that makes highly productive developers. The ability to identify and remove friction from the things you do every day.

I like things I can rely on. So I make simple things that do one thing... then rely on them do to that thing for me, so I can think at a higher level of abstraction.I wrote a script to go grab all the env vars from an environment, so I can set up my machine to connect to that environment correctly.

I wrote a script to launch 'docker-compose -f docker-compose-localRemotedb.config %$'  so I don't have to think about it any more. ... then it grew... to include sending my ssh key.. and soon to set up the env variables for me based on the output of the other script 
:wink:Anything that makes me able to type what I'm trying to achieve and it does it... instead of telling the computer a series of commands to get it to do something. :slightly_smiling_face:

The natural extension of this is devops.  I want to just say "i'm happy with this" and it gets checked and rolled out for me.
When learning Lisp the language itself is so light weight... that if you want to do anything you end up making your own abstractions and data structures...etc.  so in effect you end up defining your domain specific language for the problem you are solving... then define your solution in terms of that language.This mindset of "this code is defines a concept" and "this code explains my intention in terms of that concept" is key to accelerating as you work.

If the concepts you create align with how your domain experts (customers?) talk about the business domain you are working in.. then the likelyhood is that your solution will be something experts can read and agree with. Also..it's likely that when you learn more about the domain you will be able to refine your definitions of those terms and your code will keep working.
If you model someone's solution with a metaphore... like "So you can think of your customers as being on a conveyer-belt being dipped in different colors of products" .. then when your next requirement comes in.. you will probably have to drop the metaphore and re-write the code.

Saturday, November 06, 2021

Remap keys on Ubuntu keyboard.

 I finally found the right way to remap keys in Ubuntu. 

This only works for later versions of udev so check your version.

udevadm --version

Should be 240+

sudo systemd-hwdb update   # if it's not

First find the keyboard to remap

sudo evtest

pick the keyboard by event id. Note the id (say it's 4)

press keys you want to remap and note the 'value' on the MSC_SCAN line on the key you want to change

press the key you want to map to and note the KEY_XXXX code

We will need the modalias, so 
> cat /sys/class/input/event4/device/modalias

Now you need to make a file
sudo gedit  /etc/udev/hwdb.d/10-my-modifiers.hwdb 

Here is mine:

evdev:input:b0011v0001p0001*
 KEYBOARD_KEY_db=leftalt
 KEYBOARD_KEY_38=leftmeta


The format needs to be exact. There is one space before KEYBOARD_XXX.
The key codes are lowercase.

So now you need to load the config
> sudo udevadm trigger
> udevadm info /dev/input/event4 | grep KEYBOARD

You should see your mappings are active.

Now even if you reboot your mappings should still be there. 









Thursday, May 13, 2021

Do I have anything I should have pushed?

I have a code folder. Under that I have subfolders for each repo I use. 

Do I have any work in any of these folders that needs pushing? 

 for /d %d in (*) do (pushd %d && git branch && popd || popd)

all on master.. so nope.


Friday, July 10, 2020

Refactoring In React: Class based components to Functional

I have a react class component I wanted to change to a functional one (to make refactoring easier)... I tried converting it.. but at the end the tests no longer ran. 

I wanted a way to incrementally convert it from one form to the other, so I could take smaller steps and run the tests after each step.

I wrapped the existing class based Component in a functional one. Renaming the existing one to InnerX and naming the functional one X.  Then I passed app props though to the existing InnerX. This adds no functionality but wrapping the component. I then moved the state from InnerX to X and passed it down via props. Then one at a time moved each function, running tests after each step... passing them as props. Any time anything failed I could rollback a step and try a different function with less dependencies.

Anyway... I share as it seems to be a useful technique if you are stuck.

GitHub Projects