Programmer, How Do You Format Your Programming Notes?

To a programmer to another programmer, how do you format your programming notes?

I’m also curious of how others handle this as well. I’ve naturally started creating “index” notes, which I believe to be similar to the map of content (MOCs) concept. For example, I have “index_Python,” then that may lead to other index notes (“index_Python_dates”) or atomic notes.

I have less than 100 notes in my vault right now, so I can’t speak to whether this is scalable or not, but it has already proven to be valuable. I’m getting deeper into my Linux notes now, so I think that will put the scalability of my system to test.

Some of my non-index notes as way too long, so I’m looking into ways of breaking them up without creating a proliferation of index notes.

I’m also reading about using timestamp IDs for note names, but I’m not yet sold on how exactly that would impact programming / technical notes. I also don’t really understand how to find the note I need when I’m wanting to link to that note. So when I type “[[”, if it were to open hundreds of notes that start with “2021*”, that seems overwhelming and confusing. Maybe I’m thinking too much about authoring on the mobile app though. I suspect it would be easier on desktop where you could have several notes open at once and link them that way.

Right now I have several different things I am doing that are programming related.

For my SQLite Database structure for LambTracker and AnimalTrakker programs I am putting the create statements for the tables in an Obsidian note with the actual create statements as code like this:

AnimalTrakker Database Table Definitions

#AOF/LambTracker_AnimalTrakker

animal_external_file_root_folder_table

CREATE TABLE "animal_external_file_root_folder"
    ( "id_animalexternalfilerootfolderid" INTEGER PRIMARY KEY NOT NULL
    , "absolute_path_root" TEXT
    )

birth_type_table

CREATE TABLE "birth_type_table" 
    ( "id_birthtypeid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE 
    , "birth_type" TEXT
    , "birth_type_abbrev" TEXT
    , "birth_type_display_order" INTEGER
    )

cluster_calculation_type_table

CREATE TABLE "cluster_calculation_type_table" 
    ( "id_cluster_calculation_typeid" INTEGER PRIMARY KEY NOT NULL
    , "cluster_calculation_type" TEXT
    , "cluster_type_display_order" INTEGER
    )

Then my notes that are the rough outline of code I need to write are just standard notes like this example

# Add sire and dam sheep_id to a lambs record
Pseudocode flowchart on how to handle the temporary_registration_cross_ref_table inputs

for each record in the table
1.  read the record and get the sheep ID number of the animal we need to get the sire and dam for
2.  Using the sire reg number look up the record in the sheep_registration_table and get the sire's sheep_id
3.  Verify that the animal is a male, if not throw an error and move on
4.  Verify that the animal was born before the offspring you are adding the sire to, if not throw and error and move on
5.  Using the dam reg number look up the record in the sheep_registration_table and get the dam's sheep_id
6.  Verify that the animal is a female, if not throw an error and move on
7.  Verify that the animal was born before the offspring you are adding the sire to, if not throw and error and move on
8.  Look at the original sheep record and see if a sire or dam has been entered. If so verify that the ones we found are the same , if not throw and error.
9.  If no sire or dam is listed for the sheep then update the sheep record in the sheep_table by adding the sire and dam sheep_id's into the sire_id and dam_id fields of the original sheep.
10. If it is successful then we can delete the record in the temporary_registration_cross_ref_table. Or perhaps mark it as completed because it may take several passes to get through them all. 
 Errors will include issues when the record we are working on has sheep that are not yet in the sheep_registration_table or cannot be found.
 
If that happens we need to leave the record in the temporary_registration_cross_ref_table and try again on a later pass once more records are in the sheep_registration_table

We then need a way to verify the results and make sure it's all ok.

I have notes that are basically a MOC of the various modules.

I also have notes that are MOCs that are links to other resources like a bunch of sites that have info on tkinter and python programming.

I have individual notes that are the SQLite queries I use to get data and I have both finished ones and in process ones. They have the query formatted as code like this.

#AOF/LambTracker_AnimalTrakker

get_overall_list_new_database

-- Gets whole list of current sheep properly including sheep without a sire or dam or without EBVs
-- This version only gets sheep located at Contact number 1 which is at Garvin Mesa

SELECT 
    sheep_table.sheep_id
    , (SELECT 
        tag_number 
        FROM id_info_table 
        WHERE 
            official_id = "1" 
            AND id_info_table.sheep_id = sheep_table.sheep_id 
            AND  (tag_date_off IS NULL OR tag_date_off = '')) 
        AS fedtag
    , (SELECT 
        tag_number 
        FROM id_info_table 
        WHERE 
            tag_type = "4" 
            AND id_info_table.sheep_id = sheep_table.sheep_id 
            AND  (tag_date_off IS NULL OR tag_date_off = '')) 
        AS farmtag
    , (SELECT 
        tag_color_name
        FROM tag_colors_table
                INNER JOIN id_info_table ON tag_colors_table.id_tagcolorsid = id_info_table.tag_color_male
        WHERE 
            tag_type = "4" 
            AND id_info_table.sheep_id = sheep_table.sheep_id 
            AND  (tag_date_off IS NULL OR tag_date_off = '')) 
        AS farmtagcolor
    ,(SELECT 
        tag_number 
        FROM id_info_table 
        WHERE 
            tag_type = "2" 
            AND id_info_table.sheep_id = sheep_table.sheep_id 
            AND (tag_date_off IS NULL OR tag_date_off = '') 
            AND ( id_info_table.official_id IS NULL OR id_info_table.official_id = 0 OR id_info_table.official_id = "")) 
        AS eidtag
-- Can add or delete items here by adding or removing -- in front of the item.
--  , flock_prefix_table.flock_name
    , sheep_table.sheep_name
    , codon136_table.codon136_alleles
    , codon141_table.codon141_alleles
    , codon154_table.codon154_alleles
    , codon171_table.codon171_alleles
--  , sheep_evaluation_table.trait_score11 as weight
--  , sheep_evaluation_table.age_in_days
    , sheep_ebv_table.usa_maternal_index
    , sheep_ebv_table.self_replacing_carcass_index
--  , sheep_ebv_table.ebv_birth_weight
--  , sheep_ebv_table.ebv_wean_weight
--  , sheep_ebv_table.ebv_post_wean_weight
--  , sheep_ebv_table.ebv_hogget_weight
--  , sheep_ebv_table.ebv_adult_weight
--  , sheep_ebv_table.ebv_post_wean_scrotal
--  , sheep_ebv_table.ebv_number_lambs_born
--  , sheep_ebv_table.ebv_number_lambs_weaned
--  , sheep_ebv_table.ebv_maternal_birth_weight
--  , sheep_ebv_table.ebv_maternal_wean_weight
--  , sheep_ebv_table.ebv_lambease_direct
--  , sheep_ebv_table.ebv_lambease_daughter
--  , ( 
--      sheep_table.birth_type
--      + sheep_table.codon171 
--      + sheep_evaluation_table.trait_score01 
--      + sheep_evaluation_table.trait_score02 
--      + sheep_evaluation_table.trait_score03 
--      + sheep_evaluation_table.trait_score04 
--      + sheep_evaluation_table.trait_score05 
--      + sheep_evaluation_table.trait_score06 
--      + sheep_evaluation_table.trait_score07 
--      + sheep_evaluation_table.trait_score08 
--      + sheep_evaluation_table.trait_score09 
--      + sheep_evaluation_table.trait_score10
--      ) AS overall_score
--  , sheep_evaluation_table.sheep_rank
    , cluster_table.cluster_name
    , sheep_table.birth_date
    , sex_table.sex_abbrev
    , birth_type_table.birth_type
    , sire_table.sheep_name as sire_name
    , dam_table.sheep_name as dam_name
    , sheep_table.alert01
    
    FROM 
        (SELECT
            sheep_id, MAX(movement_date)
            , to_id_contactsid
            , id_sheeplocationhistoryid
        FROM sheep_location_history_table
        GROUP BY
            sheep_id) 
        AS last_movement_date

INNER JOIN sheep_ownership_history_table ON sheep_table.sheep_id = sheep_ownership_history_table.sheep_id 
INNER JOIN sheep_table ON sheep_table.sheep_id = last_movement_date.sheep_id
INNER JOIN codon136_table ON sheep_table.codon136 = codon136_table.id_codon136id 
INNER JOIN codon141_table ON sheep_table.codon141 = codon141_table.id_codon141id 
INNER JOIN codon154_table ON sheep_table.codon154 = codon154_table.id_codon154id 
INNER JOIN codon171_table ON sheep_table.codon171 = codon171_table.id_codon171id 
LEFT JOIN birth_type_table ON sheep_table.birth_type = birth_type_table.id_birthtypeid 
LEFT JOIN sex_table ON sheep_table.sex = sex_table.sex_sheepid 
LEFT JOIN sheep_table AS sire_table ON sheep_table.sire_id = sire_table.sheep_id
LEFT JOIN sheep_table AS dam_table ON sheep_table.dam_id = dam_table.sheep_id
LEFT OUTER JOIN  sheep_cluster_table ON sheep_table.sheep_id = sheep_cluster_table.sheep_id
LEFT  JOIN cluster_table ON cluster_table.id_clusternameid = sheep_cluster_table.id_clusterid
-- LEFT JOIN flock_prefix_table ON sheep_table.id_flockprefixid =flock_prefix_table.flock_prefixid 
LEFT OUTER JOIN sheep_ebv_table ON sheep_table.sheep_id = sheep_ebv_table.sheep_id 
-- INNER JOIN sheep_evaluation_table ON sheep_evaluation_table.sheep_id = sheep_table.sheep_id

--  Edit the date to be the most recent run of EBV data by changing the date below
--  Modify this to be the latest EBV run date. Should be a way to get this automatically .
        AND sheep_ebv_table.ebv_date LIKE "2020-11%"

WHERE 
    sheep_table.death_date = "" 
    AND  sheep_ownership_history_table.to_id_contactsid = '1'  
    AND sheep_table.id_sheepbreedid = 1 
    AND  last_movement_date.to_id_contactsid = 1

--  If want to add evaluations add this and uncomment the last INNER JOIN above
--      AND eval_date LIKE "2019-11-%"

-- To get only a single sex add this in the WHERE clause
-- Edit for sex by making Ram sex = 1 Ewe Sex = 2 Wether sex = 3 
--      AND sheep_table.sex = 1 

-- To get no butcher or sell add this in the WHERE clause
--      AND (sheep_table.alert01 NOT LIKE "%Sell%" 
--      AND sheep_table.alert01 NOT LIKE "%Butcher%")

-- To get only butcher or sell add this in the WHERE clause
--      AND (sheep_table.alert01 LIKE "%Sell%" 
--          OR sheep_table.alert01 LIKE "%Butcher%")

-- To get only a specific alert add this in the WHERE clause
-- Change the text between the % to be what alert you are looking for. 
-- Common ones include Sell, Butcher, Keep and so on.  
--      AND sheep_table.alert01 LIKE "%Sell%"
--      AND sheep_table.alert01 NOT LIKE "%Ship%"

-- To get only older sheep not current year lambs add this in the WHERE clause changing the year as required
-- To get only this years lambs change the < to a > 
-- To get a specific year change the < to LIKE 
--      AND sheep_table.birth_date < "2021%"

ORDER BY 
    sex_table.sex_abbrev ASC
    , cluster_table.cluster_name
    , sheep_ebv_table.self_replacing_carcass_index DESC
    , sheep_table.birth_date ASC

I am slowly moving my various ideas, bugs, feature requests and future plans etc into Obsidian as just individual notes but linked to the module so I’ll end up with a MOC type note that has sections for Current Bugs, Feature Requests, Documentation etc. I am looking at the kanban plug-in in Obsidian to see if that makes sense for the things I am working on now and also considering how or whether to publish stuff out of Obsidian into Git.

All very much a work in progress. I’m trying to consolidate things that are currently living in Scrivener, DEVONThink, Plain text files, email messages and Libre Office files and it’s slow going.

1 Like

Similar to @chmod764 I have index notes for each technology I work with (though I call them cheatsheets). Each “cheatsheet” links to other notes that detail how to do a particular thing for that technology. For example, for git I have a bunch of useful git commands for things I don’t do often enough to have memorized. Another example, is that I have notes for common testing patterns in rspec (a testing library for ruby). For example, how to set up object mocks in a specific way. Again, these are things I do often enough that it’s helpful to have a reference that’s easy to look up. Instead of bookmarking a stackoverflow link or whatever, I store it in Obsidian along with some notes explaining how/why something works a particular way.

Also in the cheatsheets, I may link to notes that explains a concept particular to that technology. For example, I have a bunch of notes related to metaprogramming in my ruby cheatsheet that explain how metaprogramming works in ruby.

Since my cheatsheets are very example heavy and directly related to a particular technology, there not a lot of dense linking between the notes. Most of the notes link to a single cheat sheet and that’s it. I try to focus on discoverability over linking ie When I want to do this particular thing, how can I make it easy to find this example? Most of the time, I know I can open up the cheatsheet and quickly find the notes that shows me how to do the thing I want to do.

I also have index notes for technology agnostic notes (design patterns, programming principles, programming concepts etc) Each note will focus on a single pattern/principle/idea and explain what it is and how it works. There are more links between my technology agnostic notes as I’ll try to compare and contrast different principles to explain how they are related. Right now, I get most of these notes from books and videos so I try to link the source as well.

I’m working on making my notes more atomic. I feel like I end up creating notes like “Caching” that end up containing a lot of ideas about caching techniques and when/why caching is useful. These could probably be broken down into smaller notes. However, for the time being I know that if I want to look up something related to caching, the “Caching” note is probably a good place to start.

1 Like