<?xml version="1.0" encoding="UTF-8" ?>

    <feed xmlns="http://www.w3.org/2005/Atom">
        <title>David Vedvick (Notes Feed)</title>
        <id>http://davidvedvick.info/notes</id>
         <link href="http://davidvedvick.info/notes" />
         <link href="http://davidvedvick.info/notes/atom.xml" rel="self" />
         <updated>2026-04-03T15:22:23.000Z</updated>
         <author>
            <name>David Vedvick</name>
            <email>dvedvick@gmail.com</email>
         </author>
        <entry>
   <title>Double the taskbar size... . necessary?</title>
   <link href="http://davidvedvick.info/notes/2009/03/02/double-the-taskbar-size-necessary" />
   <updated>2009-03-02T17:43:35.000Z</updated>
   <id>http://davidvedvick.info/notes/2009/03/02/double-the-taskbar-size-necessary</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Double the taskbar size... . necessary?&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/03/background-300x187.png&quot; alt=&quot;background&quot; /&gt;So I&apos;m thinking of going double the size for my taskbar in Windows 7.  Worth it?  I don&apos;t know yet, it&apos;s my experiment in usability.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Exciting Stuff</title>
   <link href="http://davidvedvick.info/notes/2009/08/17/exciting-stuff" />
   <updated>2009-08-18T01:36:53.000Z</updated>
   <id>http://davidvedvick.info/notes/2009/08/17/exciting-stuff</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Exciting Stuff&lt;/h1&gt;
&lt;p&gt;Working on exciting stuff here in the batcave.  The new &lt;a href=&quot;http://store.devedcomputers.com/CreateOrder.php&quot;&gt;computer configuration doo-hickey&lt;/a&gt; is now available and is 99% complete.  Go ahead and test it out, build a computer, have fun.  Order one, if you like, as well.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Space Shuttle Launch</title>
   <link href="http://davidvedvick.info/notes/2009/08/24/space-shuttle-launch" />
   <updated>2009-08-25T02:21:08.000Z</updated>
   <id>http://davidvedvick.info/notes/2009/08/24/space-shuttle-launch</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Space Shuttle Launch&lt;/h1&gt;
&lt;p&gt;The launch of Space Shuttle STS-128 is &lt;a href=&quot;http://www.space.com/spaceshuttle/index.html&quot;&gt;about to take place&lt;/a&gt;.  This is going to be a night time watch, and these things are always the coolest to watch.  Although day time ones are cool too. I highly recommend watching one of these if you never have.  I would like to see one live myself.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Windows 7 RTM Coming Up</title>
   <link href="http://davidvedvick.info/notes/2009/08/28/windows-7-rtm-coming-up" />
   <updated>2009-08-29T02:53:34.000Z</updated>
   <id>http://davidvedvick.info/notes/2009/08/28/windows-7-rtm-coming-up</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Windows 7 RTM Coming Up&lt;/h1&gt;
&lt;p&gt;NDSU has had the kind heart to loan me a Windows 7 key for personal use.  Hopefully it turns out.  I&apos;ll try to get back to everyone on the quality of Windows 7 here in a bit. A few words though, before the installation occurs.  I&apos;m currently using Windows 7 RC (Release Candidate), and I can say that it is rock-hard stable.  The only place, in my mind, that the Release to Manufacturer&apos;s release has is to go up. In other news, I&apos;m listening to &lt;em&gt;&apos;Abel&apos;&lt;/em&gt; by The National, and it&apos;s awesome.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Firefox Useability Enhancements</title>
   <link href="http://davidvedvick.info/notes/2009/08/29/firefox-useability-enhancements" />
   <updated>2009-08-29T20:16:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2009/08/29/firefox-useability-enhancements</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Firefox Useability Enhancements&lt;/h1&gt;
&lt;p&gt;So we&apos;ve all been enchanted by the simplicity and usability of Google Chrome, correct?  Well, if you haven&apos;t, then I highly recommend downloading it. However, overall  I prefer many of the features of Firefox, and even some of the UI decisions of the open source browser, so I prefer to use it for my everyday browsing needs.  Even so, I find myself missing Google&apos;s Aero Glass integration and such.  So I decided to look for ways to integrate some of these with Firefox&apos;s add-on support.  Here&apos;s my list of what I added to make Firefox more usable by today&apos;s standards:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;h2&gt;Firefox &quot;Windows 7 Remix&quot; theme:&lt;/h2&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://addons.mozilla.org/en-US/firefox/images/p/35581/1249846734&quot; alt=&quot;Windows 7 Remix Theme&quot; /&gt;
**&lt;/p&gt;
&lt;p&gt;I installed &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/13579&quot;&gt;this theme&lt;/a&gt; that emulates the proposed Firefox 3.7 &quot;Windows 7 Remix&quot; theme perfectly.  You also have to install the &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/12181&quot;&gt;All-Glass Firefox&lt;/a&gt; Add-on, which allows Firefox to use the Glass effect present in Windows Vista and 7.  Makes browsing look much nicer.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;h2&gt;Personal Menu&lt;/h2&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://addons.mozilla.org/en-US/firefox/images/p/22186/1213925519&quot; /&gt;
**&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/3895/&quot;&gt;This plug-in&lt;/a&gt; lets you get rid of that space-consuming menu-bar and replace it with a few IE7/8/Chrome-ish buttons.  On top of that, you can even edit the personal menu and add your own menu  items from the aforementioned traditional menu-bar to it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;h2&gt;Speed Dial&lt;/h2&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://addons.mozilla.org/en-US/firefox/images/p/15857/1187524480&quot; alt=&quot;Speed Dial Add-on&quot; /&gt;
**&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/4810&quot;&gt;Speed Dial &lt;/a&gt;has been around for awhile.  Basically allows you to have a similar Speed dial page to the one in Opera show when you open a new tab.  Useful, similar in concept to the bookmarks bar.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;h2&gt;Tabs Open Relative&lt;/h2&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The final Chrome-inspired add-on that I added was the simple &quot;Tabs Open Relative&quot;.  All it does is make links that open a new tab open the tab directly to the right of the originating tab.  Find it &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/1956&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://ted.mielczarek.org/code/mozilla/tabpreview/tabpreview.png&quot; alt=&quot;Tab Preview Add-on&quot; /&gt;
**&lt;/p&gt;
&lt;p&gt;Feeling a little inspired by Win7 I was when I was searching for an Aero Peek-ish add-on that would show my current Firefox tabs in the Aero Peek tabs in Windows 7.  Well I couldn&apos;t find any add-ons, but this&lt;a href=&quot;http://ted.mielczarek.org/code/mozilla/tabpreview/&quot;&gt; tab preview add-on&lt;/a&gt; helps out, at least.\&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;h2&gt;A tip&lt;/h2&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I would also like to add a tip this list to give you &lt;em&gt;even more&lt;/em&gt; browsing space: get rid of that worthless status bar at the bottom of the browser.  Just go to &apos;View&apos; in the menu-bar and uncheck &quot;Status Bar&quot;.&lt;/p&gt;
&lt;h2&gt;The Final Look:&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/08/firefoxaerod-274x300.png&quot; alt=&quot;Firefox now with Aero Glass&quot; /&gt;
** Well, there it is.  Hopefully, this post will be useful to anyone, including my customers, in making a better looking, more useful browser out of Firefox.  If you would like to see more posts like this, let me know in the comments section. Later, David&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Ordering a Computer on DeVed Computers</title>
   <link href="http://davidvedvick.info/notes/2009/09/01/ordering-a-computer-on-deved-computers" />
   <updated>2009-09-02T02:51:45.000Z</updated>
   <id>http://davidvedvick.info/notes/2009/09/01/ordering-a-computer-on-deved-computers</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Ordering a Computer on DeVed Computers&lt;/h1&gt;
&lt;p&gt;As some of you know, I&apos;ve recently created an application for DeVed Computers (&lt;a href=&quot;http://www.devedcomputers.com/store/CreateOrder.php&quot;&gt;found here&lt;/a&gt;), that allows you to either pick from a computer created ahead of time or to create your own.  I&apos;ve had this up for a couple of weeks, and have since kinda taken a break from all DeVed Computers related stuff (except for building and troubleshooting/repair computers, of course).  While I have tried to make this web app as self-explanatory as possible, it is probably still helpful for some to see a tutorial straight from the creator, so here goes:&lt;/p&gt;
&lt;h2&gt;Step 1:  Pick needs that reflect what you want to do with this computer&lt;/h2&gt;
&lt;p&gt;In this step, you check the boxes for things you want to do with your computer.  While I&apos;ve tried to add as many needs for a computer as possible, there&apos;s a very good chance I haven&apos;t added them all yet - if you think of one, contact me at &lt;a href=&quot;mailto:contact@devedcomputers.com&quot;&gt;contact@devedcomputers.com&lt;/a&gt; and let me know.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/08/SS-2009.08.30-23.46.53.png&quot; alt=&quot;Step 1: Pick Your Needs&quot; /&gt;
**&lt;/p&gt;
&lt;h2&gt;Step 2:  Enter a Budget for your PC&lt;/h2&gt;
&lt;p&gt;In this step, you set a top limit on what you want to spend on a new PC.  If there are existing orders in the DeVed Computers COSAS Database that reflect your  needs, they&apos;ll only show if they&apos;re under or equal to the budget you set (nifty, huh?)!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/08/SS-2009.08.30-23.58.04.png&quot; alt=&quot;Set Your Budget on this screen&quot; /&gt;
**&lt;/p&gt;
&lt;h2&gt;Step 3:  Buy a PC that&apos;s already been ordered from DeVed Computers or Create your Own&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/09/SS-2009.09.01-16.06.38.png&quot; alt=&quot;Select or Create a PC&quot; /&gt;
**&lt;/p&gt;
&lt;p&gt;Here, you can select a similar PC to yours that was previously ordered from a user whom had selected needs and a budget at your level or lower, if you wish.  If you choose to do that, proceed to Finishing ordering your computer below.&lt;/p&gt;
&lt;p&gt;Otherwise, go ahead and click the &apos;create your own PC&apos; link below the pre-configured PCs, and proceed on to the next step!&lt;/p&gt;
&lt;h2&gt;Step 4:  Select a case&lt;/h2&gt;
&lt;p&gt;So now that you&apos;ve chosen to create your own PC, the web-app has found some cases that fit your needs.  If you move your mouse over the item, you will see the item description and the price of the case.  After selecting your case, go ahead and click the &apos;next&apos; arrow.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/09/SS-2009.09.01-17.10.47.png&quot; alt=&quot;Selecting a case&quot; /&gt;
**&lt;/p&gt;
&lt;h2&gt;Step 5-10(ish):  Configuration&lt;/h2&gt;
&lt;p&gt;Complete the rest of the steps - don&apos;t worry, the app figures out the compatible items for your computer, so just pick the items that fit your budget and with the features you want.&lt;/p&gt;
&lt;h2&gt;Step 11: Finalizing your order&lt;/h2&gt;
&lt;p&gt;Now please take a moment to review your order.  If you see an item you don&apos;t want, or decide you want to change something, just go ahead and click on an item to change it!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/09/SS-2009.09.01-21.18.41.png&quot; alt=&quot;Review your order on this screen.&quot; /&gt;
**&lt;/p&gt;
&lt;h2&gt;Step 12:  Link your order to a username&lt;/h2&gt;
&lt;p&gt;Now you can go ahead and link your order to a username.  Don&apos;t worry, I don&apos;t ask for a name or address, this is just so I know who ordered that fancy computer.  Name and address get asked for later by PayPal (who has secure storage for your credit card information).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/09/SS-2009.09.01-21.25.37.png&quot; alt=&quot;Login/Create Account&quot; /&gt;
**&lt;/p&gt;
&lt;h2&gt;Last Step:  Add your computer to the PayPal Cart&lt;/h2&gt;
&lt;p&gt;This last button leads you to the PayPal cart.  From there, PayPal will take care of you.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/09/SS-2009.09.01-21.36.39.png&quot; alt=&quot;Add the Order to a PayPal Cart&quot; /&gt;
**&lt;/p&gt;
&lt;h2&gt;The Last Last Step:&lt;/h2&gt;
&lt;p&gt;Finally, if your payment goes through, your parts will be assembled and your customized PC will be shipped to you in under 3 weeks!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Computer stickers/Case Badges</title>
   <link href="http://davidvedvick.info/notes/2009/12/26/computer-stickerscase-badges" />
   <updated>2009-12-26T17:23:46.000Z</updated>
   <id>http://davidvedvick.info/notes/2009/12/26/computer-stickerscase-badges</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Computer stickers/Case Badges&lt;/h1&gt;
&lt;p&gt;Well now that school is hopefully done, I have plenty of time to post random stuff. Check out these cool &quot;case badges&quot; I bought a few months ago: &lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2009/12/wpid-2009-12-26-11.19.38.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Just did Java, on to C#</title>
   <link href="http://davidvedvick.info/notes/2011/03/20/just-did-java-on-to-c" />
   <updated>2011-03-20T23:14:06.000Z</updated>
   <id>http://davidvedvick.info/notes/2011/03/20/just-did-java-on-to-c</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Just did Java, on to C#&lt;/h1&gt;
&lt;p&gt;After the Java project that saw limited success with our client, I&apos;m moving on to a new project in which I&apos;ll be coding in C#.  Should lend me some new, valuable experience.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Starting up the development blog</title>
   <link href="http://davidvedvick.info/notes/2011/07/14/starting-up-the-development-blog" />
   <updated>2011-07-15T03:42:17.000Z</updated>
   <id>http://davidvedvick.info/notes/2011/07/14/starting-up-the-development-blog</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Starting up the development blog&lt;/h1&gt;
&lt;p&gt;So, I used to write... alot.  Truth be told, I had a lot more time on my hands.   I also had a lot of sad teenage/college experiences to talk about.  I&apos;d like to think I&apos;ve matured a bit since then, and also, since then, gained a bit of brain power (although a night at the bar&apos;s can erase that brain power a little bit).   Anyways, I plan to use this space to talk about software development, and the lessons I learn from it.  The main thrust of this blog will be, as it has been for quite some time, DeVeD Computers (name-change and new look coming soon, or at least within the next 30 years hopefully).   I am also thinking about starting up a resume page, for information about yours truly.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>A guide to initialization logic</title>
   <link href="http://davidvedvick.info/notes/2011/07/17/a-guide-to-initialization-logic" />
   <updated>2011-07-17T15:40:13.000Z</updated>
   <id>http://davidvedvick.info/notes/2011/07/17/a-guide-to-initialization-logic</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;A guide to initialization logic&lt;/h1&gt;
&lt;p&gt;I have seen many a programmer make some basic logic mistakes that could save them a lot of time and cleanliness.   The simple case is this: Let&apos;s say you want a = 5 when &quot;condition&quot; is true, and a = 4 otherwise. Below may seem the obvious way to do it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    if (condition is true) {
        a = 5
    }
    else {
        a = 4
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, there is nothing wrong with this in a basic scenario. However, if you have other nested if&apos;s where it must equal another number, it can get confusing. So let&apos;s make our conditions more complicated. Let&apos;s say if George is 5, we give him 5 apples. If George is 6, we give him 7 apples. Otherwise, we give him 4. Using the above logic and extending it, we end up with something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    if (George == 5) {
         apples = 5
    }
    else if (George == 6) {
         apples = 7
    }
    else {
         apples = 4
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once again, nothing implicitly wrong in this scenario. However, what if the age we&apos;re given for George is, say -1? Let&apos;s say, for our robust apple giving programming language, that this results in an impossible age exception. Thus, we must try and catch this language now:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    try {
         if (George == 5) {
              apples = 5
         }
         else if (George == 6) {
              apples = 7
         }
         else {
              apples = 4
         }
    } catch (AgeException AgeExc) {
         apples = 4
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here you can see the cracks in using the above logic where you set apples = 4 after you confirm &lt;em&gt;no other scenario is true&lt;/em&gt;.  You have to now set apples = 4 twice, unless you prevent this exception from occurring.  This would would like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    if (George == 5) {
         apples = 5
    }
    else if (George == 6) {
         apples = 7
    }
    else if (George &amp;lt; 0) {
         apples = 4
    }
    else {
         apples = 4
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, different code, same result, apples has to be set to 4 in two different conditions.  I could go on with examples much more complicated than this, but I will save you the time and present you a much simpler solution to the problem: &lt;em&gt;initializing apples to 4 at the beginning of the program&lt;/em&gt;.  So, if you set apples = 4 at the beginning of the program, what does our code now look like?   With the try catch block:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    apples = 4
    try {
         if (George == 5) {
              apples = 5
         }
         else if (George == 6) {
              apples = 7
         }
    } catch (AgeException AgeExc) {
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Without a try catch block:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    apples = 4
    if (George == 5) {
         apples = 5
    }
    else if (George == 6) {
         apples = 7
    }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can see here that we&apos;ve reduced the complexity of the program substantially, while reducing the programmer&apos;s risk to the otherwise apples value changing in the future (let&apos;s say we want to give George 10 apples when he&apos;s not 5 or 6 in the future), by only providing one area where the default value for Apples would need to be changed. While the logic may seem less straight forward, it just requires a different way of thinking: You must say, instead of &quot;if George is 5, we give him 5 apples. If George is 6, we give him 7 apples. Otherwise, we give him 4&quot;, &quot;George will get 4 apples no matter what. However, if he is 5, we will instead give him 5 apples, and if he is 6, we will instead give him 7 apples&quot;.  This has saved me many a time in the past from some pretty basic programming defects that could have been avoided if the amount of logic and amount of initialization had been reduced.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Neat story on some of the lost disciplines of programming</title>
   <link href="http://davidvedvick.info/notes/2011/08/06/neat-story-on-some-of-the-lost-disciplines-of-programming" />
   <updated>2011-08-06T23:40:13.000Z</updated>
   <id>http://davidvedvick.info/notes/2011/08/06/neat-story-on-some-of-the-lost-disciplines-of-programming</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Neat story on some of the lost disciplines of programming&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;http://www.itworld.com/print/190213&quot;&gt;http://www.itworld.com/print/190213&lt;/a&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>jQuery UI sort on hidden table rows</title>
   <link href="http://davidvedvick.info/notes/2011/10/02/jquery-ui-sort-on-hidden-table-rows" />
   <updated>2011-10-03T01:10:50.000Z</updated>
   <id>http://davidvedvick.info/notes/2011/10/02/jquery-ui-sort-on-hidden-table-rows</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;jQuery UI sort on hidden table rows&lt;/h1&gt;
&lt;p&gt;jQuery UI&apos;s &lt;a href=&quot;http://jqueryui.com/demos/sortable/&quot;&gt;sortable&lt;/a&gt; works great on tables in the newest version, 1.8.  I&apos;ve been using it for some pretty interesting sorting of data involving complex parent child relationships, where one row may have children directly below it. However, I recently had a major issue, where rows were flickering when you would try to move them and the placeholder would continuously jump down to the second to last row.  This was very confusing, as I had done many more complicated things with table sorting in IE8. After 5+ hours of troubleshooting that I won&apos;t go into, but will reassure you, was quite frustrating, I finally had  revelation after I stepped away from my computer:  hidden rows were in the table, and these were causing the conflicts!  jQuery UI sortable calculates the position of your sorting row by first getting the height of all the rows that can be sorted. If your table is like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &amp;lt;table&amp;gt;
         &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Row 1&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
         &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Row 1&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
         &amp;lt;tr style=&quot;display:none&quot;&amp;gt;&amp;lt;td&amp;gt;Row 3&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
         &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Row 4&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
    &amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You will discover that, at least in IE8, your table sorting will not work work as expected.  You will see various flickering issues and rows being dropped in the incorrect places if you just do a basic jQuery UI sortable declaration: &lt;code&gt;$(&apos;table&apos;).sortable();&lt;/code&gt; Instead, what you will need to do is a slightly more clever declaration: &lt;code&gt;$(&apos;table&apos;).sortable({items: &apos;tr:visible&apos;});&lt;/code&gt; This will only sort on the currently visible rows.  This worked really well and only involved a small code change to implement the change. Hope this helps others if they are implementing jQuery UI&apos;s sortable on a table.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Moving to CakePHP</title>
   <link href="http://davidvedvick.info/notes/2011/10/02/moving-to-cakephp" />
   <updated>2011-10-03T02:38:28.000Z</updated>
   <id>http://davidvedvick.info/notes/2011/10/02/moving-to-cakephp</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Moving to CakePHP&lt;/h1&gt;
&lt;p&gt;Well, I think I&apos;m just gonna pull the plug and move my current development on DeVeD Computers to CakePHP.  Having a well done framework really does decrease development time, instead of worrying about simple things like proper page routing and whatnot.  Maybe I&apos;ll first branch development on my server....&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>SharpXML</title>
   <link href="http://davidvedvick.info/notes/2011/10/23/sharpxml" />
   <updated>2011-10-24T00:53:55.000Z</updated>
   <id>http://davidvedvick.info/notes/2011/10/23/sharpxml</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;SharpXML&lt;/h1&gt;
&lt;p&gt;So this weekend I made an XML parsing Library called SharpXML.  Basically, all of the XML Libraries that come with MS&apos;s standard .Net implementation seem to me to fall very short of ease-of-use, which is something I value highly when developing. I could write more about it, but in short, what it really means is I need to get a life :). Here&apos;s the link to get it: &lt;a href=&quot;http://sharpxml.codeplex.com/&quot;&gt;http://sharpxml.codeplex.com/&lt;/a&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Expanding or changing the business...</title>
   <link href="http://davidvedvick.info/notes/2012/05/07/expanding-or-changing-the-business" />
   <updated>2012-05-07T14:37:52.000Z</updated>
   <id>http://davidvedvick.info/notes/2012/05/07/expanding-or-changing-the-business</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Expanding or changing the business...&lt;/h1&gt;
&lt;p&gt;So, now that I&apos;ve had some free time, I&apos;ve been thinking deeply about the business model I chose way-back-when I decided to open a boutique computer shop. Obviously, the market is not huge here, and to make a dent, I need to do something different than what I currently do. This puts a major roadblock in further developing my website... maybe. Or maybe not ;).... Either way, I&apos;ve gone forward with CakePHP 1.3, and development has been easier than even I anticipated. Really slick framework for PHP.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>New version of J. River Media Center Windows 7 Integration plug-in released</title>
   <link href="http://davidvedvick.info/notes/2012/06/10/new-version-of-j-river-media-center-windows-7-integration-plug-in-released" />
   <updated>2012-06-10T19:24:50.000Z</updated>
   <id>http://davidvedvick.info/notes/2012/06/10/new-version-of-j-river-media-center-windows-7-integration-plug-in-released</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;New version of J. River Media Center Windows 7 Integration plug-in released&lt;/h1&gt;
&lt;p&gt;A new version of my Windows 7 integration plug-in for &lt;a href=&quot;http://www.jriver.com/index.html&quot;&gt;J. River Media Center&lt;/a&gt; has been released. Notable fixes include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Memory Leaked fixed on preview when Thumbnail Cover Art is enabled.&lt;/li&gt;
&lt;li&gt;Thumbnail Cover Art properly re-sizes to thumbnail size.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It can be downloaded from the &lt;a href=&quot;http://code.google.com/p/j-river-media-center-windows-7-shell-integration/downloads/list&quot;&gt;Google Code&lt;/a&gt; site I set-up for it.&lt;/p&gt;
&lt;p&gt;I will detail the memory leak fix in greater detail a little bit later, as it was quite interesting... &lt;img src=&quot;http://machine.devedcomputers.com/wp-content/uploads/2012/06/progressbar-300x187.png&quot; alt=&quot;Windows 7 J. River Media Center Integration&quot; /&gt;
**    &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Download: &lt;a href=&quot;http://code.google.com/p/j-river-media-center-windows-7-shell-integration/downloads/list&quot;&gt;http://code.google.com/p/j-river-media-center-windows-7-shell-integration/downloads/list&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>Version 0.9.2 of J. River Media Center Plug-in</title>
   <link href="http://davidvedvick.info/notes/2012/06/10/version-0-9-2-of-j-river-media-center-plug-in" />
   <updated>2012-06-10T23:25:29.000Z</updated>
   <id>http://davidvedvick.info/notes/2012/06/10/version-0-9-2-of-j-river-media-center-plug-in</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Version 0.9.2 of J. River Media Center Plug-in&lt;/h1&gt;
&lt;p&gt;I guess I&apos;ve been bored today :).... I posted a new version to Google code. Notable fixes include: Fixes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Thumbnail Previews&lt;ul&gt;
&lt;li&gt;Improved initialization of the Thumbnail Preview&lt;/li&gt;
&lt;li&gt;Improved handling of Minimize scenarios
Check it out at &lt;a href=&quot;http://code.google.com/p/j-river-media-center-windows-7-shell-integration/downloads/list&quot;&gt;Google Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>Version 0.9.3 of J. River Windows 7 Integration Media Center Plug-in</title>
   <link href="http://davidvedvick.info/notes/2012/06/13/version-0-9-3-of-j-river-windows-7-integration-media-center-plug-in" />
   <updated>2012-06-13T20:48:26.000Z</updated>
   <id>http://davidvedvick.info/notes/2012/06/13/version-0-9-3-of-j-river-windows-7-integration-media-center-plug-in</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Version 0.9.3 of J. River Windows 7 Integration Media Center Plug-in&lt;/h1&gt;
&lt;p&gt;Version 0.9.3 of J. River Windows 7 Integration Media Center Plug-in is out today! I posted the new version to Google code. Notable fixes include: Fixes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Regression: Pause now changes progress to yellow as before&lt;/li&gt;
&lt;li&gt;Regression: Waiting status now changes progress to indeterminate (cycling progress bar without begin or end)&lt;/li&gt;
&lt;li&gt;Correct Version Number in installer
Check it out at &lt;a href=&quot;http://code.google.com/p/j-river-media-center-windows-7-shell-integration/downloads/list&quot;&gt;Google Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>Oracle 10G and Parentheses</title>
   <link href="http://davidvedvick.info/notes/2012/10/10/oracle-10g-and-parentheses" />
   <updated>2012-10-11T03:57:08.000Z</updated>
   <id>http://davidvedvick.info/notes/2012/10/10/oracle-10g-and-parentheses</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Oracle 10G and Parentheses&lt;/h1&gt;
&lt;p&gt;A word of warning to all who are still stuck with using Oracle 10G 32-bit in a 64-bit environment: _Do not install  your programs in a path where one of the folders has parentheses in it. _ So, in other words, the most common 32-bit install path, &quot;C:\Program Files (x86)\..&quot; is unusable if you have an app that uses Oracle 10G 32-bit. Oracle cannot handle this situation, and is unable to even complete a TNS Look-up and make a connection. Bleh.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Music Streamer for J. River Media Center on the way</title>
   <link href="http://davidvedvick.info/notes/2012/11/04/music-streamer-for-j-river-media-center-on-the-way" />
   <updated>2012-11-05T03:29:34.000Z</updated>
   <id>http://davidvedvick.info/notes/2012/11/04/music-streamer-for-j-river-media-center-on-the-way</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Music Streamer for J. River Media Center on the way&lt;/h1&gt;
&lt;p&gt;I&apos;m building this with the goal of improving upon and/or pushing J. River to improve their own media player for Android. It&apos;s in a _very early _stage of development. Here&apos;s some screenshots :)   [gallery columns=&quot;2&quot;]&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>A eulogy for a man I didn't ever know...</title>
   <link href="http://davidvedvick.info/notes/2013/01/12/a-eulogy-for-a-man-i-hardly-knew" />
   <updated>2013-01-12T19:21:02.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/01/12/a-eulogy-for-a-man-i-hardly-knew</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;A eulogy for a man I didn&apos;t ever know...&lt;/h1&gt;
&lt;p&gt;Today it has been reported that Aaron Swartz has committed suicide. I never really knew who the guy was, but his credentials were amazing, and I think this is one of those things where you don&apos;t realize what your world (my world consisting mostly of technology) had until you have lost that asset. Aaron Swartz was an incredible mind; he developed the early version of Reddit, he was a co-author of the original RSS 1.0 feed (which my blog and every blog uses), he helped develop a &lt;em&gt;L__egal&lt;/em&gt; document (Creative Commons 1.0), and he had released tons of scientific data to the public. He committed suicide today, and we now will never know what else he could have contributed to our world, and to mine in particular.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>NearlyFreeSpeech.net</title>
   <link href="http://davidvedvick.info/notes/2013/02/08/nearlyfreespeech-net" />
   <updated>2013-02-09T00:38:24.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/02/08/nearlyfreespeech-net</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;NearlyFreeSpeech.net&lt;/h1&gt;
&lt;p&gt;It seems like it&apos;s been forever since I switched to NearlyFreeSpeech.net, and while it may reflect poorly on the amount of readers I have, I have to say I love the pricing model, and the speed that their servers run at!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>The new deliciouspc.com (the site formerly known as DevedComputers)</title>
   <link href="http://davidvedvick.info/notes/2013/02/11/the-new-deliciouspc-com-the-site-formerly-known-as-devedcomputers" />
   <updated>2013-02-11T06:10:40.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/02/11/the-new-deliciouspc-com-the-site-formerly-known-as-devedcomputers</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;The new deliciouspc.com (the site formerly known as DevedComputers)&lt;/h1&gt;
&lt;p&gt;I have &quot;officially&quot; launched my new computer business website, delicious pc. It&apos;s currently in a bit of a rough state, but I was so pleased with how everything was coming together that I couldn&apos;t help myself and so I published it to deliciouspc.com. Here&apos;s a little run through of the site: The homepage: &lt;img src=&quot;/notes/content/uploads/2013/02/homepage-300x159.jpg&quot; alt=&quot;homepage&quot; /&gt;   Selecting needs:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2013/02/needs-300x159.jpg&quot; alt=&quot;needs&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Inputting your budget:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2013/02/budget-300x159.jpg&quot; alt=&quot;budget&quot; /&gt;     &lt;a href=&quot;./content/uploads/2013/02/email.png&quot;&gt; &lt;/a&gt; &lt;a href=&quot;./content/uploads/2013/02/homepage.jpg&quot;&gt; &lt;/a&gt;     And the final page! You&apos;re already done. Wasn&apos;t that easy? &lt;img src=&quot;/notes/content/uploads/2013/02/email-300x159.png&quot; alt=&quot;email&quot; /&gt;             I&apos;m sure there are some parts that won&apos;t work (I just discovered the e-mail option isn&apos;t working at the moment), but overall it seems to be in a decent alpha stage. UPDATE: I just got the e-mail option working again. Back to android development soon!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Android Media Streamer App Progress</title>
   <link href="http://davidvedvick.info/notes/2013/03/17/android-media-streamer-app-progress" />
   <updated>2013-03-18T02:55:16.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/03/17/android-media-streamer-app-progress</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Android Media Streamer App Progress&lt;/h1&gt;
&lt;p&gt;For some reason, programming in Java makes me feel like blogging. I think it&apos;s just the monumental amount of work involved in getting some of the basic things done that makes me particularly angsty (don&apos;t get me started on setting up your own events). Anyways, I&apos;ve made some decent progress:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The state machine logic to get the Service to pre-buffer the next file to be played in a playlist in a background thread&lt;/li&gt;
&lt;li&gt;The connection has some fault-tolerance so that if you move away from your local network it tries to get the remote URL and connect to it&lt;/li&gt;
&lt;li&gt;Album art now displays in the Now playing dialogue&lt;/li&gt;
&lt;li&gt;The notification changes with the album
My next steps:&lt;/li&gt;
&lt;li&gt;Add playlists as a &quot;Category&quot; to browse like the normal categories (whatever is set in the Media Center configuration)&lt;/li&gt;
&lt;li&gt;Add the ability to choose different play modes on a &quot;long-click&quot; of any item that is not a category&lt;/li&gt;
&lt;li&gt;Add play controls&lt;/li&gt;
&lt;li&gt;Add progress indicator&lt;/li&gt;
&lt;li&gt;Make sure you can start a different playlist if you choose to (I&apos;m afraid to test this out ;))
Sorry for any wild grammar or spelling mistakes, my heads kind of throbbing :-/&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>"JR Media/Music Streamer" screenshots...</title>
   <link href="http://davidvedvick.info/notes/2013/03/26/jr-mediamusic-streamer-screenshots" />
   <updated>2013-03-27T02:15:06.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/03/26/jr-mediamusic-streamer-screenshots</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;&quot;JR Media/Music Streamer&quot; screenshots...&lt;/h1&gt;
&lt;p&gt;Some work in progress screenshots....&lt;img src=&quot;/notes/content/uploads/2013/03/device-2013-03-26-220857-576x1024.png&quot; alt=&quot;device-2013-03-26-220857&quot; /&gt;   &lt;img src=&quot;/notes/content/uploads/2013/03/device-2013-03-26-220654-576x1024.png&quot; alt=&quot;device-2013-03-26-220654&quot; /&gt; &lt;img src=&quot;/notes/content/uploads/2013/03/device-2013-03-26-220731-576x1024.png&quot; alt=&quot;device-2013-03-26-220731&quot; /&gt; &lt;img src=&quot;/notes/content/uploads/2013/03/device-2013-03-26-220753-576x1024.png&quot; alt=&quot;device-2013-03-26-220753&quot; /&gt; &lt;img src=&quot;/notes/content/uploads/2013/03/device-2013-03-26-220808-576x1024.png&quot; alt=&quot;device-2013-03-26-220808&quot; /&gt;Todo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add a button to go to &quot;Now Playing&quot; when it&apos;s not playing but is paused&lt;/li&gt;
&lt;li&gt;Save the state of the app to local (NAND) memory when the music is paused and the garbage collector comes around&lt;/li&gt;
&lt;li&gt;Improve the look.&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>"Project Blue Water" - formerly known as "Media Streamer" progress</title>
   <link href="http://davidvedvick.info/notes/2013/08/12/project-blue-water-formerly-known-as-media-streamer-progress" />
   <updated>2013-08-12T12:03:51.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/08/12/project-blue-water-formerly-known-as-media-streamer-progress</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;&quot;Project Blue Water&quot; - formerly known as &quot;Media Streamer&quot; progress&lt;/h1&gt;
&lt;p&gt;Major improvements have begun to the UI of my media streamer project for J. River Media Center, which I&apos;m now giving the name &quot;Project Blue Water&quot;. First and foremost is the &quot;Now Playing&quot; UI, for which I&apos;ve taken some new screenshots, to be loved or hated: &lt;img src=&quot;/notes/content/uploads/2013/08/loading_img-576x1024.png&quot; alt=&quot;&amp;quot;Loading&amp;quot; Now playing screen&quot; /&gt;   &lt;img src=&quot;/notes/content/uploads/2013/08/device-2013-08-12-075712-576x1024.png&quot; alt=&quot;&amp;quot;Inactive&amp;quot; Now Playing screen&quot; /&gt;   &lt;img src=&quot;/notes/content/uploads/2013/08/device-2013-08-12-075734-576x1024.png&quot; alt=&quot;&amp;quot;Active&amp;quot; Now Playing screen&quot; /&gt; As you can see, I&apos;ve also added the ability to change the rating on a song!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>My (slightly (un)qualified) thoughts on Windows</title>
   <link href="http://davidvedvick.info/notes/2013/09/01/my-slightly-unqualified-thoughts-on-windows" />
   <updated>2013-09-02T01:06:49.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/09/01/my-slightly-unqualified-thoughts-on-windows</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;My (slightly (un)qualified) thoughts on Windows&lt;/h1&gt;
&lt;p&gt;In the court of public opinion, the jury has ruled on Windows 8. It has become clear that the drastic changes in UI without any instruction to the user or any way to change it back has had a negative effect in the uptake of Windows 8. And after I installed &lt;a href=&quot;http://www.stardock.com/products/start8/&quot;&gt;Start8&lt;/a&gt; and &lt;a href=&quot;http://www.stardock.com/products/modernmix/&quot;&gt;Modern Mix&lt;/a&gt; it has finally become clear to me that either Microsoft has plans that we aren&apos;t aware of yet or it has completely missed some massive potential here. If you aren&apos;t aware, Start8 restores the Windows start menu. It uses an icon that is similar to the icon from the restored Start button in Windows 8.1. Modern Mix is unique in that it adds the ability to run the Modern UI apps in a Window. This effectively restores Windows 8 to a Windows 7-like desktop UI. Surprisingly, it all works really well - and more than anything, it actually makes me want to &lt;em&gt;start using&lt;/em&gt; Windows 8 on my laptop. Modern Mix makes those beautiful Metro Modern UI apps usable without having to mess with the start screen, and with the ability to quickly switch to my normal Windows apps using my normal workflow. This tells me that at least I personally would have loved my purchase of Windows 8 if the following things had been done: When in laptop mode (i.e. with a keyboard/mouse):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The Windows  7 start menu, in the style of Windows 8 (or even a slightly improved one)&lt;/li&gt;
&lt;li&gt;No &quot;start screen&quot;&lt;/li&gt;
&lt;li&gt;No &quot;charms&quot;&lt;/li&gt;
&lt;li&gt;The ability to use Modern UI apps on the desktop
When in a &quot;tablet mode&quot; (i.e. no keyboard/mouse), enabling all the UI changes that Microsoft introduced with Windows 8 are fine, and even great. On top of this, to add on some nice-to-haves, when using my software on a Theater PC, I think these things would be nice:&lt;/li&gt;
&lt;li&gt;The start button on an MCE remote should bring up the Start screen (yes now I like it)&lt;/li&gt;
&lt;li&gt;Metro apps should have an easy ability to tie-in with and use an MCE remote
On a side note, the Start screen actually works really well with the MCE remote once it is started, and &lt;a href=&quot;http://thedigitalmediazone.com/2012/07/25/remap-green-button-as-start-button-on-remote/&quot;&gt;adding a registry change to map the Start Screen to the Start button&lt;/a&gt; is not as hard as it sounds.&lt;/li&gt;
&lt;/ol&gt;

  </content>
</entry>
<entry>
   <title>Version 0.9.4 of Windows 7/8 J. River Integration Media Center Plug-in</title>
   <link href="http://davidvedvick.info/notes/2013/09/02/version-0-9-4-of-windows-78-j-river-integration-media-center-plug-in" />
   <updated>2013-09-02T16:00:07.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/09/02/version-0-9-4-of-windows-78-j-river-integration-media-center-plug-in</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Version 0.9.4 of Windows 7/8 J. River Integration Media Center Plug-in&lt;/h1&gt;
&lt;p&gt;After a long wait, a new version of the Media Center plug-in is out! &lt;a href=&quot;https://code.google.com/p/j-river-media-center-windows-7-shell-integration/downloads/list&quot;&gt;It can be downloaded here&lt;/a&gt; and as you can see, I&apos;ve added basic Jumplist support for Playlists:   &lt;img src=&quot;/notes/content/uploads/2013/09/mc_aero_jumplist.png&quot; alt=&quot;Playlist Jumplist&quot; /&gt;   &lt;img src=&quot;/notes/content/uploads/2013/09/mc_config-1024x506.jpg&quot; alt=&quot;Added configuration for adding playlists to jumplist&quot; /&gt;   Here&apos;s the official changelist: New:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Playlists can be pinned in the jumplist
Bug fixes:&lt;/li&gt;
&lt;li&gt;Config reverts upon installing a new version of Media Center&lt;/li&gt;
&lt;li&gt;Window Title text in preview will not truncate to &quot;J River Media Ce&quot; (Thanks &lt;a href=&quot;http://yabb.jriver.com/interact/index.php?topic=83236.msg568489#msg568489&quot;&gt;StFeder&lt;/a&gt; from the J River forums)
As this a new release, I am not yet removing the 0.9.3 version until any stability issues are sorted out. &lt;a href=&quot;https://code.google.com/p/j-river-media-center-windows-7-shell-integration/downloads/list&quot;&gt;Download link.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>Windows 8.1 Upgrade - potential hard drive killer?</title>
   <link href="http://davidvedvick.info/notes/2013/10/19/windows-8-1-upgrade-potential-hard-drive-killer" />
   <updated>2013-10-19T23:50:20.000Z</updated>
   <id>http://davidvedvick.info/notes/2013/10/19/windows-8-1-upgrade-potential-hard-drive-killer</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Windows 8.1 Upgrade - potential hard drive killer?&lt;/h1&gt;
&lt;p&gt;Upgrading from Windows 8 to Windows 8.1 has already taken two victims. Will it take more? Word of warning to those upgrading their Windows installs to Windows 8.1 this weekend - I installed it on my (7-year old) 250GB RAID 1 array and it thrashed and killed both drives. So lookout! Obviously it being an older pair of drives, I can&apos;t speak to the reliability of them, but it does seem very odd that they would &lt;em&gt;both&lt;/em&gt; suffer from SMART errors on the same day. Otherwise, on my other machine Windows 8.1 seems to be working fine.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>The Promise of Google Voice</title>
   <link href="http://davidvedvick.info/notes/2014/01/12/the-promise-of-google-voice" />
   <updated>2014-01-12T15:08:55.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/01/12/the-promise-of-google-voice</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;The Promise of Google Voice&lt;/h1&gt;
&lt;p&gt;I have just recently decided to drop my phone contract. I&apos;m not dropping a contract completely - I&apos;m making the incredibly tempting switch to T-Mobile&apos;s no annual contract, which won&apos;t include an ETF that will kill me if I decide to switch again. However, I hit one major snag while making this switch. I couldn&apos;t use my old North Dakota number as T-Mobile doesn&apos;t have 1st-party coverage in Bismarck, ND yet. My alternative would have been to go with AT&amp;amp;T or with their MVNO, AIO wireless, &lt;a href=&quot;http://www.aiowireless.com/home.html&quot;&gt;which offers comparable plans to T-Mobile&lt;/a&gt;. However, I&apos;m still fairly apprehensive of AT&amp;amp;T and their death-throe &lt;a href=&quot;http://arstechnica.com/tech-policy/2014/01/att-plan-to-turn-data-caps-into-more-cash-could-come-to-home-internet/&quot;&gt;business tactics&lt;/a&gt;. In the end, I chose T-Mobile. So how does this play into Google Voice? My solution ended being that I would use T-Mobile, but use Google voice as my number. The potential of this solution is amazing: without a number that is tied to a phone service or contract, but rather just to &lt;em&gt;me&lt;/em&gt;, I&apos;m able to easily pick up a prepaid SIM from AT&amp;amp;T when I need some minutes in North Dakota, and just assign the number with the SIM to my Google voice account. I really hope that as Google starts to move more out of working on building the structure for an open handset into providing the services on that handset that they come back to Google Voice and really start to sell this potential to customers.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Latest Project Blue Water Updates</title>
   <link href="http://davidvedvick.info/notes/2014/04/07/latest-project-blue-water-updates" />
   <updated>2014-04-08T03:41:47.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/04/07/latest-project-blue-water-updates</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Latest Project Blue Water Updates&lt;/h1&gt;
&lt;p&gt;I&apos;ve made numerous improvements to Project Blue Water. I&apos;m feeling a little too lazy to write about it extensively, but below are new screenshots. &lt;img src=&quot;/notes/content/uploads/2014/04/Screenshot_2014-04-06-11-02-36-576x1024.png&quot; alt=&quot;Slideout drawer&quot; /&gt;
&lt;em&gt;Slideout drawer&lt;/em&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>An ideal SPA</title>
   <link href="http://davidvedvick.info/notes/2014/05/19/an-ideal-spa" />
   <updated>2014-05-19T12:16:12.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/05/19/an-ideal-spa</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;An ideal SPA&lt;/h1&gt;
&lt;p&gt;An ideal SPA should have its initial state on load pre-rendered from the server. After this, the client-side JavaScript should be able to take over all duties.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Ridiculous</title>
   <link href="http://davidvedvick.info/notes/2014/06/05/ridiculous" />
   <updated>2014-06-05T12:22:39.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/06/05/ridiculous</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Ridiculous&lt;/h1&gt;
&lt;p&gt;It&apos;s absurd to think that we can afford to stream HD video from space but somehow Comcast can&apos;t afford to upgrade their equipment to stream episodes of mad men competently.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Stop using my documents folder</title>
   <link href="http://davidvedvick.info/notes/2014/06/11/stop-using-my-documents-folder" />
   <updated>2014-06-11T18:08:33.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/06/11/stop-using-my-documents-folder</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Stop using my documents folder&lt;/h1&gt;
&lt;p&gt;Game developers, please stop using my &quot;Documents&quot; folder to preserve the state of your video games. This is annoying at best and worst case, destructive. Here&apos;s my random list of why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It eats up space on an area that I might have specifically set-up to not use space (since it is only supposed to be &lt;em&gt;documents&lt;/em&gt; and all)&lt;/li&gt;
&lt;li&gt;There&apos;s a better place for preserving the state of a program in Windows; it&apos;s under /&lt;em&gt;AppData&lt;/em&gt;/... notice the &quot;AppData&quot; in the folder path?&lt;/li&gt;
&lt;li&gt;It adds unnecessary data and/or configuration steps when I synchronize my personal, you know &lt;em&gt;documents&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Like the above point, it requires extra configuration in a back-up tool that I may use for backing up my documents to exclude your information&lt;ul&gt;
&lt;li&gt;And don&apos;t think that just because I am playing your game, I care to back-up the game data!&lt;ul&gt;
&lt;li&gt;And if I do, and I already know how to use a back-up service, I will configure it do that myself!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;It puts a bunch of folders in &lt;em&gt;my&lt;/em&gt; documents folder referencing gaming companies. I don&apos;t see you putting your video games in my filing cabinet, WHY IN THE HELL IS IT IN MY DOCUMENTS FOLDER?!&lt;/li&gt;
&lt;li&gt;Finally, usually the data isn&apos;t even frickin&apos; documents! Take a look at Sid Meier&apos;s Civilization 5:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2014/06/civ5-300x204.png&quot; alt=&quot;Civ 5 Cache&quot; /&gt;
&lt;em&gt;Civilization 5 Cache is somehow in my Documents folder&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Note above how the _cache_ is stored in my documents folder. Do you think a _cache_ is something I would store in my documents, Sid?
&lt;/code&gt;&lt;/pre&gt;
  </content>
</entry>
<entry>
   <title>SpaceX launch</title>
   <link href="http://davidvedvick.info/notes/2014/08/04/spacex-launch" />
   <updated>2014-08-05T05:22:01.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/08/04/spacex-launch</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;SpaceX launch&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2014/08/tmp_15854-IMG_20140805_241428776451287281-300x168.jpg&quot; alt=&quot;tmp_15854-IMG_20140805_241428776451287281&quot; /&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Great post on "starting from scratch"</title>
   <link href="http://davidvedvick.info/notes/2014/08/23/great-post-on-starting-from-scratch" />
   <updated>2014-08-23T21:17:31.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/08/23/great-post-on-starting-from-scratch</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Great post on &quot;starting from scratch&quot;&lt;/h1&gt;
&lt;p&gt;This is a great post on &quot;starting from scratch&quot;. It&apos;s pretty old and I&apos;ve probably come across it before, but it&apos;s a &lt;a href=&quot;http://joelonsoftware.com/articles/fog0000000069.html&quot;&gt;good one&lt;/a&gt;.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Coming soon!</title>
   <link href="http://davidvedvick.info/notes/2014/08/29/coming-soon" />
   <updated>2014-08-30T04:45:34.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/08/29/coming-soon</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Coming soon!&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2014/08/tmp_11347-Screenshot_2014-08-29-23-36-35-1424824712-576x1024.png&quot; alt=&quot;tmp_11347-Screenshot_2014-08-29-23-36-35-1424824712&quot; /&gt; &lt;img src=&quot;/notes/content/uploads/2014/08/tmp_11347-Screenshot_2014-08-29-23-39-11-355661793-576x1024.png&quot; alt=&quot;tmp_11347-Screenshot_2014-08-29-23-39-11-355661793&quot; /&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>I'm glad</title>
   <link href="http://davidvedvick.info/notes/2014/08/30/im-glad" />
   <updated>2014-08-31T02:21:51.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/08/30/im-glad</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;I&apos;m glad&lt;/h1&gt;
&lt;p&gt;I don&apos;t have this problem &lt;a href=&quot;http://online.wsj.com/articles/the-u-s-s-ailing-medical-system-a-doctors-perspective-1409325361?mod=WSJ_hppMIDDLENexttoWhatsNewsSecond&quot;&gt;yet&lt;/a&gt;.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Installing MonoDevelop on Linux</title>
   <link href="http://davidvedvick.info/notes/2014/10/30/installing-monodevelop-on-linux" />
   <updated>2014-10-31T03:51:17.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/10/30/installing-monodevelop-on-linux</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Installing MonoDevelop on Linux&lt;/h1&gt;
&lt;p&gt;Today I discovered the joys of &quot;installing&quot; as it were MonoDevelop on Linux. All it took was pulling down from Git, getting all the dependencies (non-trivial) and doing a full build. And then there was something to do with &lt;a href=&quot;http://stackoverflow.com/questions/24793207/error-when-compiling-monodevelop-5-3-on-linux&quot;&gt;adding a key of some sort&lt;/a&gt; before I could finish the build - since NuGet needs some keys of something or other. Either way - I&apos;m up and running and boy is it fast compared to Java&apos;s equivalent (as far as I know), Eclipse. Still running into some issues getting MVC.net up and running, but it looks like &lt;a href=&quot;http://curtis.schlak.com/2014/02/04/setup-asp-net-mvc-4-on-monodevelop-4.2.html&quot;&gt;I&apos;m not the only one&lt;/a&gt;. Here&apos;s the &lt;a href=&quot;http://stackoverflow.com/a/20577968&quot;&gt;Linux fix&lt;/a&gt; since that was a Mac fix.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>A (color) change is gonna come</title>
   <link href="http://davidvedvick.info/notes/2014/12/19/a-color-change-is-gonna-come" />
   <updated>2014-12-20T04:34:51.000Z</updated>
   <id>http://davidvedvick.info/notes/2014/12/19/a-color-change-is-gonna-come</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;A (color) change is gonna come&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2014/12/tmp_9802-Screenshot_2014-12-19-22-29-521040253195-576x1024.png&quot; alt=&quot;tmp_9802-Screenshot_2014-12-19-22-29-521040253195&quot; /&gt; Coming even sooner! Without the sepia/night time shading.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Clearstream, the project formerly known as blue water</title>
   <link href="http://davidvedvick.info/notes/2015/01/01/clearstream-the-project-formerly-known-as-blue-water" />
   <updated>2015-01-02T00:37:37.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/01/01/clearstream-the-project-formerly-known-as-blue-water</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Clearstream, the project formerly known as blue water&lt;/h1&gt;
&lt;p&gt;It&apos;s a new year, so I have some new screenshots of Clearstream, the project I used to call &quot;project blue water&quot;. I&apos;m closing in on the final feature set for Clearstream before I release it to the public - only one item left on my list: Last.fm support. [gallery ids=&quot;1340,1339,1338&quot;]&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Clearstream on a Tablet</title>
   <link href="http://davidvedvick.info/notes/2015/01/14/clearstream-on-a-tablet" />
   <updated>2015-01-14T23:39:47.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/01/14/clearstream-on-a-tablet</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Clearstream on a Tablet&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2015/01/tmp_15489-Screenshot_2015-01-14-17-32-292112591728-640x1024.png&quot; alt=&quot;Clearstream on a Nexus 7 \(2012\)&quot; /&gt;&lt;em&gt;Clearstream on a Nexus 7 (2012)&lt;/em&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Clearstream (name subject to change) Beta is out!</title>
   <link href="http://davidvedvick.info/notes/2015/01/24/clearstream-name-subject-to-change-beta-is-out" />
   <updated>2015-01-24T22:12:45.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/01/24/clearstream-name-subject-to-change-beta-is-out</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Clearstream (name subject to change) Beta is out!&lt;/h1&gt;
&lt;p&gt;I&apos;m proud to announce that Clearstream is ready for a beta release. I initially will be providing it as a download that you will have to install manually. It currently only supports Android 4.0.3+. I also plan a release of the source on GitHub or some other Git hosting service at some point soon. It&apos;s a fairly straightforward app that is intended only for streaming &lt;em&gt;music&lt;/em&gt; from &lt;a href=&quot;http://www.jriver.com/index.html&quot;&gt;J. River Media Center&lt;/a&gt;. It&apos;s main goals are improved streaming reliability and better usability. I intend to write at least a crappy attempt at a tutorial for using it, but until (or if) that happens, you can look up &lt;a href=&quot;/category/coding/music-streamer/&quot;&gt;previous posts&lt;/a&gt; to get a hint of how to use it. The main UI &quot;trick&quot; that users will need to be aware of is that many list items will show a menu if they are long pressed. Update: Please use the &lt;a href=&quot;/2015/05/24/news/audiocanoe-the-alternative-android-audio-streaming-client-formerly-known-as-clearstream/&quot;&gt;most recent version of audiocanoe&lt;/a&gt;. [gallery size=&quot;medium&quot; ids=&quot;1356,1357&quot;]   If you&apos;ve never installed a third-party app before, there&apos;s very many good tutorials to set you up. &lt;a href=&quot;http://pocketpccentral.net/help/android/general/app_install_android4.htm&quot;&gt;Here&apos;s one.&lt;/a&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Clearstream 1.0-beta features</title>
   <link href="http://davidvedvick.info/notes/2015/01/24/clearstream-1-0-beta-features" />
   <updated>2015-01-25T04:25:45.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/01/24/clearstream-1-0-beta-features</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Clearstream 1.0-beta features&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Stream music from server with high reliability&lt;ul&gt;
&lt;li&gt;Will use local music files if they exist and the filename and metadata match&lt;/li&gt;
&lt;li&gt;Modern interface&lt;/li&gt;
&lt;li&gt;Updates server with now playing information&lt;/li&gt;
&lt;li&gt;Interfaces with Bluetooth remote control clients and Pebble watches&lt;/li&gt;
&lt;li&gt;Interfaces with apps that implement the &lt;a href=&quot;https://play.google.com/store/apps/details?id=net.jjc1138.android.scrobbler&amp;amp;hl=en&quot;&gt;Scrobble Droid&lt;/a&gt; interface (&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.adam.aslfms&amp;amp;hl=en&quot;&gt;Simple Last.fm Scrobbler&lt;/a&gt; is my scrobbler of choice) for scrobbling to Last.fm or Libre.fm&lt;/li&gt;
&lt;li&gt;And more....&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>I have had a sustained switch to Linux</title>
   <link href="http://davidvedvick.info/notes/2015/02/08/i-have-had-a-sustained-switch-to-linux" />
   <updated>2015-02-08T19:11:55.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/02/08/i-have-had-a-sustained-switch-to-linux</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;I have had a sustained switch to Linux&lt;/h1&gt;
&lt;p&gt;After many years of fits and starts, I have finally stayed on a Linux distro for many months. What conditions enabled this change?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I spend much more of my time just programming these days when I&apos;m on my PC than doing entertainment tasks (i.e. watching movies, playing games)&lt;ul&gt;
&lt;li&gt;Except for Visual Studio, many of the same tools I use for programming are available on Linux&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Steam was made available for Linux, and most importantly, Civ 5 was ported to Linux, so when I &lt;em&gt;do&lt;/em&gt; game, I can play the game I like playing most on my PC&lt;/li&gt;
&lt;li&gt;Linux Mint came out with a, shall we say, &quot;normal&quot; or perhaps &quot;traditional&quot; user interface, and is rock solid&lt;/li&gt;
&lt;li&gt;As a bonus, the Media player program I&apos;ve used for years, &lt;a href=&quot;http://yabb.jriver.com/interact/index.php?board=35.0&quot;&gt;has come out with a Linux port that&apos;s in development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The open source driver for AMD cards has really grown into its own
Overall, I&apos;m loving it!&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>Mutability</title>
   <link href="http://davidvedvick.info/notes/2015/02/22/mutability" />
   <updated>2015-02-22T16:58:30.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/02/22/mutability</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Mutability&lt;/h1&gt;
&lt;p&gt;Was mutability the cardinal sin of high level programming languages?&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Clearstream 1.0.0.2</title>
   <link href="http://davidvedvick.info/notes/2015/03/08/clearstream-1-0-0-2" />
   <updated>2015-03-08T14:37:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/03/08/clearstream-1-0-0-2</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Clearstream 1.0.0.2&lt;/h1&gt;
&lt;p&gt;Hey everyone, I&apos;ve released a new version of Clearstream, Clearstream 1.0.0.2.
Feature-wise, it&apos;s the same as the previous release (I will likely bump the minor
version number up if I add a new feature). This is still what I would consider
a beta release, but the code has reached a point where I&apos;m comfortable releasing
the code to the general public.&lt;/p&gt;
&lt;p&gt;First, the download&lt;/p&gt;
&lt;p&gt;Update: Please use the
&lt;a href=&quot;/2015/05/24/news/audiocanoe-the-alternative-android-audio-streaming-client-formerly-known-as-clearstream/&quot;&gt;most recent version of audiocanoe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/danrien/projectBlueWater&quot;&gt;To the code&lt;/a&gt;: Clearstream code will
be released under the Lesser General Public License
(&lt;a href=&quot;http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License&quot;&gt;LGPL&lt;/a&gt;) 3.0,
meaning you can fork the code and change what you want, but any derivative works
must be released under the LGPL or a more restrictive license (such as the GPL).
Further, if you use parts of the code as a library (for whatever reason you would
want to do that?), you can use it in software with any license, as long as you give
me credit! &lt;a href=&quot;https://github.com/danrien/projectBlueWater/issues&quot;&gt;I&apos;d suggest you post any issues here.&lt;/a&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Wilco streaming clear</title>
   <link href="http://davidvedvick.info/notes/2015/03/09/wilco-streaming-clear" />
   <updated>2015-03-10T04:22:36.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/03/09/wilco-streaming-clear</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Wilco streaming clear&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2015/03/tmp_17386-Screenshot_2015-03-09-23-17-49-344938572-576x1024.png&quot; alt=&quot;Tweedy + clearstream&quot; /&gt;
&lt;em&gt;Tweedy + clearstream&lt;/em&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Clearstream 1.0.0.3</title>
   <link href="http://davidvedvick.info/notes/2015/04/05/clearstream-1-0-0-3" />
   <updated>2015-04-06T03:55:29.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/04/05/clearstream-1-0-0-3</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Clearstream 1.0.0.3&lt;/h1&gt;
&lt;p&gt;Hey everyone! Clearstream 1.0.0.3 is out! I mostly focused on making the UI consistent across the board. No doubt there are some areas that are still inconsistent however. Here&apos;s a list of the fixes/changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search activity filters on audio file type&lt;/li&gt;
&lt;li&gt;Pressing &quot;back&quot; button when a context menu is open reverts context menu to list item first&lt;/li&gt;
&lt;li&gt;Clicking on an item in a context menu reverts the context menu to the list item first&lt;/li&gt;
&lt;li&gt;Clicking on a file no longer plays it&lt;/li&gt;
&lt;li&gt;Added small tutorial&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Download here: Update: Please use the &lt;a href=&quot;/2015/05/24/news/audiocanoe-the-alternative-android-audio-streaming-client-formerly-known-as-clearstream/&quot;&gt;most recent version of audiocanoe&lt;/a&gt;. If you&apos;ve never installed a third-party app before, there&apos;s very many good tutorials to set you up. &lt;a href=&quot;http://pocketpccentral.net/help/android/general/app_install_android4.htm&quot;&gt;Here&apos;s one.&lt;/a&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>"audiocanoe" - the alternative JRiver Media Center audio streaming client for Android formerly known as Clearstream</title>
   <link href="http://davidvedvick.info/notes/2015/05/24/audiocanoe-the-alternative-android-audio-streaming-client-formerly-known-as-clearstream" />
   <updated>2015-05-24T17:05:51.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/05/24/audiocanoe-the-alternative-android-audio-streaming-client-formerly-known-as-clearstream</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;&quot;audiocanoe&quot; - the alternative JRiver Media Center audio streaming client for Android formerly known as Clearstream&lt;/h1&gt;
&lt;p&gt;&quot;audiocanoe&quot;, the alternative JRiver Media Center audio streaming client for
Android, formerly known as &quot;Clearstream&quot;, has been updated. The biggest update in
this release is an improved &quot;File details&quot; view:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2015/05/nexus_5_portrait-576x1024.png&quot; alt=&quot;nexus_5_portrait&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/uploads/2015/05/nexus_5_landscape-1024x576.png&quot; alt=&quot;nexus_5_landscape&quot; /&gt;&lt;/p&gt;
&lt;p&gt;An update: If you prefer downloading and installing from Google Play, along with
all the benefits that provides, you can join the &quot;beta&quot; as it were by joining
&lt;a href=&quot;https://plus.google.com/communities/116136407897208577626.&quot;&gt;this Google+ group&lt;/a&gt;
(annoying, I know, I think if/as soon as I decide to promote it to production,
I&apos;m going to disband the beta group). You can also try this
&lt;a href=&quot;https://play.google.com/apps/testing/com.lasthopesoftware.bluewater&quot;&gt;direct link to the play store&lt;/a&gt;,
 but I think it&apos;s going to ask you to join the group first.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>New Personal Site Setup</title>
   <link href="http://davidvedvick.info/notes/2015/06/26/new-personal-site-setup" />
   <updated>2015-06-26T15:32:31.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/06/26/new-personal-site-setup</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;A New Personal Site Setup&lt;/h1&gt;
&lt;p&gt;Finally, I have gotten off of wordpress and migrated my site to a nodejs/ReactJS
custom set-up that statically renders markdown files.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>How I Built My New Site</title>
   <link href="http://davidvedvick.info/notes/2015/07/26/how-i-built-my-new-site" />
   <updated>2015-07-27T01:42:22.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/07/26/how-i-built-my-new-site</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;How I Built My New Site&lt;/h1&gt;
&lt;p&gt;Long ago, shortly after I had started hearing about React on
&lt;a href=&quot;http://news.ycombinator.com&quot;&gt;Hacker News&lt;/a&gt;, I came across a post that suggested
that it was fairly &lt;a href=&quot;https://news.ycombinator.com/item?id=8894692&quot;&gt;trivial to build a blog&lt;/a&gt;
(or any website in general) with &lt;a href=&quot;https://github.com/jlongster/blog&quot;&gt;ReactJS and NodeJS&lt;/a&gt;,
and that you could not only have dynamic routing and client-side rendering, but
also render views statically server-side.&lt;/p&gt;
&lt;h2&gt;Architecture&lt;/h2&gt;
&lt;p&gt;For years, I had been hearing the outcry about Wordpress (usually related to it&apos;s
unnecessary complexities and security faults), and had for the most part, agreed
with them. So, for a while I fiddled around with NodeJS and ReactJS for a few
months and finally reached a breakthrough point where I really felt I had the
knowledge to build this site by hand, and hopefully, get a good introduction to
this new ReactJS thing, and this old (but totally new to me) thing called NodeJS.&lt;/p&gt;
&lt;p&gt;The stack I chose is fairly standard:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;expressjs for the routing&lt;/li&gt;
&lt;li&gt;express-react-views for displaying statically rendered ReactJS views&lt;/li&gt;
&lt;li&gt;ReactJS for the front-end views&lt;/li&gt;
&lt;li&gt;GulpJS for build and deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To reduce processing time in my release environment, most of the pages are rendered
and built once in my GulpJS deploy task to an HTML file using ReactJS&apos;s
&lt;code&gt;React.renderToStaticMarkup&lt;/code&gt; method (this avoids a render method on every request,
and allows browsers to cache more). This page is the exception, of course.&lt;/p&gt;
&lt;h2&gt;Development&lt;/h2&gt;
&lt;p&gt;Building the site was just a develop/refresh cycle, with what I would assume is
fairly vanilla ReactJS, so I won&apos;t bore you with the details. GulpJS, along with
a watch task, provided extroardinary amounts of help here.&lt;/p&gt;
&lt;h2&gt;Deployment&lt;/h2&gt;
&lt;p&gt;Once development was finished and it had a style that I enjoyed (simple does it!),
I began focusing on deployment. I currently use
&lt;a href=&quot;http://nearlyfreespeech.net&quot;&gt;nearlyfreespeech&lt;/a&gt; as my host provider, and I decided
to stay with them if I could. Luckily, nearlyfreespeech hasn&apos;t stood still since
I started hosting with them in 2012, and they have since enabled the usage of
long-running processes, and proxies to connect them to. Of course they would also
have the most recent version of NodeJS and NPM installed.&lt;/p&gt;
&lt;p&gt;The downside to nearlyfreespeech&apos;s current pricing model with continuous running
processes is that Node can tend to be fairly resource heavy.&lt;/p&gt;
&lt;p&gt;For deployment, I fell back on GulpJS again. Unfortunately, there was not any
first-hand support for SSH in GulpJS, so I used a plug-in called, aptly enough,
&lt;a href=&quot;https://github.com/teambition/gulp-ssh&quot;&gt;gulp-ssh&lt;/a&gt; (notice the pattern here?).
This plug-in competently handled connecting to SSH, however it was fairly limited
in how it sent files - it only allowed files to be sent one at a time.&lt;/p&gt;
&lt;p&gt;What I wanted was an SSH version of &lt;code&gt;gulp.dest&lt;/code&gt;. I ended up adding &lt;a href=&quot;https://github.com/teambition/gulp-ssh/pull/22&quot;&gt;a prototype method
to gulp-ssh&lt;/a&gt; that did exactly that,
called using &lt;code&gt;gulpSsh.dest&lt;/code&gt;. I still have my doubts as to whether that functionality
should exist independently in a separate plug-in, perhaps called &lt;code&gt;gulp-ssh-dest&lt;/code&gt;,
or something similar, operating in the spirit of Gulp. For now I will leave it as
is, and perhaps come back to it later if I decide to make a separate plug-in which
just covers that functionality.&lt;/p&gt;
&lt;p&gt;You can view the source for the site on my &lt;a href=&quot;https://github.com/danrien/a-personal-site&quot;&gt;github&lt;/a&gt;.
My updates to the gulp-ssh plug-in can be reviewed and improved
&lt;a href=&quot;https://github.com/teambition/gulp-ssh/pull/22&quot;&gt;as well&lt;/a&gt;.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>When the Boss comes on, it's gonna be good</title>
   <link href="http://davidvedvick.info/notes/2015/08/08/when-the-boss-comes-on" />
   <updated>2015-08-08T21:06:40.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/08/08/when-the-boss-comes-on</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;When the Boss comes on, it&apos;s gonna be good&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/Screenshot_2015-08-08-15-56-16.png&quot; alt=&quot;The Boss&quot; /&gt;
&lt;em&gt;When the Boss comes on, it&apos;s gonna be good&lt;/em&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Nifty SQL</title>
   <link href="http://davidvedvick.info/notes/2015/08/15/nifty-sql" />
   <updated>2015-08-15T13:26:38.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/08/15/nifty-sql</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Nifty SQL&lt;/h1&gt;
&lt;p&gt;It&apos;s a very rare thing when neat code is also useful; in my experience &quot;neat&quot;
or &quot;clever&quot; code usually also comes with some major caveats: readability and
maintainability, and usually arguable usefulness being the major ones.&lt;/p&gt;
&lt;p&gt;However, I think the self-join solution to the
&lt;a href=&quot;http://stackoverflow.com/questions/121387/fetch-the-row-which-has-the-max-value-for-a-column/123481#123481&quot;&gt;&quot;greatest-n-per-group&quot;&lt;/a&gt;
problem might be one of the exceptions to that rule. While it certainly suffers
from a lack of readability (at least personally, it requires a few mental acrobatics
to comprehend), it makes up for it in its usefulness and execution speed; since it
generally can work on indexes, it can avoid expensive index and/or table scans!&lt;/p&gt;
&lt;p&gt;Really, quite a clever solution. I wonder if there&apos;s a mathematical analog to this
solution?&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Custom SQLite Access Difficulties in Android</title>
   <link href="http://davidvedvick.info/notes/2015/09/23/custom-sqlite-difficulties-android" />
   <updated>2015-09-23T12:11:57.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/09/23/custom-sqlite-difficulties-android</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Custom SQLite Access Difficulties in Android&lt;/h1&gt;
&lt;p&gt;It is surprisingly difficult to access the SQLite database that the Android API
exposes in anyway that is not using Android&apos;s native APIs. There&apos;s certainly
no native JDBI wrapper supplied.&lt;/p&gt;
&lt;p&gt;This is unacceptable for me; mapping fields to database fields by hand is something
that we have automated numerous times in the last couple decades. The Android
API does not do this. SQLite Access from the Android library is like going back
to the ADO.net ages, here&apos;s an example I found
&lt;a href=&quot;http://www.vogella.com/tutorials/AndroidSQLite/article.html#sqliteoverview_query&quot;&gt;duckduckgo&apos;ing&lt;/a&gt;
the internet:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return database.query(DATABASE_TABLE,
  new String[] { KEY_ROWID, KEY_CATEGORY, KEY_SUMMARY, KEY_DESCRIPTION },
  null, null, null, null, null);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you&apos;re thinking the above &lt;code&gt;SCREAMING_CAPS&lt;/code&gt; look like they may be string constants,
you would not be mistaken. Yes, the bare Android SQLite library drops you back
to mapping an object manually. Hello, 2000.&lt;/p&gt;
&lt;p&gt;So where did I go from here? What I&apos;ve been using for a while is
&lt;a href=&quot;http://ormlite.com/&quot;&gt;OrmLite&lt;/a&gt;, and while that certainly works, it has some massive
memory leak problems, which, for a library that touts itself as &quot;Lite&quot; (I mean,
it&apos;s in the name), is not very &quot;lite&quot; :).&lt;/p&gt;
&lt;p&gt;Next steps were to look for a library that just bridged the database result set
to object mapping gap, which is all I really wanted; ideally, something
like &lt;a href=&quot;https://github.com/StackExchange/dapper-dot-net&quot;&gt;Dapper&lt;/a&gt; for Java. Once again,
numerous tools exist in this space but none supported Android out of the box.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://commons.apache.org/proper/commons-dbutils/&quot;&gt;DbUtils&lt;/a&gt; from the Apache
foundation looks promising, but it once again needs JDBI drivers. Perhaps with
&lt;a href=&quot;https://github.com/SQLDroid/SQLDroid&quot;&gt;SQLDroid&lt;/a&gt; I will achieve what I&apos;ve always
wanted!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Use Git to Manage Your Blog History</title>
   <link href="http://davidvedvick.info/notes/2015/10/06/use-git-to-manage-your-blog-history" />
   <updated>2015-10-06T12:21:04.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/10/06/use-git-to-manage-your-blog-history</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Use Git to Manage Your Blog History!&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;One of the major problems of rolling your own weblog is properly managing the
history of your posts.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The aim of this post is to elucidate how one can easily manage blog history,
using only Git.&lt;/p&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;The best known methods for managing history of text documents have always been
terrible. Yes, I&apos;m speaking of Wordpress, but also commercial solutions like
SharePoint, or the version tracking that has been built into Microsoft Word
for the longest time.&lt;/p&gt;
&lt;p&gt;Here&apos;s a list of cons that I always think of when using these tools:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;pre&gt;&lt;code&gt;Inconsistently track history
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;   Sometimes can leave comments, sometimes can&apos;t&lt;/li&gt;
&lt;li&gt;   Usually diffing is either unavailable or is built using some proprietary/internal
  code that probably doesn&apos;t work well&lt;/li&gt;
&lt;li&gt;   Obfuscated via dense database models, XML formats, and/or binary formats&lt;/li&gt;
&lt;li&gt;   Difficult to use third party tools with them&lt;/li&gt;
&lt;li&gt;   Content management systems, which is what all blog engines are, need security
to manage the blog. These security systems usually come riddled with bugs and
security flaws.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Along comes lowly git, the little DCVS tool that could, which fills in the above
gaps nicely. Combine this with a nice text format such as markdown, and you&apos;ve got
yourself a nice, versioned, document management system.&lt;/p&gt;
&lt;p&gt;However, it does come with its own set of cons:
1.	The git learning curve
2.	Git doesn&apos;t natively take post metadata
3.	Git is a version control system, and thus doesn&apos;t track file metadata either
— so &quot;true&quot; file creation time, last modified time are not available
4.	Wrapping git commands up in your favorite server-side language can sometimes
    be tricky
5.	Versioning doesn&apos;t happen automatically, but rather on intentional commits&lt;/p&gt;
&lt;p&gt;None of this is a show-stopper however. Yes, git is ridiculous to learn. Yes,
you can&apos;t get &quot;true&quot; file creation time. But none of this certainly bothered me
much.&lt;/p&gt;
&lt;h2&gt;How?&lt;/h2&gt;
&lt;p&gt;This is how I did it with nodejs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a git repo (&lt;code&gt;git init&lt;/code&gt;) where you want your posts to reside.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a nice sane format to store metadata about your posts. I&apos;d personally go
with at least a JSON-like format. Mine looks like below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;title: Use Git to Manage Your Blog History
author: vedvick
description:
---
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; The &lt;code&gt;---&lt;/code&gt; signals to the parser that the metadata section is complete.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grab the posts from a configured or constant location. This is my highly
sophisticated version:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;glob(path.join(notesConfig.path, &apos;*.md&apos;), function (err, files) { ... });
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; Following a simple convention of prefixing filenames with the date the post is created, such as &lt;code&gt;20151006-use-git-to-manage-your-blog-history.md&lt;/code&gt;, the server can then easily
 and reproducibly sort the files by the created date.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parsing the notes has a little sophistication to it. Here&apos;s the code used on
my server in full:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var parseNote = function (file, callback) {
    parseNote.propMatch = /(^[a-zA-Z_]*)\:(.*)/;

    fs.readFile(file, &apos;utf8&apos;, function (err, data) {
        if (err) {
            callback(err);
            return;
        }

        var textLines = data.split(&apos;\n&apos;);

        var fileName = path.basename(file, &apos;.md&apos;);
        var newNote = {
            created: null,
            pathYear: fileName.substring(0, 4),
            pathMonth: fileName.substring(4, 6),
            pathDay: fileName.substring(6, 8),
            pathTitle: fileName.substring(9)
        };

        var lineNumber = 0;
        for (var i = lineNumber; i &amp;lt; textLines.length; i++) {
            lineNumber = i;
            var line = textLines[i];

            if (line.trim() === &apos;---&apos;) break;

            var matches = parseNote.propMatch.exec(line);
            if (!matches) continue;

            var propName = matches[1];
            var value = matches[2].trim();

            switch (propName) {
                case &apos;created_gmt&apos;:
                    newNote.created = new Date(value);
                    break;
                case &apos;title&apos;:
                    newNote.title = value;
                    break;
            }
        }

        newNote.text = textLines
                            .slice(lineNumber + 1)
                            // add back in the line returns
                            .join(&apos;\n&apos;);

        if (newNote.created !== null) {
            callback(null, newNote);
            return;
        }

        if (!notesConfig.gitPath) {
            newNote.created = new Date(newNote.pathYear, newNote.pathMonth, newNote.pathDay);
            callback(null, newNote);
            return;
        }

        exec(&apos;git -C &quot;&apos; + notesConfig.gitPath + &apos;&quot; log HEAD --format=%cD -- &quot;&apos; + file.replace(notesConfig.path + &apos;/&apos;, &apos;&apos;) + &apos;&quot; | tail -1&apos;,
            function (error, stdout, stderr) {
                if (error !== null) {
                    callback(error);
                    return;
                }

                newNote.created = new Date(stdout);
                callback(null, newNote);
            }
        );
    });
};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; The neatest part here (and where git or some other version control system shines)
 is using it to determine the note&apos;s created date:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;exec(&apos;git -C &quot;&apos; + notesConfig.gitPath + &apos;&quot; log HEAD --format=%cD -- &quot;&apos; + file.replace(notesConfig.path + &apos;/&apos;, &apos;&apos;) + &apos;&quot; | tail -1&apos;,
     function (error, stdout, stderr) {
         if (error !== null) {
             callback(error);
             return;
         }

         newNote.created = new Date(stdout);
         callback(null, newNote);
     }
 );
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;  Note how this doesn&apos;t actually return the true &quot;created&quot; timestamp of the file,
  but it does, in my opinion, return a timestamp that is close enough.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When drafting a new post, create a new branch so the draft can be worked on in
isolation without affecting work on other posts (for example, I posted
&lt;a href=&quot;/notes/2015/10/13/new-materialish-look-for-audiocanoe&quot;&gt;an entirely different post&lt;/a&gt;
while drafting this one). For this I also follow another convention:
&lt;code&gt;post/&amp;lt;post-name-here&amp;gt;&lt;/code&gt;. Of course, the convention is optional but I think at the
very least it encourages consistency.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, merge posts into master and push it to a web server. Then add a
&lt;code&gt;post-receive&lt;/code&gt; hook that checks out master to the location determined above:
&lt;code&gt;GIT_WORK_TREE=&amp;lt;note-location&amp;gt; git checkout -f&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

  </content>
</entry>
<entry>
   <title>New Materialish Look for Audiocanoe</title>
   <link href="http://davidvedvick.info/notes/2015/10/13/new-materialish-look-for-audiocanoe" />
   <updated>2015-10-13T12:20:17.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/10/13/new-materialish-look-for-audiocanoe</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;New Materialish Look for audiocanoe&lt;/h1&gt;
&lt;p&gt;audiocanoe is seeing some updates coming up to match Google&apos;s new Material Design
specs! Take a look below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/20151013-new-materialish-look-for-audiocanoe/Screenshot_2015-10-11-20-37-42.png&quot; alt=&quot;Browsing Library&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/20151013-new-materialish-look-for-audiocanoe/Screenshot_2015-10-12-08-48-56.png&quot; alt=&quot;Now Playing&quot; /&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Sync your media to your phone with Audiocanoe</title>
   <link href="http://davidvedvick.info/notes/2015/12/24/audiocanoe-syncing" />
   <updated>2015-12-24T19:51:57.000Z</updated>
   <id>http://davidvedvick.info/notes/2015/12/24/audiocanoe-syncing</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Sync your media to your phone with Audiocanoe&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Sometimes, Santa wants to listen to his music in his sleigh but his connection
is spotty&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;What can Santa do? He can sync his music to his phone with the new version of
audiocanoe that is in testing! Following the gif below, Santa can easily sync
his favorite playlists and within minutes have them on his phone for playback:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/20151224-audiocanoe-syncing/2015_12_24_13_25_28.gif&quot; alt=&quot;Syncing Playlist&quot; /&gt;&lt;/p&gt;
&lt;p&gt;To grab it, head over to the &lt;a href=&quot;https://play.google.com/apps/testing/com.lasthopesoftware.bluewater&quot;&gt;beta test site&lt;/a&gt; and opt-in to help test it out!&lt;/p&gt;
&lt;p&gt;Happy holidays!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>lazy-j: Lazy Java initialization library</title>
   <link href="http://davidvedvick.info/notes/2016/01/05/lazy-j-lazy-java-initialization-library" />
   <updated>2016-01-06T05:04:01.000Z</updated>
   <id>http://davidvedvick.info/notes/2016/01/05/lazy-j-lazy-java-initialization-library</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;lazy-j: Lazy Java initialization library&lt;/h1&gt;
&lt;p&gt;Coming from the C# world, while working on audiocanoe I&apos;ve often had the
overwhelming desire to use something similar to the
&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/dd642331%28v=vs.110%29.aspx&quot;&gt;Lazy&lt;/a&gt;
class that is in the Standard libs for .Net. Using it, you can easily initialize
any object lazily without needing to implement your own double-check locked
lazy initialization code.&lt;/p&gt;
&lt;p&gt;So in a hasty moment, I wrote a library called &lt;code&gt;lazy-j&lt;/code&gt; which supposedly guarantees
your object will lazily be created the first time it is requested, using the
supplied initialization function. It should also be thread-safe. It is also
&lt;em&gt;EXCEEDINGLY&lt;/em&gt; simple, here&apos;s the source:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package com.vedsoft.lazyj;

/**
 * Created by david on 11/28/15.
 */
public abstract class Lazy&amp;lt;T&amp;gt; {

    private T object;

    public boolean isInitialized() {
        return object != null;
    }

    public T getObject() {
        return isInitialized() ? object : getValueSynchronized();
    }

    private synchronized T getValueSynchronized() {
        if (!isInitialized())
            object = initialize();

        return object;
    }

    protected abstract T initialize();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There&apos;s some nice things here; it uses Java&apos;s built in synchronized methods to
do a double-checked lock for object initialization. It doesn&apos;t have all the
niceties of Microsoft&apos;s library (such as different degrees of thread-safety),
but it gets the job done nicely while being simple enough to understand at a
glance.&lt;/p&gt;
&lt;p&gt;Usage is also fairly simple. To instantiate a new object do something like below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class MyClass {
    .
    .
    .

    public static Lazy&amp;lt;MyCrazySingletonConfig&amp;gt; myCrazySingletonConfig = new Lazy&amp;lt;MyCrazySingletonConfig&amp;gt;() {
        @Override
        protected MyCrazySingletonConfig initialize() {
            final MyCrazySingletonConfig newConfig = .....

            return newConfig;
        }
    };    
}

class SomeOtherClassThatNeedsConfig {

    public void doingThingsWithConfig() {
        final String property = MyClass.myCrazySingletonConfig.getObject().getMyCrazyProperty();
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can view the source &lt;a href=&quot;https://github.com/danrien/lazy-j&quot;&gt;here&lt;/a&gt;!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>What is Software Engineering and are we Software Engineers?</title>
   <link href="http://davidvedvick.info/notes/2016/05/18/what-is-software-engineering" />
   <updated>2016-05-19T05:31:58.000Z</updated>
   <id>http://davidvedvick.info/notes/2016/05/18/what-is-software-engineering</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;What is Software Engineering and are we Software Engineers?&lt;/h1&gt;
&lt;p&gt;In our day jobs, we often call ourselves many things (or our HR departments call us these terms for us):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Software Developer&lt;/li&gt;
&lt;li&gt;Programmer&lt;/li&gt;
&lt;li&gt;Software Designer&lt;/li&gt;
&lt;li&gt;Software Engineer&lt;/li&gt;
&lt;li&gt;Technologist &lt;em&gt;(what does this even mean?)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think most of us prefer the term &quot;Software Engineer&quot; at the end of the day; it tends to properly transmit the problem-solving needs, due diligence, and rigor required in our job, even if we don&apos;t apply those three traits all the time. We even may work with people ensuring the validity (and thus quality) of our software, who hold the title of &quot;Software Quality Engineer&quot;.&lt;/p&gt;
&lt;p&gt;But what really defines a Software Engineer? It&apos;s not enough to just have a title that gives a good feeling of the difficulties our job entails - is it? Well this question is answered easily enough - a Software Engineer is someone who practices Software Engineering!&lt;/p&gt;
&lt;p&gt;But then the next practical question becomes... what is Software Engineering? &lt;a href=&quot;https://en.wikipedia.org/wiki/Software_engineering&quot;&gt;Wikipedia gives Software Engineering &lt;em&gt;five possible definitions&lt;/em&gt;&lt;/a&gt;, which I&apos;ll repeat here for convenience:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&quot;research, design, develop, and test operating systems-level software, compilers, and network distribution software for medical, industrial, military, communications, aerospace, business, scientific, and general computing applications.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&quot;the systematic application of scientific and technological knowledge, methods, and experience to the design, implementation, testing, and documentation of software&quot;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&quot;the application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software&quot;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&quot;an engineering discipline that is concerned with all aspects of software production&quot;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&quot;the establishment and use of sound engineering principles in order to economically obtain software that is reliable and works efficiently on real machines.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok, so many of these definitions look somewhat flimsy on the face of it; perhaps for proper definition, one should look at what gave birth to other engineering disciplines.&lt;/p&gt;
&lt;h2&gt;The Birth of an Engineering Discipline&lt;/h2&gt;
&lt;p&gt;Mary Shaw from Carnegie Mellon University in a keynote address at the International Conference on Software Engineering, determined that an engineering discipline emerges following these rough steps:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/20160521-software-engineering/engineering-practice-flowchart.png&quot; alt=&quot;From craft practice to engineering discipline&quot; /&gt;
&lt;em&gt;A diagram detailing the process a craft practice goes through to become an engineering discipline&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;People begin using a new discovery or tool to solve some problems in simpler, newer, faster ways; this is the emergence of a craft practice around this discovery - say the &lt;em&gt;&quot;The emerging field of &quot;&lt;/em&gt; - or &lt;em&gt;The emerging field of Computer Science&lt;/em&gt; in the late 1950s through the 1980s.&lt;/li&gt;
&lt;li&gt;Some of these people start businesses with their new, disruptive products, others are hired to disrupt existing businesses&lt;/li&gt;
&lt;li&gt;The businesses begin running into problems with the new products, eventually practitioners of the craft in the field cannot solve problems of ever increasing complexity alone, spurring the need for research into how solve these problems&lt;/li&gt;
&lt;li&gt;Scientists develop new practices and methodologies, make new discoveries in the field to solve problems; in order to properly disseminate these findings, the scientists use all tools available: documentation, training, etc.&lt;/li&gt;
&lt;li&gt;The findings of these discoveries eventually coalesce into a discipline; finally we have engineering!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Software development is far along the path of becoming an engineering practice; people use the computer sciences to solve common problems in business, government, and medical fields. As problems are found with current patterns and practices, subsequent solutions are found, and disbursed through many avenues (a common one in our field is Stack Overflow!).&lt;/p&gt;
&lt;p&gt;Some tools and processes seem to introduce sea-changes in producing reliable code. The SOLID approach to object-oriented software design was one. From this, a whole literature has stemmed to produce consistently SOLID software designs. Peer review and test-driven development also seem like step-wise improvements in producing reliable software (by stressing as many variations of state that take place in a finite state machine as possible at time of development, a developer takes the step of not only ensuring correct operation of the code at the time of development, but also correct &lt;em&gt;forward&lt;/em&gt; operation of the code in the future).&lt;/p&gt;
&lt;p&gt;However, we aren&apos;t quite at the point where the science and tooling and practice sides of the equation have caught up to produce highly reliable code &lt;em&gt;and&lt;/em&gt; solve novel problems at a high frequency.&lt;/p&gt;
&lt;h2&gt;If Building Software is not yet an Engineering Practice, are we Engineers?&lt;/h2&gt;
&lt;p&gt;Now comes the chicken and egg question: does an engineering practice make an engineer, or does an engineer make an engineering practice?&lt;/p&gt;
&lt;p&gt;Instead of using the above process that Mary Shaw went through to define an engineering practice, let&apos;s look at what defines an engineer. From there we can maybe answer the question of what an engineer is without answering the question of what an engineering practice is.&lt;/p&gt;
&lt;p&gt;Let&apos;s think of the situation of an electrical engineer and a certified electrician: both are capable of designing operating electrical circuits. Both are knowledgeable in the real-world limits and dangers of electrical equipment and components. An electrician can likely solder components onto a board just as quickly and deftly as an electrical engineer. In other words, they&apos;re both capable of understanding and applying circuit theory.&lt;/p&gt;
&lt;p&gt;Where do they differ? What makes an electrical engineer&apos;s degree and certification harder to achieve? What do electrical engineers bring to the table that electricians do not? Perhaps the engineer solves novel electrical problems, but I think that an electrician is also capable of that when working within his own knowledge and what he has learned beyond that. Perhaps the engineer is tasked with staying at the forefront of his field, but a good electrician should also stay current with the field (and may be required to as well by government).&lt;/p&gt;
&lt;p&gt;It seems more correct to say that electrical engineers (are supposed to) have the ability to &lt;em&gt;contribute back to the fields of electrical engineering when a novel problem requires a novel solution outside of the bounds of the existing body of knowledge of the electrical engineering field&lt;/em&gt;. So maybe it is sufficient to say that an Engineer has enough mastery of the field they work in that they can contribute back to their field with novel solutions from outside of the discipline as it exists in that moment.&lt;/p&gt;
&lt;p&gt;So are software engineers, you know, engineers? In most engineering disciplines, proper testing and certification is required by state and national boards in order to properly claim that one is an engineer. This type of certification does not exist yet. IEEE offered a &lt;a href=&quot;https://en.wikipedia.org/wiki/Certified_Software_Development_Professional&quot;&gt;Certified Software Development Professional program at one time&lt;/a&gt;, but that was discontinued in 2014. Instead, they now offer certifications in &lt;a href=&quot;https://www.computer.org/web/education&quot;&gt;multiple areas of software development&lt;/a&gt;, with the reasoning seeming to be that software development covers too broad of a spectrum of software creation at the moment to be grouped into one certification.&lt;/p&gt;
&lt;p&gt;So at present, it doesn&apos;t seem that there are any widely recognized certifications that provide a definitive &quot;software engineer&quot; title. However, that doesn&apos;t mean that there are not many of us today who are in effect practicing the same disciplines as other engineers; it just may be that there is not yet enough agreed upon material for there to be a known, written determination of what makes the software engineering discipline.&lt;/p&gt;
&lt;h2&gt;So what?&lt;/h2&gt;
&lt;p&gt;I do predict that one day - perhaps 1500 years from now, but hopefully not that long - the title of Software Engineer will be a professional distinction that will require full testing and certification. At the end of the day, does any of this matter? If the rest of the industry is following the title of &quot;Software Engineer&quot;, then there doesn&apos;t seem to be any good reason to be apprehensive to the usage of the title of Software Engineer. However, I think after taking all of the above into account, we should feel encouraged and motivated to continue growing our practice, and contributing as much as we can to the development of software engineering as a discipline!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Concurrency vs. Parallelism: A breakfast example</title>
   <link href="http://davidvedvick.info/notes/2017/01/20/concurrency-vs-parallelism" />
   <updated>2017-12-03T17:45:49.000Z</updated>
   <id>http://davidvedvick.info/notes/2017/01/20/concurrency-vs-parallelism</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Concurrency vs. Parallelism: A breakfast example&lt;/h1&gt;
&lt;p&gt;One of the harder problems in Computer Science is concurrency. This summer at my employer, I gave a presentation on asynchrony, which I consider nearly the same thing as concurrency. One of the things that I felt was lacking was my explanation of concurrency vs. parallelism. I ended up just giving a textbook explanation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parallel processing is taking advantage of a lot of processors (local or remote) to run calculations on large volumes of data&lt;/li&gt;
&lt;li&gt;Asynchronous execution is freeing up the processor to do other things while a lengthy operation is occurring&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This morning, however, I was making myself breakfast, and I thought up a useful analogy.&lt;/p&gt;
&lt;h2&gt;A breakfast example&lt;/h2&gt;
&lt;p&gt;My breakfast this morning consisted of a coffee and two slices of toast with peanut butter.&lt;/p&gt;
&lt;p&gt;A perfect example of concurrency was how I made the breakfast: I first started the toast, then put the coffee cup in the Keurig and pushed the brew button on the Keurig. This is a &lt;strong&gt;concurrent&lt;/strong&gt; operation - one job (toasting the bread) was started, and after that began, I (the processor) was freed up to start another job, the &quot;brew coffee&quot; operation.&lt;/p&gt;
&lt;p&gt;We can take this analogy further: the toaster can actually process two pieces of bread at once, which is a &lt;strong&gt;parallel&lt;/strong&gt; operation. From here, we can easily see that parallelism is a subset of concurrency: technically, the toaster is technically performing two operations concurrently, what makes it a parallel operation is the fact that it&apos;s the same process occurring twice, started at the same time within the same machine.&lt;/p&gt;
&lt;p&gt;Should we write this as C#?&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Program&lt;/span&gt; {
  &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Main&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt; {
    MakeBreakfast().Wait();
  }

  &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;MakeBreakfast&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt; {
    &lt;span class=&quot;hljs-comment&quot;&gt;// Start toast - this operation takes the longest to complete, so let&apos;s get&lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;// it started as soon as possible&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; toaster = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; StandardToaster(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; ElectricitySupplier());
    &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; toastingTask = toaster.Toast(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; WheatBread(), &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; WheatBread());

    &lt;span class=&quot;hljs-comment&quot;&gt;// Now start the Keurig, a relatively short operation&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; brewer = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Keurig(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Water());
    &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; brewingTask = brewer.Brew(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; DarkCoffee());

    &lt;span class=&quot;hljs-comment&quot;&gt;// Don&apos;t return control to the human until operations complete&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; Task.WhenAll(toastingTask, brewingTask);
  }

  &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Toaster&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Task&amp;lt;IEnumerable&amp;lt;Toast&amp;gt;&amp;gt; Toast(Bread bread, Bread bread);
  }

  &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Brewer&lt;/span&gt; {
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Task&amp;lt;Coffee&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;Brew&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;GroundCoffee groundCoffee&lt;/span&gt;)&lt;/span&gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Concurrency and Parallelism in Real Life&lt;/h2&gt;
&lt;p&gt;The thing about concurrency and parallelism is that you can do this all the time; for example, humans are terrible at multi-tasking (parallel processing), but are great at starting multiple jobs, and then taking action when they finish (concurrent processing).&lt;/p&gt;
&lt;p&gt;I encourage everyone to always think of how the things they do in real life apply to different concepts in software development. Since software development is all about automating real life processes, these analogies actually occur much more frequently than one would expect!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Things I've Built Building an Android Music Player</title>
   <link href="http://davidvedvick.info/notes/2018/02/18/things-ive-learnt-building-an-android-music-player" />
   <updated>2018-04-08T17:02:45.000Z</updated>
   <id>http://davidvedvick.info/notes/2018/02/18/things-ive-learnt-building-an-android-music-player</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Things I&apos;ve Built While Building an Android Music Player&lt;/h1&gt;
&lt;p&gt;Five and a half years ago, I &lt;a href=&quot;/notes/2012/11/04/music-streamer-for-j-river-media-center-on-the-way&quot;&gt;began building an Android application&lt;/a&gt; to stream music from my home server, which runs &lt;a href=&quot;https://jriver.com/&quot;&gt;J River media center&lt;/a&gt;. Looking back, the journey has been as or more rewarding than the destination, as I only have about 20 active users on a given day beyond myself, but the software I&apos;ve built along the way has been extremely fun to build. On the other hand, it&apos;s often been an act of frustration to build an application in Android&apos;s language of choice, as many of the tools I expected to have even back in 2012 were missing from the Java ecosystem. As a result, I built some of these tools myself.&lt;/p&gt;
&lt;p&gt;Those tools were Lazy-J, a simple Lazy instantiation library, Artful, a library that serializes SQLite queries and results from and to Java classes, and Handoff, a promise library for easy asynchronous programming. While each of these libraries could probably have had many posts devoted to each of them, I find writing painful, so I&apos;ll devote this one blog-post to them all, and hopefully do them some of the justice they deserve.&lt;/p&gt;
&lt;h2&gt;Lazy-J&lt;/h2&gt;
&lt;p&gt;One of the things I missed when I was working in Java was the lack of lazy instantiation in the standard library. While there&apos;s all sorts of recommendations on how to do lazy instantiation, the approaches usually only apply to static methods, and rely on intimate knowledge of the runtime and Java spec to properly expect lazy operation. I needed a way to do a &lt;code&gt;private final Lazy&amp;lt;MyObject&amp;gt; lazyObject = new Lazy&amp;lt;MyObject&amp;gt;()&lt;/code&gt;, because I often needed to use a shared resource in my Android view objects without knowing when they&apos;d be created.&lt;/p&gt;
&lt;p&gt;I&apos;ve seen IOC frameworks such as &lt;a href=&quot;https://github.com/google/dagger&quot;&gt;Dagger&lt;/a&gt; do this, but my application was never complicated enough to warrant using an IOC framework. I also confess to not being a huge fan of Java IOC frameworks due to their dependence on attributes (although it&apos;s understandable given the language&apos;s limitations).&lt;/p&gt;
&lt;p&gt;Usage of Lazy-J is pretty straight-forward - a simple usage, just new-ing up an object, looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-java&quot;&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MyClass&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; readonly Lazy&amp;lt;Object&amp;gt; lazyObject = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Lazy&amp;lt;Object&amp;gt;(Object::&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&apos;ve abused Lazy-J excessively, for example, I don&apos;t want to have to run &lt;code&gt;findView&lt;/code&gt; all the time to get a view, so I have a class titled &lt;code&gt;LazyViewFinder&lt;/code&gt;, which will hold on to the reference to the view the first time you use it. This class lets me hold a reference to the view in my class, so I can reference my views like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Activity&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; LazyViewFinder&amp;lt;TextView&amp;gt; lblConnectionStatus = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; LazyViewFinder&amp;lt;&amp;gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;, R.id.lblConnectionStatus);

  &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;handleConnectionStatusChange&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt; status)&lt;/span&gt; &lt;/span&gt;{
    .
    .
    .

    &lt;span class=&quot;hljs-keyword&quot;&gt;final&lt;/span&gt; TextView lblConnectionStatusView = lblConnectionStatus.findView();
        &lt;span class=&quot;hljs-keyword&quot;&gt;switch&lt;/span&gt; (status) {
        &lt;span class=&quot;hljs-keyword&quot;&gt;case&lt;/span&gt; BuildingSessionConnectionStatus.GettingLibrary:
            lblConnectionStatusView.setText(R.string.lbl_getting_library_details);
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt;;
    }
    .
    .
    .
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can find lazy-j at &lt;a href=&quot;https://github.com/danrien/lazy-j&quot;&gt;https://github.com/danrien/lazy-j&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Artful&lt;/h2&gt;
&lt;p&gt;Artful is a library which also began as a source of frustration: at the time (and even today?) there are not many easy, transferable ways to easily map the results of a SQL query on the built-in SQLite database to a Java object.&lt;/p&gt;
&lt;p&gt;In C#, using the excellent &lt;a href=&quot;https://github.com/StackExchange/Dapper&quot;&gt;Dapper&lt;/a&gt; library, one can just do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;using&lt;/span&gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; connection = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; SqlConnection())
{
  &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; conn.QueryAsync&amp;lt;MyObject&amp;gt;(&lt;span class=&quot;hljs-string&quot;&gt;&quot;select * from my_object&quot;&lt;/span&gt;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Perfectly bridging the gap between SQL Queries and a strongly-typed languague, while still allowing each language to flex its respective strengths (small note: I think future interop efforts between languages should focus on these types of bridges).&lt;/p&gt;
&lt;p&gt;Due to type erasure, we can&apos;t do quite the same thing in Java, but with Artful, I managed to get pretty close:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-java&quot;&gt;
&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Collection&amp;lt;Library&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;getLibraries&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(Context context)&lt;/span&gt; &lt;/span&gt;{
  RepositoryAccessHelper repositoryAccessHelper = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; RepositoryAccessHelper(context);
  &lt;span class=&quot;hljs-keyword&quot;&gt;try&lt;/span&gt; {
      &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt;
          repositoryAccessHelper
              .mapSql(&lt;span class=&quot;hljs-string&quot;&gt;&quot;SELECT * FROM library&quot;&lt;/span&gt;)
              .fetch(Library.class);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Artful is new&apos;d up inside of &lt;code&gt;RepositoryAccessHelper&lt;/code&gt;, which does this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-java&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Artful &lt;span class=&quot;hljs-title&quot;&gt;mapSql&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String sqlQuery)&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Artful(sqliteDb.getObject(), sqlQuery);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since Artful caches the SQL queries and the reflection, it becomes pretty performant after the first round of serialization on a given class. It is by no means feature-complete, for example it can&apos;t serialize directly to primitive types - &lt;code&gt;repositoryAccessHelper.mapSql(&quot;SELECT COUNT(*) FROM library&quot;).fetchFirst(Long.class)&lt;/code&gt; would likely give you nothing - but it has served me remarkably well, without memory leaks as well.&lt;/p&gt;
&lt;p&gt;You can find Artful at &lt;a href=&quot;https://github.com/namehillsoftware/artful&quot;&gt;https://github.com/namehillsoftware/artful&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Handoff&lt;/h2&gt;
&lt;p&gt;Asynchronous programming in Java is really painful. Java has &lt;code&gt;Future&lt;/code&gt;, which purports to be the way to perform asynchronous behavior, but it merely introduces a &lt;em&gt;spin-lock&lt;/em&gt; to achieve receiving a value &lt;em&gt;synchronously&lt;/em&gt; on your calling thread. While this may be fine behavior for a server application (although many a NodeJS and nginx server may disagree with you on the principle of thread starvation), for a desktop application, knowingly introducing blocking behavior into your application is border-line offensive.&lt;/p&gt;
&lt;p&gt;Android attempted to make this better with &lt;code&gt;AsyncTask&lt;/code&gt;, but I found it to be nearly as painful to work with as &lt;code&gt;Future&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It&apos;s difficult to easily chain one asynchronous action to another without developing verbose APIs&lt;/li&gt;
&lt;li&gt;It has messy internal state that &lt;a href=&quot;https://github.com/aosp-mirror/platform_frameworks_base/blob/d61e87ad0899c8a737aa8f3f43b263bcee24325f/core/java/android/os/AsyncTask.java#L634&quot;&gt;leaks into your consumption of the library with unchecked exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Results &lt;a href=&quot;https://github.com/aosp-mirror/platform_frameworks_base/blob/d61e87ad0899c8a737aa8f3f43b263bcee24325f/core/java/android/os/AsyncTask.java#L707&quot;&gt;post back to the UI thread&lt;/a&gt; that it was called on, which is often all that is wanted in simple applications, but the second you have to perform additional asynchronous work, starts to cause troubles&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Handoff is the last library I&apos;ve developed for my little music player, and the one of which I am proudest. Handoff aims to be a Promises A+ like promise library for Java. While Java has &lt;code&gt;CompletableFuture&lt;/code&gt;, I find its API surface layer to be &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html&quot;&gt;rather large&lt;/a&gt;. In this instance, I also found C#&apos;s &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx&quot;&gt;Task&lt;/a&gt; library to be very verbose - they had to introduce an entirely new language primitive just to make it easier to work with (&lt;code&gt;async/await&lt;/code&gt;)! I even speculate that the &lt;code&gt;Task&lt;/code&gt; library was explicitly written to set the stage for &lt;code&gt;async/await&lt;/code&gt; ;).&lt;/p&gt;
&lt;p&gt;I really like the ergonomics of Javascript&apos;s &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&quot;&gt;Promise&lt;/a&gt; class, and thought it would be fun to see if I could make something like that for Java. It has both been fun to develop and tremendously beneficial! I wish it was easy to show a side-by-side comparison of my app&apos;s responsiveness before and after using &lt;code&gt;Handoff&lt;/code&gt;, but the difference has been night and day for me - ever since switching to a promise-like async model, I rarely get UI hangs or unresposive warnings from the OS, and unexpected &lt;code&gt;IllegalStateException&lt;/code&gt; hangs have gone completely away.&lt;/p&gt;
&lt;p&gt;Handoff in the simple case is used like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Promise&amp;lt;&amp;gt;(messenger -&amp;gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;final&lt;/span&gt; IPositionedFileQueueProvider queueProvider = positionedFileQueueProviders.get(nowPlaying.isRepeating);
    &lt;span class=&quot;hljs-keyword&quot;&gt;try&lt;/span&gt; {
        &lt;span class=&quot;hljs-keyword&quot;&gt;final&lt;/span&gt; PreparedPlayableFileQueue preparedPlaybackQueue = preparedPlaybackQueueResourceManagement.initializePreparedPlaybackQueue(queueProvider.provideQueue(playlist, playlistPosition));
        startPlayback(preparedPlaybackQueue, filePosition)
            .firstElement() &lt;span class=&quot;hljs-comment&quot;&gt;// Easily move from one asynchronous library (RxJava) to Handoff&lt;/span&gt;
            .subscribe(
        playbackFile -&amp;gt; messenger.sendResolution(playbackFile.asPositionedFile()), &lt;span class=&quot;hljs-comment&quot;&gt;// Resolve&lt;/span&gt;
        messenger::sendRejection); &lt;span class=&quot;hljs-comment&quot;&gt;// Reject&lt;/span&gt;
    } &lt;span class=&quot;hljs-keyword&quot;&gt;catch&lt;/span&gt; (Exception e) {
        messenger.sendRejection(e);
    }
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The returned promise can then be chained as you&apos;d expect:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-java&quot;&gt;playlist.promiseFirstFile()
  .then(f -&amp;gt; { &lt;span class=&quot;hljs-comment&quot;&gt;// Perform another action immediately with the result - this continues on the same thread the result was returned on&lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;// perform action&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; f; &lt;span class=&quot;hljs-comment&quot;&gt;// return a new type if wanted, return null to represent Void&lt;/span&gt;
  })
  .eventually(f -&amp;gt; { &lt;span class=&quot;hljs-comment&quot;&gt;// Handoff the result to a method that is expected to produce a new promise&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Promise&amp;lt;&amp;gt;(m -&amp;gt; {

    });
  })
  .excuse(e -&amp;gt; { &lt;span class=&quot;hljs-comment&quot;&gt;// Do something with an error, errors fall through from the top, like with try/catch&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; e;
  })
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Handoff can be found here - &lt;a href=&quot;https://github.com/danrien/handoff&quot;&gt;https://github.com/danrien/handoff&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And the application that motivated me to build all of these little libraries is Music Canoe, which can be found here - &lt;a href=&quot;https://github.com/danrien/projectBlue&quot;&gt;https://github.com/danrien/projectBlue&lt;/a&gt;.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>A Conceptual Model of Async/Await</title>
   <link href="http://davidvedvick.info/notes/2019/03/21/conceptual-model-of-async-await" />
   <updated>2019-03-24T15:30:58.000Z</updated>
   <id>http://davidvedvick.info/notes/2019/03/21/conceptual-model-of-async-await</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;A Conceptual Model of Async/Await&lt;/h1&gt;
&lt;p&gt;Microsoft released the async/await programming model to the world in &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-version-history#c-version-50&quot;&gt;2012&lt;/a&gt;. While many of us diligent C# developers have been advocating the use of async/await since then, I have noticed many programmers still struggle with finding the benefits of async/await worth the cost of understanding. There&apos;s a few behaviors I notice when looking through code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Developers will often go for synchronous code over asynchronous&lt;/li&gt;
&lt;li&gt;Continued use of &lt;code&gt;Task.Result&lt;/code&gt; to force a task into performing synchronously&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These behaviors indicate (to me) that developers have a hard time seeing the benefit of asynchronous code over synchronous. And to be fair, in their day-to-day development activities, it may seem like async/await just adds another layer of cognitive overhead to an already difficult job. Throughout this post, I will try to give a simple model with which to conceptualize async/await and show some of the fun things you can do with async/await.&lt;/p&gt;
&lt;p&gt;Most of this text is also applicable to Javascript Promises, and their async/await implementation. This is because C# Tasks and Javascript Promises are both implementations of the same construct, better covered by Wikipedia than myself: &lt;a href=&quot;https://en.wikipedia.org/wiki/Futures_and_promises&quot;&gt;https://en.wikipedia.org/wiki/Futures_and_promises&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The Simple Model&lt;/h2&gt;
&lt;p&gt;This is all that async/await does:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An &lt;code&gt;await&lt;/code&gt; signals that you desire for your current line of code to &lt;strong&gt;pause execution&lt;/strong&gt; until the task you are waiting for completes execution. Once the task completes, the code after your current line will continue execution. You can only await an object that has a &lt;code&gt;GetAwaiter()&lt;/code&gt; method which returns an implementation of &lt;code&gt;INotifyCompletion&lt;/code&gt;. In the wild, this is usually a &lt;code&gt;Task&lt;/code&gt; class.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;async&lt;/code&gt; tells the compiler that you want to use the &lt;code&gt;await&lt;/code&gt; keyword in a function. The function must return a type &lt;code&gt;Task&amp;lt;...&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Uses&lt;/h2&gt;
&lt;p&gt;Now that we have a simple conceptual model for async/await, we can have a lot of fun with async/await while continuing to write code that is easy to reason with.&lt;/p&gt;
&lt;h3&gt;Imperative Code Style&lt;/h3&gt;
&lt;p&gt;Below is a simple example to illustrate the difference between using a &lt;code&gt;Task&lt;/code&gt; with continuations and using a &lt;code&gt;Task&lt;/code&gt; with &lt;code&gt;await&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;Main&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;
{
  GetData()
    .ContinueWith(myData =&amp;gt;
    {
      &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myProcessor = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Processor();
      &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; myProcessor.Process(myData.Result);
    }, TaskCompletionOptions.OnlyOnRanToCompletion)
    .Unwrap()
    .Wait();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above callback style model can become this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;Main&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;
{
  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myData = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; GetData();

  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myProcessor = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Processor();
  &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; myProcessor.Process(myData);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This contrived example obviously doesn&apos;t show much, but the code does arguably become cleaner. Async/await also opens us up to using other programming constructs, such as loops, with our asynchronous code. So taking the above example, let&apos;s say the data is an &lt;code&gt;IEnumerable&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;Main&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;
{
  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myData = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; GetData();

  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myProcessor = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Processor();

  &lt;span class=&quot;hljs-keyword&quot;&gt;foreach&lt;/span&gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; data &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; myData)
  {
    &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; myProcessor.Process(data);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&apos;m not even going to bother to try to write this with a Task chain! It&apos;s important to note that while this code does not block while waiting for the data to process, the code still does execute in-order. Async/await enables us to write non-blocking code with our typical C# programming style, which is really neat. However, we can do some even more interesting things with Tasks.&lt;/p&gt;
&lt;h3&gt;Interleaving&lt;/h3&gt;
&lt;p&gt;Interleaving is one of my favorite uses of async/await. Rather than immediately pausing execution on a long-running task, we can start execution of the task, hold onto the &lt;strong&gt;task itself&lt;/strong&gt;, and then start execution of other tasks in the meanwhile. When we&apos;re actually ready for the result of the first task, we can then await it. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;Main&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;
{
  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myDataTask = GetData(); &lt;span class=&quot;hljs-comment&quot;&gt;// Hold onto a reference of the Task, rather than the result of the Task&lt;/span&gt;

  &lt;span class=&quot;hljs-comment&quot;&gt;// Execution can still be paused in the method on the Tasks below, and the myDataTask&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;// will continue execution in its own synchronization context (usually a Thread)&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; Console.WriteLineAsync(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Please input some additional data while the other data loads!&quot;&lt;/span&gt;);
  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; additionalData = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; Console.ReadLineAsync();

  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myProcessor = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Processor();

  &lt;span class=&quot;hljs-comment&quot;&gt;// Finally pause for `myDataTask` to complete execution&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; myProcessor.Process(&lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; myDataTask, additionalData);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This allows gathering data from your data source while the user is keying in other data, potentially masking the time it took to retrieve the data from the data source.&lt;/p&gt;
&lt;h3&gt;Racing&lt;/h3&gt;
&lt;p&gt;Tasks also have the combinatorial helpers &lt;code&gt;Task.WhenAll(Task...)&lt;/code&gt; and &lt;code&gt;Task.WhenAny(Task...)&lt;/code&gt; (or &lt;code&gt;Promise.all(Promise...)&lt;/code&gt; and &lt;code&gt;Promise.race(Promise...)&lt;/code&gt; for those Javascript folks following along). While the applications of &lt;code&gt;Task.WhenAll&lt;/code&gt; may seem obvious (and I will cover them soon), it is a little more difficult to find a use for &lt;code&gt;Task.WhenAny&lt;/code&gt;. Often times, I&apos;ll use &lt;code&gt;Task.WhenAny&lt;/code&gt; when I want to execute multiple tasks and change the control flow of my program as a result of which task completed first - timing out execution is a clear use case for this pattern.&lt;/p&gt;
&lt;p&gt;Let&apos;s say we&apos;re waiting for our data to come in on a message bus:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task&amp;lt;&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;Main&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;
{
  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myDataTask = GetDataOffOfMessageBus();

  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; raceResult = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; Task.WhenAny(myDataTask, Task.Delay(TimeSpan.FromMinutes(&lt;span class=&quot;hljs-number&quot;&gt;30&lt;/span&gt;)));

  &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (myDataTask != raceResult) &lt;span class=&quot;hljs-comment&quot;&gt;// Task.WhenAny returns a `Task&amp;lt;Task&amp;gt;`, whose result is the winning task&lt;/span&gt;
  {
    &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; Console.WriteLineAsync(&lt;span class=&quot;hljs-string&quot;&gt;&quot;What&apos;s taking that message so long?&quot;&lt;/span&gt;);
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;-1&lt;/span&gt;; &lt;span class=&quot;hljs-comment&quot;&gt;// Unceremoniously stop the program&lt;/span&gt;
  }

  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myProcessor = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Processor();
  &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; myProcessor.Process(&lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; myDataTask); &lt;span class=&quot;hljs-comment&quot;&gt;// You can also await the same Task multiple times, the result is held onto by the task once it completes, so it will always be the same **reference** or **value**&lt;/span&gt;

  &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Aggregation&lt;/h3&gt;
&lt;p&gt;Once you start interleaving and racing your code, you will start having the desire to just not wait at all for anything until it&apos;s absolutely needed. Aggregation of your tasks using &lt;code&gt;Task.WhenAll(Task...)&lt;/code&gt; can help you with this.&lt;/p&gt;
&lt;p&gt;Let&apos;s take the above example where we iterated over an &lt;code&gt;IEnumerable&lt;/code&gt; of data. Let&apos;s instead use the combined power of LINQ and Tasks to process all of that data all at once:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;Main&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;
{
  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myData = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; GetData();

  &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; myProcessor = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Processor();

  &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; Task.WhenAll(myData.Select(&lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; data =&amp;gt;
  {
    &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; myProcessor.Process(data)); &lt;span class=&quot;hljs-comment&quot;&gt;// You could also just return the Task returned by `Process`, which might give you some speed benefits&lt;/span&gt;
  });
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;A Cautionary Note&lt;/h2&gt;
&lt;p&gt;It&apos;s important to note that except for the first two examples, all the above examples introduce &lt;em&gt;concurrency&lt;/em&gt; into your code. Along with concurrency come all the concerns that plague concurrent models: deadlocks, unsynchronized state, etc. That being said, it&apos;s still completely acceptable (and possible) to write &lt;strong&gt;non-concurrent&lt;/strong&gt; code with async/await, such as in the first two examples, and still realize benefits. That&apos;s because every operating system comes with a maximum number of supported native threads [0][1] (which many runtimes use) and an &lt;code&gt;await&lt;/code&gt; call frees up that thread to either be used by something else, or to be collected by the garbage collector. This is why async/await helps your application more efficiently use its hosts resources - whether it be for parallel processing or just conservative use of threads. I hope you come to enjoy the benefits of having the more responsive and conscientious applications that async/await brings you as much as I have.&lt;/p&gt;
&lt;p&gt;[0] Increasing number of threads per process (Linux) (&lt;a href=&quot;https://dustycodes.wordpress.com/2012/02/09/increasing-number-of-threads-per-process/&quot;&gt;https://dustycodes.wordpress.com/2012/02/09/increasing-number-of-threads-per-process/&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;[1] Does Windows have a limit of 2000 threads per process?
&lt;a href=&quot;https://devblogs.microsoft.com/oldnewthing/20050729-14/?p=34773&quot;&gt;https://devblogs.microsoft.com/oldnewthing/20050729-14/?p=34773&lt;/a&gt;)&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>The Satisfaction of UI Development</title>
   <link href="http://davidvedvick.info/notes/2019/09/20/satisfaction-of-ui-development" />
   <updated>2019-09-21T04:47:54.000Z</updated>
   <id>http://davidvedvick.info/notes/2019/09/20/satisfaction-of-ui-development</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;The Satisfaction of UI Development&lt;/h1&gt;
&lt;p&gt;There&apos;s something oddly satisfying about UI Development. These days I spend most of my time doing back-end, server-side work, and that&apos;s highly satisfying as well... but there&apos;s something about being able to see and play with the results yourself when a change is made.&lt;/p&gt;
&lt;p&gt;Anyways, that&apos;s of course going to lead to a screenshot of my latest update to project blue, which introduced a fancy, transparent, &lt;em&gt;right-handed&lt;/em&gt; sliding drawer for the Now Playing list:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/20190920-satisfaction-of-ui-development/Screenshot_20190921-090430.png&quot; alt=&quot;New Slide Out Now Playing Drawer&quot; /&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>May 2021 Log</title>
   <link href="http://davidvedvick.info/notes/2021/05/01/log" />
   <updated>2021-05-01T00:00:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2021/05/01/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;May 20th, 2021&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;These are notes I took from the 2021 &lt;a href=&quot;https://opensourcenorth.com/&quot;&gt;Open-Source North&lt;/a&gt; conference, which takes place annually in Minneapolis, Minnesota&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Deep Learning for Natural Language Processing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Natural Language Understanding (NLU) is the focus of this talk&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Natural Language Generation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mapping from computer representation space to language space&lt;/li&gt;
&lt;li&gt;Opposite direction of NLU&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Deep Learning&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Subfield of machine learning&lt;/li&gt;
&lt;li&gt;Algorithms inspired by the structure and function of the brain called artificial neural networks&lt;/li&gt;
&lt;li&gt;Advantage over machine learning is to extract features automatically&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Text is Messy&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Punctuation, typos, unknown words, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Preprocessing Techniques&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Turn the text into meaningful format for analysis (tokenization)&lt;/li&gt;
&lt;li&gt;Clean the data&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Remove: upper case letters, punctuation, numbers, stop words&lt;/li&gt;
&lt;li&gt;Stemming&lt;/li&gt;
&lt;li&gt;Parts of speech tagging&lt;/li&gt;
&lt;li&gt;Correct misspelled words&lt;/li&gt;
&lt;li&gt;Chunking (named entity recognition, compound term extraction)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Preprocessing: stemming&lt;/h4&gt;
&lt;p&gt;Stemming and Lemmatization = cut word down to base form&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stemming: uses rough heuristics to reduce words to base&lt;/li&gt;
&lt;li&gt;Lemmatization: uses vocabulary and morphological analysis&lt;/li&gt;
&lt;li&gt;Makes the meaning of run, runs, running, ran all the same&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Bag of words&lt;/h4&gt;
&lt;p&gt;Way of representing text data when modeling text with machine learning or deep learning algorithms&lt;/p&gt;
&lt;h4&gt;Word embeddings&lt;/h4&gt;
&lt;p&gt;Type of word representation that allows words with similar meaning to have a similar representation&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They are a distributed representation of text&lt;/li&gt;
&lt;li&gt;Word embedding methods learn a real-valued vector representation for a predefined fixed sized vocabulary from a corpus of text&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Word2Vec&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Problem: count vectors far too large for many documents&lt;ul&gt;
&lt;li&gt;Solution: Word2Vec reduces number of dimensions (configurable, e.g. 300)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Problem: bag of words neglects word order&lt;/li&gt;
&lt;li&gt;SkipGrams: SkipGrams is a neural network architecture that uses a word to predict the words in the surrounding context, defined by the window size&lt;/li&gt;
&lt;li&gt;Continuous Bag of Words: CBOW uses the surrounding context&lt;/li&gt;
&lt;li&gt;What happens? Learns words likely to appear near each word&lt;/li&gt;
&lt;li&gt;Vector scan combined to create features for documents&lt;/li&gt;
&lt;li&gt;Use Document Vectors for ML/DL on documents (classification, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Feature Selection&lt;/h3&gt;
&lt;p&gt;Manual process in traditional machine learning techniques, which happens automatically in deep learning&lt;/p&gt;
&lt;h4&gt;Embeddings + CNN&lt;/h4&gt;
&lt;p&gt;Using word embeddings for representing words and convolution neural network for classification task. Architecture has 3 pieces:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Word embedding model: generate word vectors&lt;/li&gt;
&lt;li&gt;Convolutional model: extracts salient features from documents&lt;/li&gt;
&lt;li&gt;Full-connected model: interpretation of extracted features in terms of a predictive model&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Recurrent Neural Networks&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Networks with loops&lt;/li&gt;
&lt;li&gt;Allows information to persist&lt;/li&gt;
&lt;li&gt;Enables connecting previous information to present task&lt;/li&gt;
&lt;li&gt;Context preserved&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Vanishing Gradients with RNN&apos;s&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;In the simplest form RNN&apos;s don&apos;t work as well as wanted&lt;/li&gt;
&lt;li&gt;Learning rate drops with back propagation&lt;/li&gt;
&lt;li&gt;Long-Short-Term Memory units help combat the vanishing gradient problem by introducing an &quot;error carousel&quot;.&lt;ul&gt;
&lt;li&gt;Allows learning sequences, keeping track of the order without a vanishing gradient&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Major challenges with DL for NLP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Data size: RNN/LSTM doesn&apos;t generalize well on small datasets&lt;/li&gt;
&lt;li&gt;Relevant Corpus: required to create domain specific word embedding&lt;/li&gt;
&lt;li&gt;Deeper Networks: empirically deeper networks have better accuracy&lt;/li&gt;
&lt;li&gt;Training Time: RNN&apos;s take a long time to learn&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/hardlyhuman&quot;&gt;https://github.com/hardlyhuman&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Robot Rock - AI and Music Composition&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Previous Examples of Music Generation:&lt;ul&gt;
&lt;li&gt;Mozart?! - developed game for auto-generating music&lt;/li&gt;
&lt;li&gt;ILIAC 1&lt;/li&gt;
&lt;li&gt;Neural Networks&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Machine Learning used for Music Generation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Standard feed forward networks aren&apos;t a good fit for predicting sequential events (e.g. music, text)&lt;ul&gt;
&lt;li&gt;Limitation: fixed number of inputs/outputs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Recurrent Neural Networks (RNN)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Better for text/music&lt;/li&gt;
&lt;li&gt;LSTM is key to improving results&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Music Encoding Options&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MIDI&lt;/li&gt;
&lt;li&gt;Waveform&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Programs that Do Music Generation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Amper&lt;/li&gt;
&lt;li&gt;AIVA&lt;ul&gt;
&lt;li&gt;Generational soundtracks for video games?!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;LANDR - AI based mastering of music&lt;/li&gt;
&lt;li&gt;Magenta (Google)&lt;/li&gt;
&lt;li&gt;OpenAI: MuseNet (built off of MuseTree), JukeBox&lt;/li&gt;
&lt;li&gt;PopGun&lt;/li&gt;
&lt;li&gt;Live Performance toolsTidal Cycles, Orca&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Artists That Use AI&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Taryn Southern - I Am AI (2018)&lt;/li&gt;
&lt;li&gt;Yacht - Chain Tripping (2019)&lt;ul&gt;
&lt;li&gt;Transcribed entire backlog to MIDI to train Magenta&lt;/li&gt;
&lt;li&gt;Treated ML as a collaborator&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Holly Herndon - Proto (2019)&lt;ul&gt;
&lt;li&gt;Created &quot;Spawn&quot;, which performed music&lt;/li&gt;
&lt;li&gt;She earned her PhD based on this album&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Lyrics Generation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;GPT-2 has a model to generate lyrics&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Empowering Streams through KSQL&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Querying Kafka streams through KSQL&lt;/li&gt;
&lt;li&gt;Custom Data Integration is hard: ephemeral isn&apos;t useful, stateful is hard&lt;/li&gt;
&lt;li&gt;Kafka: A-B integration allows loose coupling, with Kafka as the middle layer&lt;/li&gt;
&lt;li&gt;Kafka can handle load with a very predictive, linearly scaling, model&lt;/li&gt;
&lt;li&gt;Kafka partitions data with &quot;Topics&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kafka Data Transformation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Single Message Transforms (SMT)&lt;ul&gt;
&lt;li&gt;Transformations configured via JSON&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;KStreams: advanced message transforms in Java&lt;/li&gt;
&lt;li&gt;KStream - unending list of messages arriving&lt;/li&gt;
&lt;li&gt;KTable - a projection of the most recent value in a KStream&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ksqlDB&lt;/h3&gt;
&lt;p&gt;Uses a SQL interface to work against KTables/KStreams&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Emit changes&lt;/code&gt; keyword continuously runs query&lt;/li&gt;
&lt;li&gt;Has basic querying capabilities, and other functions, that work against Kafka streams&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ksqldb.io&lt;/li&gt;
&lt;li&gt;Confluent open source&lt;/li&gt;
&lt;li&gt;Confluent runs cloud native Kafka distribution&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Lessons on Chaos Engineering&lt;/h2&gt;
&lt;p&gt;Chaos engineering is an experiment, building an experiment around steady-state hypothesis.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not all signs are useful.&lt;/li&gt;
&lt;li&gt;&quot;The future seems implausible, the past incredible&quot;&lt;/li&gt;
&lt;li&gt;Weak signals are the signals we get before something goes wrong, and are an important insight into something before it goes wrong&lt;/li&gt;
&lt;li&gt;Search for how close we are to failure&lt;/li&gt;
&lt;li&gt;Past signals may not be future signals, future signals may come from areas that were not signalling before&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Insights that Come From Weak Signals&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;On-Call shifts should end on Fridays!&lt;ul&gt;
&lt;li&gt;Engineers are tired, and&lt;/li&gt;
&lt;li&gt;On-call shifts ended on Fridays and begin for the next person Friday&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A designated &quot;ops-support&quot; person&lt;/li&gt;
&lt;li&gt;&quot;I don&apos;t know anything about this, we&apos;ll need to talk to Emma.&quot;: signalling the system is approaching a boundary - what happens if Emma decides to pursue other opportunities?&lt;/li&gt;
&lt;li&gt;Value proposition of chaos engineering is the insights you gain&lt;/li&gt;
&lt;li&gt;Rare that a single signal is strong enough&lt;/li&gt;
&lt;li&gt;Having a multi-functional product team is the best way to make products&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Technical Excellence through Mob Programming&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Retrospectives: tie together learning time&lt;/li&gt;
&lt;li&gt;1 year of no bugs! Organization chose to scale mob programming.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;How to Mob Program&lt;/h3&gt;
&lt;h4&gt;The Mob Programming RPG&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/willemlarsen/mobprogrammingrpg&quot;&gt;https://github.com/willemlarsen/mobprogrammingrpg&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Driver: drive the PC&lt;/li&gt;
&lt;li&gt;Navigator: gives the directions on what to program&lt;/li&gt;
&lt;li&gt;Mobber: yield to less privileged voice, contributes ideas&lt;/li&gt;
&lt;li&gt;Researcher: break off on tangents to look into different ideas&lt;/li&gt;
&lt;li&gt;Sponsor: speak-up for others&lt;/li&gt;
&lt;li&gt;Navigator of the Navigator: navigates the navigator!&lt;/li&gt;
&lt;li&gt;Automationist: sees a developer doing the same thing over and over again, might be able to automate those things&lt;/li&gt;
&lt;li&gt;The Nose: calls out code smells&lt;/li&gt;
&lt;li&gt;Traffic Cop: keeps everyone in line&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other Mob Role Taxonomies: other mob role taxonomies exist&lt;/p&gt;
&lt;h4&gt;Goals&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Treat everyone with kindness, consideration, and respect&lt;/li&gt;
&lt;li&gt;No one between code and production&lt;/li&gt;
&lt;li&gt;Clean Code - code expressed cleanly within the domain&lt;/li&gt;
&lt;li&gt;Zero Bugs!&lt;/li&gt;
&lt;li&gt;Deliver Working Software to Production Consistently&lt;/li&gt;
&lt;li&gt;Anyone can take a vacation (zero silos)&lt;/li&gt;
&lt;li&gt;Effective interdepartmental ownership&lt;/li&gt;
&lt;li&gt;Continuously develop lofty goals and practices&lt;/li&gt;
&lt;li&gt;Experiment Frequently with small changes&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Benefits&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;High Bandwidth Learning&lt;/li&gt;
&lt;li&gt;Quality and Technical Debt&lt;/li&gt;
&lt;li&gt;Group Conscientiousness&lt;/li&gt;
&lt;li&gt;Flow is easier in a mob vs pairing&lt;/li&gt;
&lt;li&gt;No more bugs!&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Law of Personal Mobility&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;If you are not contributing or learning, go to a different mob&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;There and Back Again: Our Rust Adoption Journey&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Async implies IO&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;amp;&lt;/code&gt; means the type that is passed into a method is immutable&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;async fn verify_signature(token: &amp;amp;Jwt)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;State Machines - enabled by &lt;code&gt;enum&lt;/code&gt; types &lt;strong&gt;having fields&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-rs&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;User&lt;/span&gt;&lt;/span&gt; {
  Pending {
    email: Email
  },
  Active {
    email: Email,
    confirmation_timestamp: DateTime&amp;lt;Utc&amp;gt;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Future looking - new states can be added, and compiler will tell you when a state isn&apos;t covered&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Predictable performance - rust is fast, but more importantly, its performance isn&apos;t affected by things such as garbage collectors&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Rust book is a great place to start&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rustlings&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>May 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/05/01/log" />
   <updated>2022-05-01T00:00:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/05/01/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;May 28th, 2022&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;It&apos;s always easier to expand scope than to constrain or reduce it&lt;/li&gt;
&lt;li&gt;Prescribed problem-solving processes that don&apos;t include a post-mortem or lessons learned don&apos;t create sustainable change (at least we weren&apos;t asking how we could prevent it in the future)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;May 22nd, 2022&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Should I split &quot;notes&quot; into two sections: &quot;thoughts&quot; and &quot;logs&quot;?&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;May 19th, 2022&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Update personal website to display log (a la twitter?)&lt;/li&gt;
&lt;li&gt;Most static analyzers should be shut off on unit tests, except for some basic formatting linters (whitespace)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Architecture Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://arc42.org&quot;&gt;http://arc42.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://doctoolchain.org&quot;&gt;http://doctoolchain.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;arc42 by Example&lt;ul&gt;
&lt;li&gt;Subset of arc42 that author always uses:&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Context&lt;/li&gt;
&lt;li&gt;Solution Strategy&lt;/li&gt;
&lt;li&gt;Building Block View&lt;/li&gt;
&lt;li&gt;Decisions&lt;/li&gt;
&lt;li&gt;Concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Architecture Diagrams&lt;ul&gt;
&lt;li&gt;System: entire system&lt;/li&gt;
&lt;li&gt;Subsystem: submodules of the system&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>Switch Notes</title>
   <link href="http://davidvedvick.info/notes/2022/05/28/switch-notes" />
   <updated>2022-05-28T00:00:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/05/28/switch-notes</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;p&gt;&lt;em&gt;Notes from the book &lt;a href=&quot;https://heathbrothers.com/books/switch/&quot;&gt;&lt;strong&gt;Switch: How to Change Things When Change is Hard&lt;/strong&gt;&lt;/a&gt; by the Heath Brothers&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Self-control is an exhaustible resource&lt;/li&gt;
&lt;li&gt;What looks like resistance is often lack of clarity&lt;/li&gt;
&lt;li&gt;Big problems are often solved with a sequence of small solutions&lt;/li&gt;
&lt;li&gt;Pursuing bright spots - &quot;what&apos;s working, and how can we do more of it?&quot;&lt;/li&gt;
&lt;li&gt;BHAG - Big Hairy Audacious Goal&lt;/li&gt;
&lt;li&gt;Big picture goals (be healthier!) make it easier to rationalize failure&lt;/li&gt;
&lt;li&gt;Change in people happens in this order: see-feel-change&lt;/li&gt;
&lt;li&gt;We define terms in ways that satisfy us&lt;/li&gt;
&lt;li&gt;If you want to inspire something to change, make it clear that progress has already been made&lt;/li&gt;
&lt;li&gt;Inspire people to be more determined, more motivated, more ready to act&lt;/li&gt;
&lt;li&gt;When people make decisions they rely on two models: the consequences model and the identity model&lt;/li&gt;
&lt;li&gt;Any change effort that violates someone&apos;s identity is likely doomed to failure &lt;/li&gt;
&lt;li&gt;Identities grow from small beginnings&lt;/li&gt;
&lt;li&gt;A growth (instead of fixed) mindset is key to achieving new things &lt;/li&gt;
&lt;li&gt;Project mood chart: U-shaped curve with a peak of &quot;hope&quot; at the beginning, second peak of &quot;confidence&quot; at the end, and a negative emotional valley of &quot;insight&quot; in the middle&lt;/li&gt;
&lt;li&gt;What looks like a person problem is often a situation problem&lt;/li&gt;
&lt;li&gt;People are more likely to change if you make it easier for them to change&lt;/li&gt;
&lt;li&gt;Sterile cockpit - give coders time during the week where they aren&apos;t interrupted&lt;/li&gt;
&lt;li&gt;Shape the environment to encourage change&lt;/li&gt;
&lt;li&gt;Habits are &quot;behavioral autopilot&quot;&lt;/li&gt;
&lt;li&gt;Habits change when the environment changes&lt;/li&gt;
&lt;li&gt;Pre-load decisions to overcome environmental habits (action triggers) &lt;/li&gt;
&lt;li&gt;Action triggers need to be specific and visible enough to interrupt normal stream of consciousness &lt;/li&gt;
&lt;li&gt;Behavior is contagious &lt;/li&gt;
&lt;li&gt;When the herd embraces the correct behavior, publicize it &lt;/li&gt;
&lt;li&gt;Free spaces allow reformers to come together while feeling safe from the conservatives&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>June 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/06/01/log" />
   <updated>2022-06-01T00:00:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/06/01/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;June 18th, 2022&lt;/h1&gt;
&lt;p&gt;A very unexpected lunch of parades and airplanes while getting a meal from one of my favorite places in St. Louis Park, MN!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/20220618-parade.jpg&quot; alt=&quot;Parade&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/20220618-st-louis-park-airplane.jpg&quot; alt=&quot;Airplane&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;June 16th, 2022&lt;/h1&gt;
&lt;p&gt;The only business model that can apply to software that receives continuous updates is a subscription or subscription-like model.&lt;/p&gt;
&lt;h1&gt;June 10th, 2022&lt;/h1&gt;
&lt;p&gt;Is all German flooring 0-based?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/german-elevator.jpg&quot; alt=&quot;German Elevator&quot; /&gt; &lt;/p&gt;
&lt;h1&gt;June 8th, 2022&lt;/h1&gt;
&lt;p&gt;Many websites use location based localization, so if you visit a site from another country, even if you frequently visited it from your home country, it will assume you&apos;re a speaker of the destination country&apos;s language. &lt;/p&gt;
&lt;h1&gt;June 4th, 2022&lt;/h1&gt;
&lt;p&gt;Writing should be a (simple?) joy in order to encourage its use (something Twitter gets right by limiting the number of allowed characters)&lt;/p&gt;
&lt;h1&gt;June 3rd, 2022&lt;/h1&gt;
&lt;h2&gt;project blue file details control buttons&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Clicking on a file from a list should show file details&lt;/li&gt;
&lt;li&gt;When viewing from &quot;Now Playing&quot;?&lt;ul&gt;
&lt;li&gt;Show &quot;pause&quot; when a file is playing&lt;/li&gt;
&lt;li&gt;Show &quot;play&quot; when a file is paused or not playing (and it is in now playing file details)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When viewing from elsewhere:&lt;ul&gt;
&lt;li&gt;Show &quot;pause&quot; when a file is playing&lt;/li&gt;
&lt;li&gt;Show &quot;play with playlist&quot; button when not playing?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Large societies have trouble with minority groups due to herd mentality writ large?&lt;/em&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Language Features and Inescapable Implementation Details</title>
   <link href="http://davidvedvick.info/notes/2022/06/20/async-await-implementation-details" />
   <updated>2022-06-20T15:25:29.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/06/20/async-await-implementation-details</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Language Features and Inescapable Implementation Details&lt;/h1&gt;
&lt;p&gt;My main gripe with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; in .Net, which makes the use of &lt;code&gt;Task&lt;/code&gt; objects to look &lt;a href=&quot;/notes/2019/03/21/conceptual-model-of-async-await&quot;&gt;more similar to procedural code&lt;/a&gt;, is the recommendation that when using &lt;code&gt;await&lt;/code&gt; in a library package, &lt;code&gt;Task.ConfigureAwait(false)&lt;/code&gt; should be used in order to ensure the task doesn&apos;t continue on the called context. This is &lt;a href=&quot;https://devblogs.microsoft.com/pfxteam/await-synchronizationcontext-and-console-apps/&quot;&gt;to prevent deadlocks&lt;/a&gt; on single-threaded synchronization contexts such as UI synchronization contexts.&lt;/p&gt;
&lt;p&gt;An alternative approach to &lt;code&gt;ConfigureAwait(...)&lt;/code&gt; could instead be syntax that improves the usability of synchronization context switching. Something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;// New keyword &quot;on&quot;, that then expects a synchronization context afterwards&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; result = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; longRunningProcess() &lt;span class=&quot;hljs-keyword&quot;&gt;on&lt;/span&gt; UISynchronizationContext;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This would have the benefit of giving the application developer improved control in the behavior of their app, while reducing the burden on library developers to make their async/await code &quot;safe&quot; for consumption.&lt;/p&gt;
&lt;p&gt;I think this is a more general problem for any programming language introducing a concept meant to paper over the &quot;hard stuff&quot;: invariably, the &quot;hard stuff&quot; creeps up, unless the sugary feature is very well thought out and future looking. And in the end, it seems the solution to the inescapable implementation details of syntactic sugar is introducing &lt;strong&gt;more&lt;/strong&gt; syntactic sugar. I think there&apos;s a lesson here: for a new language feature to have successful adoption, it needs to minimize harm and maximize helpfulness...&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>June 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/06/23/log" />
   <updated>2022-06-23T00:17:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/06/23/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;June 30th, 2022&lt;/h1&gt;
&lt;p&gt;If you think today&apos;s Wordle was hard, try using &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/transforms-overview?view=netframeworkdesktop-4.8&quot;&gt;WPF transforms&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;June 23rd, 2022&lt;/h1&gt;
&lt;p&gt;I have a sneaking suspicion that Intuit is actively trying to kill &lt;a href=&quot;https://mint.com&quot;&gt;Mint&lt;/a&gt; with the ever-increasing number of authentication steps.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>July 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/07/07/log" />
   <updated>2022-07-07T00:17:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/07/07/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;July 7th, 2022&lt;/h1&gt;
&lt;p&gt;Simple things Tesla could do with their overpowered CPUs and GPUs to improve the driving experience:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Range estimation based on weather, simply requires data (of which they have plenty) and regression models, using temperature, windspeed, and altitude changes as an input. To make it fancy, they could adjust it based on predicted temperature along a route, but while technically feasible, this might be a major pain. To make it even fancier, they could add component lifetime as an input. All of this is hard with traditional rule-based systems, but should be natural for machine learning. Supposedly, Tesla has a supercomputer creating advanced ML models that could easily create this kind of model.&lt;/li&gt;
&lt;li&gt;Simulate summer weather braking during winter weather&lt;/li&gt;
&lt;li&gt;Predicting component lifetime, detecting car problems ahead of time&lt;/li&gt;
&lt;/ol&gt;

  </content>
</entry>
<entry>
   <title>August 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/08/17/log" />
   <updated>2022-08-17T15:59:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/08/17/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;August 20th, 2022&lt;/h1&gt;
&lt;p&gt;MUT = module under test. Fun to write, read, and say, and generic enough to describe any level of test, while also specific enough to connotate this is local code under test. Also, a &quot;mutt&quot; is a canine breed of many different types, which I think fits well with &quot;module under test&quot; as well.&lt;/p&gt;
&lt;h1&gt;August 18th, 2022&lt;/h1&gt;
&lt;p&gt;A defect is ordering a Big Mac with Cheese and receiving a Big Mac without any cheese. A &lt;strong&gt;critique&lt;/strong&gt; is saying &quot;boy this sandwich could really be improved with some barbecue sauce.&quot; This may seem obvious, but the latter is not a defect, it&apos;s a &lt;strong&gt;new requirement&lt;/strong&gt;.&lt;/p&gt;
&lt;h1&gt;August 17th, 2022&lt;/h1&gt;
&lt;p&gt;Presentations follow a general format of 1) give presentation, and 2) question and answer. If the same presentation is presented multiple times to different audiences, then the Q&amp;amp;A tends to differ, out of which a &quot;Frequently Asked Questions&quot; list can be compiled. I wonder if there&apos;s a way to formalize this approach with existing presentation software (Powerpoint would be nice, but it would be easier to build something off of OS Markdown based presentation tools).&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>September 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/09/14/log" />
   <updated>2022-10-09T15:53:14.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/09/14/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;September 16th, 2022&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt; TODO: Register the project blue &lt;a href=&quot;https://github.com/namehillsoftware/projectBlue/blob/main/projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/browsing/files/details/FileDetailsActivity.kt&quot;&gt;File Details activity&lt;/a&gt; for mime-type &lt;code&gt;application/x-mediajukebox-mpl&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;September 14th, 2022&lt;/h1&gt;
&lt;p&gt;One day, the ultra wealthy, taking the baton from generations of the ultra wealthy who preceeded them, will  attach giant rockets to the earth&apos;s moon and fly away, living their lives in hermetically sealed environments and enjoying the Earth as they thought it should be in their VR metaverse. In true keeping with their predecessors, they will leave cleaning up the mess created by their action to the less fortunate left behind (losing the moon would destroy Earth&apos;s ecology in many ways). I have a hard time deciding whether I am making a joke or not 🤔.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>October 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/10/09/log" />
   <updated>2022-10-09T15:58:21.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/10/09/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;October 13th, 2022&lt;/h1&gt;
&lt;p&gt;Software is &lt;em&gt;too&lt;/em&gt; easy to change, which makes it easier to make breaking changes. This is another reason to add unit tests - to make code that is performing its function hard to change in the wrong ways. &lt;/p&gt;
&lt;h1&gt;October 9th, 2022&lt;/h1&gt;
&lt;h2&gt;project blue File Properties Editor&lt;/h2&gt;
&lt;p&gt;The file properties editor should popup a dialog when a certain property is touched, and the user should then have to initiate editing by clicking a button - it should be difficult to change such data through a User Interface.&lt;/p&gt;
&lt;h2&gt;Integration Tests&lt;/h2&gt;
&lt;p&gt;An issue with higher level integration tests is that the implementation of a method becomes intertwined with its usage.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>November 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/11/03/log" />
   <updated>2022-11-03T23:26:53.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/11/03/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;November 13th, 2022&lt;/h1&gt;
&lt;p&gt;The power of the Fediverse is that there can be a mastodon instance that has all verified, paid accounts, and there can be instances that are all anonymous accounts. The biggest risks I find with the Fediverse concept is that governments can more easily pressure, infiltrate, etc. small instances, not that this doesn&apos;t happen with Twitter as well.&lt;/p&gt;
&lt;p&gt;Anyways, my Fediverse account is on &lt;a href=&quot;https://fosstodon.org/web/@davidvedvick&quot;&gt;Fosstodon&lt;/a&gt; now.&lt;/p&gt;
&lt;h1&gt;November 3rd, 2022&lt;/h1&gt;
&lt;p&gt;Microsoft has a command line upgrade assistant to help with porting .Net framework to .Net core now - &lt;a href=&quot;https://dotnet.microsoft.com/en-us/platform/upgrade-assistant&quot;&gt;https://dotnet.microsoft.com/en-us/platform/upgrade-assistant&lt;/a&gt;. I wish this had been available when I ported 60+ .Net framework projects to .Net core 2.2!&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>December 2022 Log</title>
   <link href="http://davidvedvick.info/notes/2022/12/12/log" />
   <updated>2022-12-12T21:02:41.000Z</updated>
   <id>http://davidvedvick.info/notes/2022/12/12/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;December 29th, 2022&lt;/h1&gt;
&lt;p&gt;It took me a long time to realize the Rx libraries [0] are most useful for UI state and not useful for data access (and perhaps even harmful). For data access, traditional pulling/enumerating methods should be used, but for UI state, Rx observables are downright magical.&lt;/p&gt;
&lt;p&gt;[0] &quot;Rx Libraries&quot; refers to the libraries published on &lt;a href=&quot;https://reactivex.io/&quot;&gt;https://reactivex.io/&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;December 12th, 2022&lt;/h1&gt;
&lt;p&gt;One area where software testers can add value is in providing an external voice questioning software requirements. I think this value addition is best achieved when the tester is truly neutral to the product.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>January 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/01/05/log" />
   <updated>2023-01-06T22:23:38.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/01/05/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;January 31st, 2023&lt;/h1&gt;
&lt;h2&gt;Rebasing Large Patches&lt;/h2&gt;
&lt;p&gt;Rebasing steps after many merges from the base branch into the target branch:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new branch for the rebasing work.&lt;/li&gt;
&lt;li&gt;Do an initial rebase without modifying the branches history - the goal is to purely update the target branch to be based off the new base commit.&lt;/li&gt;
&lt;li&gt;Compare the tree of original branch and the new &quot;rebase&quot; branch, ideally, if the original branch was up-to-date with the target branch, then the &quot;rebase&quot; and &quot;original&quot; branch file trees are identical.&lt;/li&gt;
&lt;li&gt;Now that the rebase branch is based off the new base commit, do another rebase, making whatever changes you want to the branch.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Dark Mode&lt;/h2&gt;
&lt;p&gt;&quot;Dark mode&quot; should really be thought of as &quot;dark gray mode&quot;. Some of these UI designers go full black, and in my opinion, it&apos;s even harder on the eyes than white.&lt;/p&gt;
&lt;h1&gt;January 23rd, 2023&lt;/h1&gt;
&lt;p&gt;A fun read on the history of the metric system and the US: &lt;a href=&quot;https://www.theregister.com/2023/01/22/retro_metric_imperial/&quot;&gt;It&apos;s been 230 years since British pirates robbed the US of the metric system&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;January 6th, 2023&lt;/h1&gt;
&lt;p&gt;Code should read from the top down, and it should tell you as soon as possible when you can quit reading.&lt;/p&gt;
&lt;h1&gt;January 5th, 2023&lt;/h1&gt;
&lt;p&gt;Now that the value of posting on a &quot;status update&quot; site has lessened (Twitter), I&apos;m happy with splitting my posts between two different mediums:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Topical content? Mastodon.&lt;/li&gt;
&lt;li&gt;Other content? My notes.&lt;/li&gt;
&lt;/ol&gt;

  </content>
</entry>
<entry>
   <title>February 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/02/23/log" />
   <updated>2023-02-23T00:17:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/02/23/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;February 23rd, 2023&lt;/h1&gt;
&lt;h2&gt;Steps to Overlaying One Image over Another (And a Log of How I Solve a Problem)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Start off with a &lt;code&gt;div&lt;/code&gt; with two images in it. Both images are rendering, the &quot;overlay&quot; is under the base image as expected. Checkpoint.&lt;/li&gt;
&lt;li&gt;Set CSS style on &quot;overlay&quot; image to &lt;code&gt;position: absolute&lt;/code&gt;, &lt;code&gt;top: 0&lt;/code&gt;, &lt;code&gt;bottom: 0&lt;/code&gt;, observer &quot;overlay&quot; effect. Checkpoint.&lt;/li&gt;
&lt;li&gt;Now pursue fitting image inside of box that takes 50% of document width.&lt;ol&gt;
&lt;li&gt;First try setting containing div CSS style to &lt;code&gt;width: 50%&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Notice overlay image is still taking 100% of parent&apos;s parent, but the &quot;base&quot; image is properly positioned. This is half of what we want.&lt;/li&gt;
&lt;li&gt;Try using &lt;code&gt;position: relative&lt;/code&gt; on overlay image. Doesn&apos;t work.&lt;/li&gt;
&lt;li&gt;Research: &quot;position absolute image does not use parent element box sizing&quot;.&lt;ol&gt;
&lt;li&gt;Click first link, most suggestions just suggest using pixel-wise adjustments, which we can&apos;t use.&lt;/li&gt;
&lt;li&gt;Notice some answers are suggesting parent container should use &quot;relative&quot; positioning. What is that about? Probably nothing, let&apos;s look into some other options.&lt;/li&gt;
&lt;li&gt;So far research seems to not be giving many great options...&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Try adding CSS style &lt;code&gt;display: inline-block&lt;/code&gt; to overlay image. This does nothing.&lt;/li&gt;
&lt;li&gt;I noticed some of the other places where this worked, the parent container was a &quot;flex&quot; container. We can do this by setting the parent container&apos;s &quot;display&quot; property in its CSS to &quot;flex&quot; - so add this to the parent &lt;code&gt;div&lt;/code&gt; CSS style: &lt;code&gt;display: flex&lt;/code&gt;.&lt;ul&gt;
&lt;li&gt;This has no noticeable effect.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ok, playing around has so far not given me any good results. Let&apos;s return to the research I had open. The fourth result was from a blog post on &quot;solodev.com&quot;. It too mentions setting the parent &lt;code&gt;div&lt;/code&gt; positioning to &lt;code&gt;relative&lt;/code&gt;. Maybe there&apos;s something to this? It&apos;s a quick thing to try, so let&apos;s try it.... success! Just what we wanted.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

  </content>
</entry>
<entry>
   <title>March 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/03/12/log" />
   <updated>2023-03-13T04:35:39.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/03/12/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;March 12th, 2023&lt;/h1&gt;
&lt;h2&gt;Fixing an Annoying Connection Issue&lt;/h2&gt;
&lt;p&gt;Currently really trying to nail down initializing a connection to a media server with project blue, so that it is portable and hopefully transitions easily to Jetpack Compose and navigation. I wonder what the best way is to initialize connection state? Here&apos;s my requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If initializing the connection fails, need to send user to settings.&lt;/li&gt;
&lt;li&gt;If no media server connection is selected, send user to the settings.&lt;/li&gt;
&lt;li&gt;If initializing succeeds, continue normal execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This piece of code has also caused me numerous, hard to track issues for years, so if I could make as much of it as testable as possible, then this would be a win. My current idea is to do this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have an interface &lt;code&gt;ControlConnectionInitialization&lt;/code&gt; that defines a single function, &lt;code&gt;promiseInitializedConnection(libraryId: LibraryId): ProgressingPromise&amp;lt;BuildingConnectionStatus, IConnectionProvider?&amp;gt;&lt;/code&gt;, through delegation, I can build up different behaviors as needed.&lt;/li&gt;
&lt;li&gt;Have a simple implementation of this interface that just proxies the connection:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-kt&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ConnectionInitializationProxy&lt;/span&gt;&lt;/span&gt;(
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; manageConnectionSessions: ManageConnectionSessions,
) : ControlConnectionInitialization {
    &lt;span class=&quot;hljs-keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;promiseInitializedConnection&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(libraryId: &lt;span class=&quot;hljs-type&quot;&gt;LibraryId&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;: ProgressingPromise&amp;lt;BuildingConnectionStatus, IConnectionProvider?&amp;gt; =
        ProgressingPromiseProxy(manageConnectionSessions.promiseLibraryConnection(libraryId))
}
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Have another implementation of &lt;code&gt;ControlConnectionInitialization&lt;/code&gt; that handles error state and routes the user to the settings in failure. This will be passed an inner &lt;code&gt;ControlConnectionInitialization&lt;/code&gt;, which we will assume is handling the basic connection (and maybe success case).&lt;/li&gt;
&lt;li&gt;At the top level, have another implementation of &lt;code&gt;ControlConnectionInitialization&lt;/code&gt; which handles the normal execution states, and delegates error-handling to the error-handling implementation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I finished this work in &lt;a href=&quot;https://github.com/namehillsoftware/projectBlue/pull/370&quot;&gt;this pull request&lt;/a&gt;.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>April 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/04/13/log" />
   <updated>2023-04-13T12:51:54.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/04/13/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;April 13th, 2023&lt;/h1&gt;
&lt;p&gt;Good source code requires other developers know as few assumptions as possible.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Drag and Drop Difficulties</title>
   <link href="http://davidvedvick.info/notes/2023/04/27/drag-drop-difficulties" />
   <updated>2023-04-27T11:56:13.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/04/27/drag-drop-difficulties</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Drag And Drop Difficulties&lt;/h1&gt;
&lt;p&gt;It is surprisingly difficult to get drag and drop working in jetpack compose. I have had it working in most parts of the list for most of the week, but the first element causes the &lt;code&gt;LazyList&lt;/code&gt; to readjust its bounds, causing absolute chaos. A fix I discovered in &lt;a href=&quot;https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/LazyColumnDragAndDropDemo.kt;l=187&quot;&gt;Google&apos;s examples&lt;/a&gt; partially helps, but still leaves the dragged element in limbo:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/Screenshot_20230427-062206.png&quot; alt=&quot;Screenshot_20230427-062206&quot; /&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>OSN 2023 Notes</title>
   <link href="http://davidvedvick.info/notes/2023/05/24/osn-2023-notes" />
   <updated>2023-05-24T00:17:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/05/24/osn-2023-notes</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Open Source 2023 Notes&lt;/h1&gt;
&lt;h2&gt;Inside ChatGPT&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Lab651 and Recursive Awesome, Captovation - AI Solutions Development&lt;/li&gt;
&lt;li&gt;Applied AI - 501c3 organization&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;GPT Releases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Version 1 - 117M parameters&lt;/li&gt;
&lt;li&gt;Version 2 - 1.5B parameters&lt;/li&gt;
&lt;li&gt;Version 3 - 175B parameters&lt;/li&gt;
&lt;li&gt;Version 4 - 1T+ parameters&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Wolfram One&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Cloud/desktop hybrid, integrated computation platform&lt;/li&gt;
&lt;li&gt;Similar to Jupyter notebooks&lt;/li&gt;
&lt;li&gt;Lets you play around with GPT models (older than v3 and v4)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;GPT 2&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Always using the next highest probability word isn&apos;t always the best... using a &quot;temperature&quot; parameter, the model can be tweaked to sometimes choose words that aren&apos;t quite the highest probablity, leading to fewer run-on sentences.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attention - when the model picks up on a higher probability and begins to focus in on it&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Embeddings - training model on relationships between words (word pairs in a sense)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example: Munich - Berlin + France =&amp;gt; Paris&lt;/li&gt;
&lt;li&gt;This can also be done for sequences of words and whole blocks of text&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ChatGPT has learned syntactic grammar using embedding techniques&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When determing a sequence of words, it essentially follows a random walk through the syntactic grammar&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wolfram can break down the structure&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenAI playground: &lt;a href=&quot;https://platform.openai.com/playground&quot;&gt;https://platform.openai.com/playground&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&quot;How would you create a neural network model that would rule the world? Please write it out in small, specific steps.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Stable Diffusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Speaking plainly&quot; to computers -isn&apos;t this programming?&lt;/li&gt;
&lt;li&gt;Hannah Loegering - @fractalorange&lt;/li&gt;
&lt;li&gt;Open Source AI:&lt;ul&gt;
&lt;li&gt;Deforum (Video, Image)&lt;/li&gt;
&lt;li&gt;Automatic1111/stale-diffusion-webai&lt;/li&gt;
&lt;li&gt;Langchain&lt;/li&gt;
&lt;li&gt;Simulacra and Simulation&lt;/li&gt;
&lt;li&gt;GPT4All Chat (text)&lt;/li&gt;
&lt;li&gt;Flowise/langchainJA-ui&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;@secondsightvisuals&lt;/li&gt;
&lt;li&gt;Music is a 4-dimensional dataspace&lt;/li&gt;
&lt;li&gt;Replicate - lucid sonic dreams, takes a source and produces an infinite sequence&lt;/li&gt;
&lt;li&gt;phygital+ - create 3d-printed models&lt;/li&gt;
&lt;li&gt;Can download stale diffusion and run locally&lt;/li&gt;
&lt;li&gt;Midjourney runs over discord?&lt;/li&gt;
&lt;li&gt;Luma AI - create 3D scenes and scan from 2D video&lt;/li&gt;
&lt;li&gt;Kaiber - super easy AI animation&lt;/li&gt;
&lt;li&gt;Wonder Dynamics - 3D character repalcement in 2D video&lt;/li&gt;
&lt;li&gt;Deep Motion - 3D character rigging from 2D video&lt;/li&gt;
&lt;li&gt;Runway ML - Full suite of video tools including their Gen1 and Gen2&lt;/li&gt;
&lt;li&gt;Blockade Labs: text to 360 image&lt;/li&gt;
&lt;li&gt;Simulacra - build 3D assets&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Role of Generative AI in Healthcare&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CTO of Virtuwell (Telehealth)&lt;/li&gt;
&lt;li&gt;Virtuwell is not-for-profit?!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Care Delivery&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Diagnosis prediction&lt;/li&gt;
&lt;li&gt;Support clinicians by providing relevant medical info&lt;/li&gt;
&lt;li&gt;Personalized health and wellness advice to individuals&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Medicine&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Personalized medicine: Forecast outcomes via patterns&lt;/li&gt;
&lt;li&gt;Drug Discovery: identify possible new meds and predict compounds likely to be effective&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Health Plan&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Organize unstructured medical data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Virtuwell AI initiatives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Reduce over/under staffing by predicting the future&lt;/li&gt;
&lt;li&gt;Predict surge traffic to website&lt;/li&gt;
&lt;li&gt;Analyze patient data for systematic follow ups&lt;/li&gt;
&lt;li&gt;Funneling relevant medical records&lt;/li&gt;
&lt;li&gt;At-home kit for colon cancer screening and STI&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Healthcare Companies in AI&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Optellum: rules out harmless cases of lng canver via scans.&lt;/li&gt;
&lt;li&gt;Ultromics: increases diagnostic accuracy of coronary heart disease from 80% to 94%&lt;/li&gt;
&lt;li&gt;IDx-DR (now Digital Diagnostics): correctly identifies diabetic retinopathy by 87.4% (8% better than industry standard)&lt;/li&gt;
&lt;li&gt;Beyond Verbal: Detecting Coronary Artery Disease by listening to voice&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Future of Generative AI&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;If you are a large enterprise, you need to train your own LLM&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Under-Engineering&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Information / Technology impedance&lt;ul&gt;
&lt;li&gt;Programmers making wrong asusmptions based on limited informaiton&lt;/li&gt;
&lt;li&gt;Tribal knowledge lost over time and developer turnover&lt;/li&gt;
&lt;li&gt;Lack of documentation&lt;ul&gt;
&lt;li&gt;Code not self-documenting&lt;/li&gt;
&lt;li&gt;Unreadable unit tests&lt;/li&gt;
&lt;li&gt;Distance between code and documentation (documentation is on a remote server away from source)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Self-inflicted complexity&lt;ul&gt;
&lt;li&gt;Ineffective bootstrapping: programmers bringing in their own toolsets instead of assessing what tools are best for their projets&lt;/li&gt;
&lt;li&gt;Programmers building their own frameworks&lt;ul&gt;
&lt;li&gt;Overfitting&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Bug-fixes / rework&lt;ul&gt;
&lt;li&gt;Bandaging code quickly instead of reworking code complexity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Under-engineering: act of explicitly engineering in a simplistic manner&lt;/li&gt;
&lt;li&gt;Architecture should be as simple as possible&lt;/li&gt;
&lt;li&gt;Developer documentation should be simple and accessible (developers should have their own set of documentation)&lt;/li&gt;
&lt;li&gt;Coding should be simple, readable, and maintainable&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Reduce Complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Find the most confusing concepts o fthe codebase&lt;/li&gt;
&lt;li&gt;Document Confusion&lt;/li&gt;
&lt;li&gt;Unit tests should be your guide on refactors&lt;ul&gt;
&lt;li&gt;Unit tests should be user friendly&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Reverse code entropy - deleting code??&lt;/li&gt;
&lt;li&gt;Identify:&lt;ul&gt;
&lt;li&gt;Challenging developer cadences&lt;/li&gt;
&lt;li&gt;confusing folder structures&lt;/li&gt;
&lt;li&gt;Hard-to-read / hard-to-write code&lt;/li&gt;
&lt;li&gt;Bad model or variable names&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Put documentation next to code&lt;/li&gt;
&lt;li&gt;Design for NOW, but with the future in mind&lt;/li&gt;
&lt;li&gt;Ask what-if, but don&apos;t design for what-if in order to ensure you don&apos;t box yourself out&lt;/li&gt;
&lt;li&gt;Push back on product feature work&lt;/li&gt;
&lt;li&gt;Use 90% rule for generic/inheritance patterns&lt;/li&gt;
&lt;li&gt;Provide code samples&lt;/li&gt;
&lt;li&gt;Write comments first? (why not write unit tests first? :P)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;IOT Eventing&lt;/h2&gt;
&lt;h3&gt;General Workflow&lt;/h3&gt;
&lt;p&gt;Devices -&amp;gt; Event Ingestion -&amp;gt; Event Matching -&amp;gt; Event Delivery -&amp;gt; Event Actions -&amp;gt; Back to Device(s)&lt;/p&gt;
&lt;h3&gt;Design Constraint: Event Volume&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Devices/Locations = 100&lt;/li&gt;
&lt;li&gt;Max Events per Device: 10 events/s&lt;/li&gt;
&lt;li&gt;SLO: &amp;lt; 1s response time from client controllers to devices&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Evolution of Eventing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;2011 - Monolithic, event-based architecture built around RabbitMQ&lt;/li&gt;
&lt;li&gt;2013 - Monolith + sharding&lt;/li&gt;
&lt;li&gt;2015 - Microservices: strong REST principles instead of Event Oriented Architecture, using Kafka instead of RabbitMQ&lt;/li&gt;
&lt;li&gt;2015-2019 - Event pipeline: Kafka, Amazon EC2, SQS, oh my...&lt;/li&gt;
&lt;li&gt;2019-current: one suscription system instead of a subscription per device type&lt;ul&gt;
&lt;li&gt;Move to a stateful subscription model&lt;/li&gt;
&lt;li&gt;One users events will always go through the same box&lt;/li&gt;
&lt;li&gt;Makes latency stable&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Breaking down and logically dividing up work wihtin a system is critical&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>May 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/05/28/log" />
   <updated>2023-05-28T00:17:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/05/28/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;May 28th, 2023&lt;/h1&gt;
&lt;p&gt;Most dependencies are just data. Data &quot;repositories&quot; are easier to fake than mock. Maybe mocks should just be used for hardware I/O?&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>June 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/06/09/log" />
   <updated>2023-06-09T12:42:24.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/06/09/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;June 9th, 2023&lt;/h1&gt;
&lt;p&gt;The pareto rule strikes again - employees are at their best when they&apos;re working at 85% capacity, not 100% - &lt;a href=&quot;https://hbr.org/2023/06/to-build-a-top-performing-team-ask-for-85-effort&quot;&gt;https://hbr.org/2023/06/to-build-a-top-performing-team-ask-for-85-effort&lt;/a&gt;. &lt;/p&gt;

  </content>
</entry>
<entry>
   <title>July 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/07/30/log" />
   <updated>2023-07-31T02:08:58.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/07/30/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;July 30th, 2023&lt;/h1&gt;
&lt;h2&gt;Programming Proficiency&lt;/h2&gt;
&lt;p&gt;To solve programming problems reliably one needs two skills:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Proficiency in &lt;strong&gt;set theory&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Specifying&lt;/strong&gt; the correct behavior of code in tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Organization&lt;/strong&gt; (naming things, type hierarchies, module placement) is also extremely useful for ensuring code maintainability, but it is a tangential skill to the first two skills.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Automated Project Publishing</title>
   <link href="http://davidvedvick.info/notes/2023/09/23/project-publishing" />
   <updated>2023-09-23T00:17:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/09/23/project-publishing</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Automated Project Publishing&lt;/h1&gt;
&lt;p&gt;The idea: a small script that periodically runs, checking for changes to project readme&apos;s, and publishes updates to davidvedvick.info.&lt;/p&gt;
&lt;p&gt;This script would need to reside in a-personal-site. Would need to be configurable so that it could accurately be run on a local machine but also on a build server.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update 11/28/2023: I instead implemented this as &lt;a href=&quot;https://www.gocd.org/&quot;&gt;GoCD&lt;/a&gt; pipeline that I run on-demand, and it is &lt;em&gt;&lt;strong&gt;glorious&lt;/strong&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>August 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/08/14/austin-sff-2023-notes" />
   <updated>2023-09-23T23:19:43.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/08/14/austin-sff-2023-notes</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Solid Freeform 2023 Notes&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;From August 14-16, 2023 I attended an academic conference on 3D printing research, below are my notes.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Technion Additive Manufacturing Center&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Current geometric design pardigm ha sbeen with us for over a decade&lt;/li&gt;
&lt;li&gt;V-rep operations:&lt;ul&gt;
&lt;li&gt;Filleting and rouding&lt;/li&gt;
&lt;li&gt;Mixed symbolic/numeric computations over multivariate (and V-rep) splines&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://csaws.cs.technion.ac.il/~gershon/irit&quot;&gt;https://csaws.cs.technion.ac.il/~gershon/irit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In-Situ Process Monitoring in AM&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Michael J. Heiden&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Purpose, Motivation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Failure mode analysis (ie spike in oxygen)&lt;/li&gt;
&lt;li&gt;Reduce coupon inspection&lt;/li&gt;
&lt;li&gt;Runs in parallel with the build process&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Detection Methods and Processes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Optical IR&lt;/li&gt;
&lt;li&gt;Use the Peregrine machine learning model from Oakridge&lt;/li&gt;
&lt;li&gt;Use multi-modal data (thermal imaging/thermography, high speed cameras, spectroscopy, acoustic monitoring)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Using the Data to Create Useful 3D Digital Twins&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Show discrepancies between what is supposed to be printed and the actual&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Future Targets&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Real time monitoring&lt;/li&gt;
&lt;li&gt;Closed lop control for defect correction (this is what we do!)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Machine Learning Applied to Process Monitoring for Laser Hot Wire Directed Energy Deposition&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Carnegie Mellon University&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Comparison with Laser Powder Bed Fusion&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Under acceptable conditions, melt pools are not stable&lt;/li&gt;
&lt;li&gt;Monitoring of rare unwanted events such as spatter requires significant ML traning (1k-10k hand-labeled images)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Laser Hot Wire Additive Manufacturing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Well behaved melt pools under normal conditions&lt;/li&gt;
&lt;li&gt;Can monitor entire buildds in real time&lt;/li&gt;
&lt;li&gt;Approach: detect unsteady behavior of the melt pool, don&apos;t attempt to learn the appearnce of irregular events&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Methodology&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Many flaws exist across multiple frames, so a time dependent analysis is beneficial&lt;/li&gt;
&lt;li&gt;Long Short-Term Memory networks are able to learn time dependencies in video data&lt;/li&gt;
&lt;li&gt;Use previous frames to predict future frames (about 10-20 frames of past history)&lt;/li&gt;
&lt;li&gt;Capture a regularity scorePredicition: within 5-10 years we will see fully sensed and automated DED systems&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Known Flaw Types&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Stable Deposition&lt;/li&gt;
&lt;li&gt;Melt pool oscillation&lt;/li&gt;
&lt;li&gt;Arcing&lt;/li&gt;
&lt;li&gt;Wire stubbing&lt;/li&gt;
&lt;li&gt;Wire dripping&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Summary and Conclusions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ML model detects unsteady behavior, which is indicative of process instability (unlike LBPF)&lt;/li&gt;
&lt;li&gt;Prediction is that DED systems will be deployed with fully automatic quality control in next 5-10 years&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Area Printing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Area printing is stamping on the powderbed&lt;/li&gt;
&lt;li&gt;Seurat is the company that developed this technology&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Rethinking Additive Manufacturing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;DfAM transcends disciplinary boundaries&lt;/li&gt;
&lt;li&gt;Traditional manufacturing informs our design sensibilities&lt;/li&gt;
&lt;li&gt;Evaluate design using consensual design techniques&lt;/li&gt;
&lt;li&gt;DfAM increases as experience increases&lt;/li&gt;
&lt;li&gt;Restrictive DfAM: &quot;Can we print it&quot;&lt;/li&gt;
&lt;li&gt;Opportunistic DfAM: &quot;Should we print it&quot;&lt;/li&gt;
&lt;li&gt;Unlearning requires designers to identify good DfAM solutions&lt;/li&gt;
&lt;li&gt;VR can help with DfAM&lt;/li&gt;
&lt;li&gt;Use VR for simulating a printer in test?&lt;ul&gt;
&lt;li&gt;Probably not super beneficial for our needs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Co-deisgn of 3D Printing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You cannot monitor your way out of trouble: need all the insights possible from &lt;strong&gt;in-situ&lt;/strong&gt; and &lt;strong&gt;operando&lt;/strong&gt; monitoring.&lt;/li&gt;
&lt;li&gt;In aircraft manufacturing: &quot;Anything that allows you to gain efficiency is worth the manufacturing cost&quot;&lt;/li&gt;
&lt;li&gt;Diffusion Modeling is not sufficient for AM Heat Exchangers&lt;ul&gt;
&lt;li&gt;Use heat exchangers used with solar energy?&lt;/li&gt;
&lt;li&gt;Alternate technology: diffusion bonding&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Improved heat exchangers reduces defects?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Physical Validation of Job Placement Optimization in Cooperative 3D Printing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Traditional vs Cooperative 3D printing&lt;ul&gt;
&lt;li&gt;Traditional: gantry systems&lt;/li&gt;
&lt;li&gt;Limited in scalability and flexibility&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Partitioning Strategy: Chunking&lt;ul&gt;
&lt;li&gt;First chunk into layers (Z-Chunking)&lt;/li&gt;
&lt;li&gt;XY-Chunking: chunk adjacent chunks at an angle to facilitate bonding of chunks&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use grid search algorithm (A* Path Planning) to plan robot movement&lt;ul&gt;
&lt;li&gt;If there are two robots that are going to take a path at the same time, apply a conflict avoidance algorithm&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AMBOTS C3DP&lt;/li&gt;
&lt;li&gt;When a robot moves to  a new location, it requires manual calibration&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Time Optimal Path Planning for Heterogenous Robots in Swarm Manufacturing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Continuous spatial profile with arbitrary robot gemoetry that includes orienatation&lt;/li&gt;
&lt;li&gt;Dynamic environment with arbitrary number of obstacles&lt;/li&gt;
&lt;li&gt;Time-optimal solution for multiple agents&lt;/li&gt;
&lt;li&gt;Projecting Dynamic Obstacles&lt;ul&gt;
&lt;li&gt;Use &quot;safe intervals&quot; to reduce number of computations&lt;/li&gt;
&lt;li&gt;Based on safe intervals, split the configurations based on what has more than one safe interval&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Limitations:&lt;ul&gt;
&lt;li&gt;Does not make real-time adjustments&lt;/li&gt;
&lt;li&gt;Truly centralized optimal planning scales exponentially with the number of agents&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Open questions:&lt;ul&gt;
&lt;li&gt;How does shape discretizaiton impact solution quality?&lt;/li&gt;
&lt;li&gt;What is the upper number of agents before it is too computationally expensive?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Layer Wise Prediction of Microstructural Evolution&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Predict grain size and melt-pool depth using thermal model features&lt;/li&gt;
&lt;li&gt;As structure grows, cooling rate decreases&lt;/li&gt;
&lt;li&gt;Prediction using physics-guided machine learning (SVM models)&lt;ul&gt;
&lt;li&gt;Predict Meltpool Depth&lt;ul&gt;
&lt;li&gt;Not inuitively explained by process parameters&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Thermal Feature Correlate to Grain Size&lt;ul&gt;
&lt;li&gt;Grain size predicted with 90% F-Score&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cooling rate also decreases with heat build-up&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Post Superficial Temperature Monitoring During Additive Manufacturing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CNN goal is to produce predicted temperature of build&lt;/li&gt;
&lt;li&gt;Best results come from combining a machine learning model, in situ monitoring, and sensors&lt;/li&gt;
&lt;li&gt;Normal Data + Wall Simulation as inputs gives best ML performance on experimental data&lt;/li&gt;
&lt;li&gt;In Situ Sensors + ML models as a &quot;Digital Twin&quot; of how the part will be produced&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Optimal Control of Wire DED Systems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Modeling of a dynamic system usually using ODE&lt;/li&gt;
&lt;li&gt;Optimal Control Theory - &lt;a href=&quot;https://en.wikipedia.org/wiki/Optimal_control&quot;&gt;https://en.wikipedia.org/wiki/Optimal_control&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Framework for Physics Guided Machine Learning&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Process variations are high in AM&lt;/li&gt;
&lt;li&gt;PSP: Process-structure-property&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;PSP Linkages for In-situ Data&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Predictive Melt-pool Modeling&lt;ul&gt;
&lt;li&gt;Multi-layer model produced best results&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Predictive Pore-structure Model&lt;/li&gt;
&lt;li&gt;Predictive Surface-height Model&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;AI Driven In-Situ Monitoring&lt;/h2&gt;
&lt;h3&gt;Intrinsic Keyhole Oscillation&lt;/h3&gt;
&lt;p&gt;Keyhole: a puncture in the powderbed that leads to an unexpected cavity (&quot;keyhole pore&quot;) in the powderbed&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Combine X-Ray imaging and Thermal Imaging&lt;/li&gt;
&lt;li&gt;Intrinsic Keyhole Oscillation&lt;ul&gt;
&lt;li&gt;Surface tension and coil pressure&lt;/li&gt;
&lt;li&gt;Liquid flow on the outside of the meltpool increases keyhole size&lt;/li&gt;
&lt;li&gt;Lower than 30KHz&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Perturbative Keyhole Oscillation&lt;ul&gt;
&lt;li&gt;Greater than 40KHz&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Gradient-weighted Class Activation Mapping (Grad CAM)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Predict where keyholes will form using an ML model, avoiding further X-Ray synchotron experiments&lt;/li&gt;
&lt;li&gt;An input to the trained model is a simulation of the build&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;PRISM: Process Parameter Optimization for Selective Manufacturing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Goldilocks zone:&lt;ul&gt;
&lt;li&gt;Not enough: lack of fusion&lt;/li&gt;
&lt;li&gt;Too much: keyhole formulation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use machine learning to determine proper process parameters!&lt;/li&gt;
&lt;li&gt;Goal is to achieve high density, assume density is a surrogate for:&lt;ul&gt;
&lt;li&gt;CTE (Coefficient of thermal expansion)&lt;/li&gt;
&lt;li&gt;Elastic modulus&lt;/li&gt;
&lt;li&gt;Strength&lt;/li&gt;
&lt;li&gt;Toughness&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Data will be published and open source&lt;/li&gt;
&lt;li&gt;ML Driven Design of Experiment&lt;ul&gt;
&lt;li&gt;Latin hyper cube sample generation&lt;/li&gt;
&lt;li&gt;Predict Printability using tree algorithm (bounds determined by expert)&lt;/li&gt;
&lt;li&gt;Predict density using tree algorithms (XGBoost)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Select candidates: diversity (determined by L2 distance), quality, and random sleection&lt;/li&gt;
&lt;li&gt;Used FLAML to automate experimentation&lt;/li&gt;
&lt;li&gt;Would probably need to re-train per material type&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;FAIR Knowledge Management System for Additive Manufacturing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AMMD.nist.gov, AMBench2022.nist.gov&lt;/li&gt;
&lt;li&gt;ASTM F42 - working group developing data models to represent AM&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Unconventional Data Sources for Market Intelligence&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Aachen Center for AM&lt;/li&gt;
&lt;li&gt;Market intelligence uses external data over internal data (patent databases, social media, etc.)&lt;/li&gt;
&lt;li&gt;Databases used for research: Amadeus, LinkedIn, Scopus&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Digital Twins&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Part qualification is manual and slow&lt;/li&gt;
&lt;li&gt;Can digital twins help understand the process to manufacturing property map?&lt;/li&gt;
&lt;li&gt;Direct Ink Write&lt;/li&gt;
&lt;li&gt;Using robotic automation to generate large amounts of parts and data&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Executable for Avant Garde Laser Exposure (EAGLE)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Common command interfaces&lt;/li&gt;
&lt;li&gt;Ability to support any input file&lt;/li&gt;
&lt;li&gt;Plugin support&lt;/li&gt;
&lt;li&gt;Process Buckets&lt;/li&gt;
&lt;li&gt;Limited interference with machine&lt;/li&gt;
&lt;li&gt;Common Build Data Storage&lt;ul&gt;
&lt;li&gt;SQL Database on machine or network&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Print Process Flow:&lt;ul&gt;
&lt;li&gt;Pre-Process&lt;/li&gt;
&lt;li&gt;Layer Process:&lt;ul&gt;
&lt;li&gt;Verify -&amp;gt; Scan -&amp;gt; Characterize -&amp;gt; Recoat&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Post-Process&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;EAGLE is written in Rust and Javascript using Tauri&lt;ul&gt;
&lt;li&gt;Designed to support print files &amp;gt; 100GB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Direction not intention determines destination&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;In-Situ Monitoring Using Neutron Rays&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Neutrons have high penetration in metals&lt;/li&gt;
&lt;li&gt;Different contrast from X-Rays&lt;/li&gt;
&lt;li&gt;Phase evolution&lt;/li&gt;
&lt;li&gt;In-Situ Laser Metal Deposition&lt;ul&gt;
&lt;li&gt;Completmentary to lab and synchotron experiments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;In-Beamline Strain Measurement&lt;/li&gt;
&lt;li&gt;Neutrons are non-destructive, tri-axial, and sub-surface&lt;/li&gt;
&lt;li&gt;Additive has a much wider distribution of gamma prime and gamma double prime sizes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;X-Ray Compute Tomagrphy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Determine powder size because that&apos;s always going to be stuck on the surface&lt;/li&gt;
&lt;li&gt;Could minimum powder size (and laser amplitude?) define minimum defects size?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;SATURN&lt;/h2&gt;
&lt;h3&gt;SCT and MPM Data&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Lack of fusion and keyhole are two major issues (laser power)&lt;/li&gt;
&lt;li&gt;Rnadom forest prediction works with decent acccuracy&lt;/li&gt;
&lt;li&gt;U-net model?&lt;/li&gt;
&lt;li&gt;Some defects will heal automatically, and don&apos;t need to be treated&lt;/li&gt;
&lt;li&gt;Non-balanced gain control introduces saturation in the photodiodes&lt;/li&gt;
&lt;li&gt;OEM gives a graphical representation of the data, not a tabular or formatted version&lt;/li&gt;
&lt;li&gt;Photodiodes operate at &amp;gt;11MHz&lt;/li&gt;
&lt;li&gt;Sensor captures images at 400um resolution&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Intelligent Process Control&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Using FPGA to provide faster response times&lt;/li&gt;
&lt;li&gt;Goal is to catch a defect within the transient state (10-20us), they&apos;ve (potentially) achieved nanosecond response times&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;High precision measurement of Melt Pools&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;FPS of 40,000&lt;/li&gt;
&lt;li&gt;Resolution: 896 x 176 pixels&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;End-to-End AI Models for Error Detection&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Current issue - solutions are not general&lt;/li&gt;
&lt;li&gt;Matta (Cambridge company), Grey-1 AI Copilot for AM&lt;/li&gt;
&lt;li&gt;Multi-head residual attention convolutional neural network:&lt;ul&gt;
&lt;li&gt;Develops its own masks to determine where to pay attention&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>November 1st, 2023 Log</title>
   <link href="http://davidvedvick.info/notes/2023/11/01/log" />
   <updated>2023-11-08T19:17:49.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/11/01/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;November 29th, 2023&lt;/h1&gt;
&lt;p&gt;A core component of learning is separating signal from noise on a given subject. The corollary is that a core component of teaching a subject is informing the student which parts are noise; the signal falls out from this.&lt;/p&gt;
&lt;h1&gt;November 1st, 2023&lt;/h1&gt;
&lt;p&gt;Having dealt with C# DLL hell for years, and then going through the equally hellish dotnet &lt;code&gt;HttpClient&lt;/code&gt; fiascos, and now struggling with adopting ES modules in a Typescript library, I am beginning to believe that Microsoft has a department focused on making module resolution a living hell for anyone who uses their tools.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>The Interaction State Primitive</title>
   <link href="http://davidvedvick.info/notes/2023/12/14/interaction-state-primitive" />
   <updated>2024-01-27T17:47:48.000Z</updated>
   <id>http://davidvedvick.info/notes/2023/12/14/interaction-state-primitive</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;The Interaction State Primitive&lt;/h1&gt;
&lt;p&gt;I&apos;ve been developing UI&apos;s in some form or another for about 25 years. It&apos;s taken nearly that long to realize the basic primitive of dynamic UI&apos;s: what I call the &quot;Interaction State&quot; primitive. The Interaction State primitive has these rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The current state of the property can be accessed via a normal get accessor. In Java, this might be a method with a signature like &lt;code&gt;T getValue()&lt;/code&gt;. Sometimes this is called a &lt;strong&gt;snapshot&lt;/strong&gt;, but I prefer the more direct terminology of &lt;strong&gt;state&lt;/strong&gt;. In a language with more syntactical magic available, it can be done via something like a get accessor.&lt;/li&gt;
&lt;li&gt;Its value can be updated via a normal set accessor. In Java, this might look like &lt;code&gt;setValue(T value)&lt;/code&gt;. Again, in other languages, syntax magic can make the write access more terse.&lt;/li&gt;
&lt;li&gt;Updates to the property&apos;s state are &lt;strong&gt;observable&lt;/strong&gt;. Below, I will cheat and use the &lt;a href=&quot;http://reactivex.io/&quot;&gt;ReactiveX flavors&lt;/a&gt; to achieve this.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setValue(T value)&lt;/code&gt; only notifies observers the value is updated when the new value is not equal to the existing value. This should follow normal equality rules of the language.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I am not the first to make this observation; KnockoutJS, which I used c.a. 2014, had observables in Javascript, and Rx.Net and other &lt;a href=&quot;http://reactivex.io/&quot;&gt;ReactiveX flavors&lt;/a&gt; have been around for quite some time, with the &lt;code&gt;BehaviorSubject&amp;lt;T&amp;gt;&lt;/code&gt;, which has the above semantics, but with slightly contorted syntax. However, in my opinion, all of these languages and libraries don&apos;t make it plain that these are the rules they&apos;re following. Perhaps the authors of these API&apos;s think these rules are obvious and don&apos;t need to be broadcast. However, these rules weren&apos;t made plain to me until I came across the &lt;a href=&quot;https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/&quot;&gt;StateFlow&lt;/a&gt; type in Kotlin: upon observing it&apos;s simplicity, the lack of too much magic or layers of obfuscation, this raw form of the Interaction State primitive made it all obvious to me.&lt;/p&gt;
&lt;p&gt;What benefits does this Interaction State primitive give?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When used as the main representation of the data state in a View Model, they&apos;re easily testable; the current state of the property can be taken just by calling &lt;code&gt;getValue()&lt;/code&gt;, and if you want to validate how the property changes over time, you can easily do that too.&lt;/li&gt;
&lt;li&gt;When the observable portion is implemented using something like the Reactive extensions, you can observe its value over time with endless numbers of operators. Using something very generic like Reactive extensions instead of something like &lt;code&gt;StateFlow&lt;/code&gt; leaves you very free of any assumptions made about the runtime or environment; for example, you don&apos;t have to mess with coroutine contexts or anything like that.&lt;/li&gt;
&lt;li&gt;Integrates very nicely with dynamic UI frameworks; React obviously has its state variables, Jetpack Compose has the magical &lt;code&gt;stateOf&lt;/code&gt; and &lt;code&gt;mutableStateOf&lt;/code&gt;, and C# has the &lt;code&gt;INotifyPropertyChanged&lt;/code&gt; magical interface, and the Interaction State primitive can integrate very nicely with all of them! It also integrates well with something like WinForms.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I want to show some examples of how this primitive can be used in different languages, with a fairly simple use case: given expenses and incomes, display the networth.&lt;/p&gt;
&lt;h2&gt;Kotlin and Jetpack Compose&lt;/h2&gt;
&lt;p&gt;Here&apos;s an example in Kotlin, integrating with Jetpack Compose:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-kotlin&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// The read-only interface for the Interaction State Primitive&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;InteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;T&lt;/span&gt;&amp;gt; : &lt;span class=&quot;hljs-type&quot;&gt;Observable&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;NullBox&amp;lt;T&lt;/span&gt;&amp;gt;&amp;gt;&lt;/span&gt;() {
    &lt;span class=&quot;hljs-keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; value: T
}

&lt;span class=&quot;hljs-comment&quot;&gt;// A mutable implementation of the read-only interface for the Interaction State Primitive.&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MutableInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;T&lt;/span&gt;&amp;gt;&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; initialValue: T) : InteractionState&amp;lt;T&amp;gt;() {

    &lt;span class=&quot;hljs-comment&quot;&gt;// RxJava has the unfortunate design decision of nulls not being allowed as values, so we &lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;// box the value to allow nulls.&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; behaviorSubject = BehaviorSubject.createDefault(NullBox(initialValue))

    &lt;span class=&quot;hljs-keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; value: T
        &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;() = behaviorSubject.value?.value ?: initialValue
        &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;(value) {
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (behaviorSubject.value != value)
                behaviorSubject.onNext(NullBox(value))
        }

    &lt;span class=&quot;hljs-keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;subscribeActual&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(observer: &lt;span class=&quot;hljs-type&quot;&gt;Observer&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NullBox&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;T&lt;/span&gt;&amp;gt;&amp;gt;?)&lt;/span&gt;&lt;/span&gt; {
        behaviorSubject.safeSubscribe(observer)
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;asReadOnly&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt;: InteractionState&amp;lt;T&amp;gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;
}

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;LiftedInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;T: Any&lt;/span&gt;&amp;gt;&lt;/span&gt;(source: Observable&amp;lt;T&amp;gt;, &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; initialValue: T) : InteractionState&amp;lt;T&amp;gt;(), AutoCloseable {

    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; behaviorSubject = BehaviorSubject.createDefault(NullBox(initialValue))
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; subscription = source.distinctUntilChanged().subscribe { behaviorSubject.onNext(NullBox(it)) }

    &lt;span class=&quot;hljs-keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; value: T
        &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;() = behaviorSubject.value?.value ?: initialValue

    &lt;span class=&quot;hljs-keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;subscribeActual&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(observer: &lt;span class=&quot;hljs-type&quot;&gt;Observer&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;NullBox&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;T&lt;/span&gt;&amp;gt;&amp;gt;?)&lt;/span&gt;&lt;/span&gt; {
        behaviorSubject.safeSubscribe(observer)
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt; {
        subscription.dispose()
    }
}

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MoneyViewModel&lt;/span&gt;&lt;/span&gt;(accountManager: ManageAccounts) : ViewModel() {
    &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; expenses = MutableInteractionState(&lt;span class=&quot;hljs-number&quot;&gt;0.0&lt;/span&gt;);

    &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; income = MutableInteractionState(&lt;span class=&quot;hljs-number&quot;&gt;0.0&lt;/span&gt;);

    &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; networth = LiftedInteractionState(
        Observable.combineLatest(expenses, income).map { expenses, income -&amp;gt; income - expenses },
        &lt;span class=&quot;hljs-number&quot;&gt;0.0&lt;/span&gt;);

    &lt;span class=&quot;hljs-keyword&quot;&gt;suspend&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;loadAccount&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(int accountId)&lt;/span&gt;&lt;/span&gt; {
        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; account = accountManager.loadAccount(accountId);
        expenses.Value = account.Expenses;
        income.Value = account.Income;
    }
}

&lt;span class=&quot;hljs-comment&quot;&gt;// easily map MutableInteractionState to mutableStateOf(...)&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;@Composable&lt;/span&gt;
&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;&amp;lt;T, S : MutableInteractionState&amp;lt;T&amp;gt;&lt;/span&gt;&amp;gt; S.&lt;span class=&quot;hljs-title&quot;&gt;subscribeAsMutableState&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(
    context: &lt;span class=&quot;hljs-type&quot;&gt;CoroutineContext&lt;/span&gt; = EmptyCoroutineContext
)&lt;/span&gt;&lt;/span&gt;: MutableState&amp;lt;T&amp;gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; state = remember { mutableStateOf(value) }
    DisposableEffect(key1 = &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;) {
        &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; disposable = subscribe { state.value = it.value }

        onDispose {
            disposable.dispose()
        }
    }

    LaunchedEffect(key1 = &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;) {
        value = state.value
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (context == EmptyCoroutineContext) {
            snapshotFlow { state.value }.collect {
                value = it
            }
        } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; withContext(context) {
            snapshotFlow { state.value }.collect {
                value = it
            }
        }
    }
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; state
}

&lt;span class=&quot;hljs-comment&quot;&gt;// The Compose view&lt;/span&gt;
&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MoneyView&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(viewModel: &lt;span class=&quot;hljs-type&quot;&gt;MoneyViewModel&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt; {
    with (viewModel){
        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; expensesState &lt;span class=&quot;hljs-keyword&quot;&gt;by&lt;/span&gt; expenses.subscribeAsMutableState()
        StandardTextField(
            placeholder = stringResource(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Debit&quot;&lt;/span&gt;),
            value = expensesState,
            onValueChange = { expensesState = it }
        )

        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; incomeState &lt;span class=&quot;hljs-keyword&quot;&gt;by&lt;/span&gt; income.subscribeAsMutableState()
        StandardTextField(
            placeholder = stringResource(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Credit&quot;&lt;/span&gt;),
            value = incomeState,
            onValueChange = { incomeState = it }
        )

        &lt;span class=&quot;hljs-keyword&quot;&gt;val&lt;/span&gt; networth &lt;span class=&quot;hljs-keyword&quot;&gt;by&lt;/span&gt; networth.subscribeAsState()
        Text(networth);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Typescript and React&lt;/h2&gt;
&lt;p&gt;Here&apos;s my usage in Typescript/React:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-ts&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// Build up the type definitions&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; InteractionState&amp;lt;State&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;extends&lt;/span&gt; Subscribable&amp;lt;State&amp;gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt;(): &lt;span class=&quot;hljs-title&quot;&gt;State&lt;/span&gt;;
}

&lt;span class=&quot;hljs-title&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;UpdatableInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;State&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;InteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;State&lt;/span&gt;&amp;gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;state: State&lt;/span&gt;);
}


// &lt;span class=&quot;hljs-title&quot;&gt;With&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Typescript&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;we&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;have&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;advantage&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;we&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;can&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;just&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;inherit&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;existing&lt;/span&gt; `&lt;span class=&quot;hljs-title&quot;&gt;BehaviorSubject&lt;/span&gt;` &lt;span class=&quot;hljs-title&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;here&lt;/span&gt;
// &lt;span class=&quot;hljs-title&quot;&gt;make&lt;/span&gt; `&lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt;()` &lt;span class=&quot;hljs-title&quot;&gt;read&lt;/span&gt;-&lt;span class=&quot;hljs-title&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;via&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;interface&lt;/span&gt;. &lt;span class=&quot;hljs-title&quot;&gt;Of&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;course&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;it&lt;/span&gt;&apos;&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;enforced&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;runtime&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;it&lt;/span&gt;&apos;&lt;span class=&quot;hljs-title&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;good&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;enough&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;us&lt;/span&gt;.
&lt;span class=&quot;hljs-title&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MutableInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;BehaviorSubject&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;UpdatableInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; {

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;constructor&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;initialValue: T&lt;/span&gt;)&lt;/span&gt; {
        &lt;span class=&quot;hljs-built_in&quot;&gt;super&lt;/span&gt;(initialValue);
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;value&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;value: T&lt;/span&gt;) {
        &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.next(value);
    }
}

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;LiftedInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;BehaviorSubject&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;InteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &lt;/span&gt;{

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;constructor&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;observable: Observable&amp;lt;T&amp;gt;, initialValue: T&lt;/span&gt;)&lt;/span&gt; {
        &lt;span class=&quot;hljs-built_in&quot;&gt;super&lt;/span&gt;(initialValue);
        observable.subscribe(&lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;);
    }
}

&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;liftInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;(&lt;span class=&quot;hljs-params&quot;&gt;observable: Observable&amp;lt;T&amp;gt;, initialValue: T&lt;/span&gt;): &lt;span class=&quot;hljs-title&quot;&gt;Observable&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &amp;amp; &lt;span class=&quot;hljs-title&quot;&gt;InteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &amp;amp; &lt;span class=&quot;hljs-title&quot;&gt;SubscriptionLike&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; LiftedInteractionState(observable, initialValue);
}

&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;mutableInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;(&lt;span class=&quot;hljs-params&quot;&gt;initialValue: T&lt;/span&gt;): &lt;span class=&quot;hljs-title&quot;&gt;Observable&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &amp;amp; &lt;span class=&quot;hljs-title&quot;&gt;UpdatableInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; &amp;amp; &lt;span class=&quot;hljs-title&quot;&gt;SubscriptionLike&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; MutableInteractionState(initialValue);
}

&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;useInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;(&lt;span class=&quot;hljs-params&quot;&gt;interactionState: InteractionState&amp;lt;T&amp;gt;&lt;/span&gt;): &lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; [state, setState] = React.useState(interactionState.value);

    React.useEffect(&lt;span class=&quot;hljs-function&quot;&gt;() =&amp;gt;&lt;/span&gt; {
        &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; sub = interactionState.subscribe({ &lt;span class=&quot;hljs-attr&quot;&gt;next&lt;/span&gt;: setState });
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;() =&amp;gt;&lt;/span&gt; sub.unsubscribe();
    }, [interactionState]);

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; state;
}

&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;useMutableInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;(&lt;span class=&quot;hljs-params&quot;&gt;interactionState: UpdatableInteractionState&amp;lt;T&amp;gt;&lt;/span&gt;): [&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;Dispatch&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;SetStateAction&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;&amp;gt;] &lt;/span&gt;{
    &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; state = useInteractionState(interactionState);

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; [
        state,
        &lt;span class=&quot;hljs-function&quot;&gt;(&lt;span class=&quot;hljs-params&quot;&gt;stateOrAction: SetStateAction&amp;lt;T&amp;gt;&lt;/span&gt;) =&amp;gt;&lt;/span&gt; {
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (stateOrAction &lt;span class=&quot;hljs-keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;Function&lt;/span&gt;) {
                interactionState.value = stateOrAction(interactionState.value);
                &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt;;
            }

            interactionState.value = stateOrAction;
        }];
}

&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MoneyViewModel&lt;/span&gt; &lt;/span&gt;{
    &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; income = mutableInteractionState(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);
    
    &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; expenses = mutableInteractionState(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);
    
    &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; networth = liftInteractionState(
        combineLatest([&lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.income, &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.expenses]).pipe(map(&lt;span class=&quot;hljs-function&quot;&gt;(&lt;span class=&quot;hljs-params&quot;&gt;[i, e]&lt;/span&gt;) =&amp;gt;&lt;/span&gt; i - e)),
        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);
}

&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; vm = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; MoneyViewModel();

&lt;span class=&quot;hljs-keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MoneyView&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;) &lt;/span&gt;{
    &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; income = useInteractionState(vm.income);
    &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; expenses = useInteractionState(vm.expenses);
    &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; networth = useInteractionState(vm.networth);

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span&gt;&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;value&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{income}&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;onChange&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{e&lt;/span&gt; =&amp;gt;&lt;/span&gt; vm.income.value = Number.parseFloat(e.target.value)}/&amp;gt;
        &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;value&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{expenses}&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;onChange&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{e&lt;/span&gt; =&amp;gt;&lt;/span&gt; vm.expenses.value = Number.parseFloat(e.target.value)}/&amp;gt;
        &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;h3&lt;/span&gt;&amp;gt;&lt;/span&gt;Networth:&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;/&lt;span class=&quot;hljs-name&quot;&gt;h3&lt;/span&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;{networth}&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;/&lt;span class=&quot;hljs-name&quot;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;/&lt;span class=&quot;hljs-name&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;/&lt;span class=&quot;hljs-name&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;C# and WPF&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-cs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;IInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; : &lt;span class=&quot;hljs-title&quot;&gt;IObservable&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;
{
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; T Value { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; }
}

&lt;span class=&quot;hljs-comment&quot;&gt;// Implementing INotifyPropertyChanged as well allows it to be used with WPF/XAML bindings&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MutableInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; : &lt;span class=&quot;hljs-title&quot;&gt;IReadOnlyObservableProperty&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;, &lt;span class=&quot;hljs-title&quot;&gt;INotifyPropertyChanged&lt;/span&gt;, &lt;span class=&quot;hljs-title&quot;&gt;IDisposable&lt;/span&gt;
{

    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; BehaviorSubject&amp;lt;T&amp;gt; subject;

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;event&lt;/span&gt; PropertyChangedEventHandler PropertyChanged;

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MutableInteractionState&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;T initialValue&lt;/span&gt;)&lt;/span&gt;
    {
        subject = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; BehaviorSubject&amp;lt;T&amp;gt;(initialValue);
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; T Value
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt; =&amp;gt; subject.Value;
        &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;
        {
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!EqualityComparer&amp;lt;T&amp;gt;.Default.Equals(&lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;, subject.Value))
            {
                subject.OnNext(&lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;);
                PropertyChanged?.Invoke(&lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;, &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; PropertyChangedEventArgs(&lt;span class=&quot;hljs-keyword&quot;&gt;nameof&lt;/span&gt;(Value)));
            }
        }
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; IDisposable &lt;span class=&quot;hljs-title&quot;&gt;Subscribe&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;IObserver&amp;lt;T&amp;gt; observer&lt;/span&gt;)&lt;/span&gt; =&amp;gt; subject.Subscribe(observer);

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Dispose&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt; =&amp;gt; subject.Dispose();
}

&lt;span class=&quot;hljs-comment&quot;&gt;// A read-only observable&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;LiftedInteractionState&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt; : &lt;span class=&quot;hljs-title&quot;&gt;IReadOnlyObservableProperty&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;, &lt;span class=&quot;hljs-title&quot;&gt;INotifyPropertyChanged&lt;/span&gt;
{
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; BehaviorSubject&amp;lt;T&amp;gt; subject;
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; IDisposable sourceSub;

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;event&lt;/span&gt; PropertyChangedEventHandler PropertyChanged;

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;LiftedInteractionState&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;IObservable&amp;lt;T&amp;gt; source, T initialValue&lt;/span&gt;)&lt;/span&gt;
    {
        subject = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; BehaviorSubject&amp;lt;T&amp;gt;(initialValue);
        sourceSub = source.Subscribe(v =&amp;gt; Value = v);
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; T Value
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt; =&amp;gt; subject.Value;
        &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;
        {
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!EqualityComparer&amp;lt;T&amp;gt;.Default.Equals(&lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;, subject.Value))
            {
                subject.OnNext(&lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;);
                PropertyChanged?.Invoke(&lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;, &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; PropertyChangedEventArgs(&lt;span class=&quot;hljs-keyword&quot;&gt;nameof&lt;/span&gt;(Value)));
            }
        }
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; IDisposable &lt;span class=&quot;hljs-title&quot;&gt;Subscribe&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;IObserver&amp;lt;T&amp;gt; observer&lt;/span&gt;)&lt;/span&gt; =&amp;gt; subject.Subscribe(observer);

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Dispose&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;
    {
        sourceSub.Dispose();
        subject.Dispose();
    }
}

&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MoneyViewModel&lt;/span&gt;
{
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; IAccountManager accountManager;

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; MutableInteractionState&amp;lt;&lt;span class=&quot;hljs-built_in&quot;&gt;decimal&lt;/span&gt;&amp;gt; Debit { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; } = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; MutableInteractionState&amp;lt;&lt;span class=&quot;hljs-built_in&quot;&gt;decimal&lt;/span&gt;&amp;gt; Credit { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; } = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; IInteractionState&amp;lt;&lt;span class=&quot;hljs-built_in&quot;&gt;decimal&lt;/span&gt;&amp;gt; Networth;

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MoneyViewModel&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;IAccountManager accountManager&lt;/span&gt;)&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;.accountManager = accountManager;
        &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;.Total = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; LiftedInteractionState&amp;lt;&lt;span class=&quot;hljs-built_in&quot;&gt;decimal&lt;/span&gt;&amp;gt;(
            &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;.Credit.CombineLatest(&lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt;.Debit).Select(tuple =&amp;gt;
            {
                &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; (credit, debit) = tuple;
                &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; credit - debit;
            }),
            &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;LoadAccount&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; accountId&lt;/span&gt;)&lt;/span&gt; {
        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; account = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; accountManager.LoadAccount(accountId);
        Debit.Value = account.Debit;
        Credit.Value = account.Credit;
    }
}

&amp;lt;Window&amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;TextField Value={Binding Debit.Value} /&amp;gt;
        &amp;lt;TextField Value={Binding Credit.Value} /&amp;gt;
        &amp;lt;TextLabel Value={Binding Networth.Value} /&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In my opinion, removing the obscurity around this primitive has a similar effect to understanding the &lt;a href=&quot;https://en.wikipedia.org/wiki/Futures_and_promises&quot;&gt;Promise&lt;/a&gt;; it opens up and simplifies a whole class of programming problems: with the &lt;code&gt;Promise&lt;/code&gt;, a single definition is wrapped around building asynchronous functions and receiving their results, likewise, for the &quot;Interaction State&quot; primitive, a single definition is given to making a UI that reacts to inputs agnostic of the source; in other words, regardless of whether the UI needs to respond to user input or the UI needs to respond to asynchronous calls, the situation will be handled in the same way by the &quot;Interaction State&quot; primitive. It also enables a programmer to use it for purposes beyond what the implementations above restrict the user to; for example, I&apos;ve used the Kotlin implementation in both Android XML views and Jetpack Compose, likewise, I&apos;ve used the C# implementation for common code between WinForms views and WPF views. This allows my view models to remain stable, while only the decoration is updated with new binding syntax.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>March 5th, 2024 Log</title>
   <link href="http://davidvedvick.info/notes/2024/03/05/log" />
   <updated>2024-03-05T20:29:16.000Z</updated>
   <id>http://davidvedvick.info/notes/2024/03/05/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;March 23rd, 2024&lt;/h1&gt;
&lt;h2&gt;Bittorrent is Dying, NFT&apos;s were dumb, but together they could be great?&lt;/h2&gt;
&lt;p&gt;This is probably an already explored idea, but I quite like the idea for digital art of some sort of proof-of-sale/proof-of-ownership system that uses a git-like (or blockchain-like) structure, which contains magnet links for that digital art, with the digital art itself remaining unencrypted. I think something like this would give society a neat way to appreciate artists for their work without having to lock down said work. Maybe this is what NFT&apos;s already are, I don&apos;t know!&lt;/p&gt;
&lt;h1&gt;March 18th, 2024&lt;/h1&gt;
&lt;p&gt;A defining feature of an asynchronous operation is that it is cancellable.&lt;/p&gt;
&lt;h1&gt;March 5th, 2024&lt;/h1&gt;
&lt;p&gt;Good programing is more about good judgment than anything else.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>April 9th, 2024 Log</title>
   <link href="http://davidvedvick.info/notes/2024/04/09/log" />
   <updated>2024-06-18T03:53:59.000Z</updated>
   <id>http://davidvedvick.info/notes/2024/04/09/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;April 9th, 2024&lt;/h1&gt;
&lt;p&gt;Rust seems like the perfect language for an LLM-driven programming agent, because the compiler has so many safeguards, that often the best way to build the best program is often to just iterate until your program passes the compilers tests anyways.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>June 17th, 2024 Log</title>
   <link href="http://davidvedvick.info/notes/2024/06/17/log" />
   <updated>2024-06-18T03:54:33.000Z</updated>
   <id>http://davidvedvick.info/notes/2024/06/17/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;June 17th, 2024&lt;/h1&gt;
&lt;h2&gt;Targeting Multiple Form Factors on Android&lt;/h2&gt;
&lt;p&gt;If you&apos;d want to target multiple form factors on Android for a single application, you suffer from a case of too many options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide the same app:&lt;ul&gt;
&lt;li&gt;Views that adapt to different view dimensions.&lt;/li&gt;
&lt;li&gt;Views that render differently depending on flags given during the launch of the application (typically via intent).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Provide different apps:&lt;ul&gt;
&lt;li&gt;Different product flavors or different modules:&lt;ul&gt;
&lt;li&gt;Different application IDs.&lt;/li&gt;
&lt;li&gt;Different version codes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means there are 6 (2 + 2*2) possible ways of providing a different application based on the deployed form factor. So how to choose the best?&lt;/p&gt;
&lt;p&gt;First off, the &quot;different apps design&quot; seems mostly intended for &lt;strong&gt;completely different&lt;/strong&gt; applications that share the same codebase; the fact that you can use it for different form factors seems to just be a nice side effect. This means that this approach really works best with different applications - with different application IDs, you don&apos;t need to worry about collisions when providing application artifacts on Google Play. The downside is that this leaves you with two separate apps as far as Google Play is concerned, or two different version code tracks. If you take the &quot;different version code&quot; and later consolidate your handheld and TV apps, with the TV app being on the &quot;higher&quot; version code track, users will have to for example uninstall the existing TV application. One thing to be aware of with this approach is that once set-up in the Google Play store, it is difficult to reverse.&lt;/p&gt;
&lt;p&gt;The other approach is to modify your views given different view dimensions or different &lt;code&gt;Intent&lt;/code&gt; information. For TV, for example, this can be discerned by launching a special activity that is filtered on the &lt;code&gt;android.intent.category.LEANBACK_LAUNCHER&lt;/code&gt; intent category. While having a single app makes publishing to the app store easier, it does leave both your TV users and your handheld users with the whole app, even though they may not use large swaths of it. Sharing views between TV and handheld is harder than it seems, at least with Jetpack compose, as the API&apos;s between touch and D-Pad navigation are largely separate.&lt;/p&gt;
&lt;p&gt;Regardless of approach, it feels like swimming upstream trying to have the same app in different form factors. The ideal would to be able to produce different applications per form-factor that can share application ID and version code. Absent that, I think the best approach is unfortunately to maintain a single application.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Distributed Large Language Models</title>
   <link href="http://davidvedvick.info/notes/2025/01/04/distributed-LLMs" />
   <updated>2025-01-05T00:59:40.000Z</updated>
   <id>http://davidvedvick.info/notes/2025/01/04/distributed-LLMs</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Distributed Large Language Models&lt;/h1&gt;
&lt;p&gt;LLM&apos;s have proven their utility for generating small scripts. You&apos;ll often read comments along these lines on programming forums these days:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sure LLM&apos;s can generate little scripts but they can&apos;t create real programs...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think this is largely true; however, this is actually useful in &quot;real&quot; programs — the &quot;scripting&quot; ability combined with auto-complete can definitely contribute to developing a full-sized program. Already, tools like Copilot are taking advantage of this ability. This is also generally useful (although it comes with some major caveats in my opinion).&lt;/p&gt;
&lt;p&gt;Since LLM&apos;s are so great at condensing a large amount of information into a relatively small model that can be queried with natural language, like many others, I worry about the loss of great sources of information like Stack Overflow. Stack Overflow&apos;s advantage over an LLM is that it&apos;s constantly gaining new information, and it&apos;s generally fed by great feedback loops that encourage contributing new information. Of course, this has its own issues, but in general, I think that holds.&lt;/p&gt;
&lt;p&gt;However, part of me feels like the philosophers of old, concerned that this new-fangled writing technology was going to reduce human intelligence since we no longer would need to learn through discussion. So, I think it&apos;s important to think of what will come next, now that we can in some ways have a miniature static Stack Overflow on our PC&apos;s: will we have shared models that can send information back to a host, feeding in new tips, fixes, etc.? I fear this being centralized by commercial entities, and I think even Stack Overflow is trying to build something like this. OpenAI and Microsoft are already using feedback mechanisms.&lt;/p&gt;
&lt;p&gt;Would it be possible for the programming community to do P2P model training and inference? This sounds great, but how do we develop and use shared models that have minimal or no quality control? Does or can a community form around a P2P model that corrects its training? How does a community pay for the training? Is it distributed, like folding@home but for programming help? Building a DNN model isn&apos;t just about dropping in a bunch of data and hitting the train button, it also involves a lot of decisions on the trainer: choosing appropriate number of layers, how many iterations to train, and more. This might need to be static to some degree with a shared community model.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Minnesota Code Freeze Conference Notes</title>
   <link href="http://davidvedvick.info/notes/2025/01/16/code-freeze-notes" />
   <updated>2025-01-17T19:28:02.000Z</updated>
   <id>http://davidvedvick.info/notes/2025/01/16/code-freeze-notes</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Minnesota Code Freeze Conference Notes&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;My notes from the 2025 Minnesota Code Freeze conference that took place at the University of Minnesota.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Working Effectively with Legacy Code&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Michael Feathers&lt;/em&gt; (r7k)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Test-Driven Architecture (like TDD but for architecture).&lt;/li&gt;
&lt;li&gt;Hyrum&apos;s Law: Any behavior you expose on an API will become depended upon even if it&apos;s not intended.&lt;/li&gt;
&lt;li&gt;Knowledge tends to dissipate over time (think music popularity reduction over time, for example, the ragtime of the 1920&apos;s).&lt;/li&gt;
&lt;li&gt;Galileo&apos;s scaling law (the square/cube law) - structure must change as things grow:&lt;ul&gt;
&lt;li&gt;Initially named after the concept that as an object grows its volume grows faster than the surface (n^3 &amp;gt; n^2).&lt;/li&gt;
&lt;li&gt;However, applies to other scaling concerns, for example, you can&apos;t build a skyscraper with wood.&lt;/li&gt;
&lt;li&gt;With graphs, as they grow, you need to break them into smaller graphs to manage them effectively.&lt;/li&gt;
&lt;li&gt;Understanding this tension can improve design.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Miller&apos;s law - humans can track 7 +/- 2 items&lt;ul&gt;
&lt;li&gt;This relates to class design, a class with 20 methods is much harder to track than a class with around 7.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&quot;The Principle of Deliberate Context&quot; (coined by Michael Feathers):&lt;ul&gt;
&lt;li&gt;Systems should be designed with intentionally bounded contexts that are optimally sized for human cognition.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Robustness principle: be liberal in what you accept and conservative in what you produce.&lt;/li&gt;
&lt;li&gt;A potential issue with AI is when it generates things that we don&apos;t understand.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Infrastructure as Code Anti-Patterns&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Jason Baker&lt;/em&gt; (Director of Cloud Operations at Civix)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Thought on anti-patterns: every anti-pattern started as a pattern with good intentions.&lt;/li&gt;
&lt;li&gt;Why do infrastructure as code anti-patterns exist?&lt;ul&gt;
&lt;li&gt;Senior tech leadership usually is promoted through software not infrastructure (citation needed).&lt;/li&gt;
&lt;li&gt;Defining infrastructure as code is immature compared to software development (isn&apos;t infrastructure as code software development?).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Cloud Cowboys&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Creating cloud infrastructure manually (using a web console) instead of using code.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Muti-Tool Madness&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Using too many tools to define the infrastructure.&lt;/li&gt;
&lt;li&gt;Increased complexity, risk, and toil.&lt;/li&gt;
&lt;li&gt;Picking a consistent tool is more important than pick the best tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Partitioning infrastructure projects by infrastructure type or environment instead of by context.&lt;/li&gt;
&lt;li&gt;Building all the environments&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Using a single infrastructure template to build out all environments.&lt;/li&gt;
&lt;li&gt;Templates should be environmentally agnostic.&lt;/li&gt;
&lt;li&gt;Infrastructure changes should be promoted using the same process as normal software.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;One repo to rule them all&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Defining all resources using infrastructure code in one monolithic infrastructure code repository.&lt;/li&gt;
&lt;li&gt;Can introduce undesirable coupling.&lt;/li&gt;
&lt;li&gt;Partition infrastructure code by services.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Using DRY With Infrastructure&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;All software problems can be solved with another layer abstraction, &lt;em&gt;except for the problem of too many layers of abstraction&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Taking an imperative approach to building infrastructure instead of a declarative approach.&lt;/li&gt;
&lt;li&gt;Coupling vs. cohesion&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Modularize all the things&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Same as above.&lt;/li&gt;
&lt;li&gt;Enforce the updating of module versions across projects, allowing no more than for example 2 versions in use.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;The infra team&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;All infrastructure code has to be defined by an infrastructure team.&lt;/li&gt;
&lt;li&gt;Reinforcese the traditional division between developer and infrastructure operations.&lt;/li&gt;
&lt;li&gt;A single team becomes a major bottleneck for infrastructure work.&lt;/li&gt;
&lt;li&gt;In high-performing organizations most of the infrastructure code is defined by software developers and co-located in application repositories.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;All security related infrastructure code changes must be implemented and approved by the secuirty team.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Finite State Machines and AI&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Adam Terlson&lt;/em&gt; (&lt;a href=&quot;https://github.com/adamterlson/AgenticStateMachines&quot;&gt;https://github.com/adamterlson/AgenticStateMachines&lt;/a&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using state machines to control AI agents.&lt;/li&gt;
&lt;li&gt;X State: state management and orchestration library&lt;/li&gt;
&lt;li&gt;Model-based testing of state machines&lt;/li&gt;
&lt;li&gt;His AI Agent definition:&lt;ul&gt;
&lt;li&gt;Autonomous - operates independently, making decisions without constant human input&lt;/li&gt;
&lt;li&gt;Goal-oriented - achieves specific objectives&lt;/li&gt;
&lt;li&gt;Context-aware&lt;/li&gt;
&lt;li&gt;Collaborates&lt;/li&gt;
&lt;li&gt;Interactive&lt;/li&gt;
&lt;li&gt;Persistence - retains memory of past interactions and data.&lt;/li&gt;
&lt;li&gt;Adaptive&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Agentic Systems:&lt;ul&gt;
&lt;li&gt;Actors provide autonomy and communication.&lt;/li&gt;
&lt;li&gt;State machines provide structure, enforce predictable behavior.&lt;/li&gt;
&lt;li&gt;AI provides adaptability.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Patterns:&lt;ul&gt;
&lt;li&gt;Tool use&lt;ul&gt;
&lt;li&gt;Available tools given to LLM.&lt;/li&gt;
&lt;li&gt;LLM returns JSON object describing a method (tool) call.&lt;/li&gt;
&lt;li&gt;Expected next message is tool response.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Human in the Loop (tool approval, if tool is expensive).&lt;/li&gt;
&lt;li&gt;Feedback: one oagent receives the output of another agent and gives feedback on how to improve.&lt;/li&gt;
&lt;li&gt;Collaboration: multiple specialist agents working on a broader goal where each agent owns a slice of the broader task.&lt;/li&gt;
&lt;li&gt;Orchestration: Planning agent dynamically routes to the next agent based on current context.&lt;/li&gt;
&lt;li&gt;&quot;Chartering&quot;: state machine defined by LLM.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Advantages over industry tools?&lt;ul&gt;
&lt;li&gt;(LangGraph and competitors)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Evolveable Architectures&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Rebecca Parsons&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conway&apos;s law - the systems you build will reflect the dysfunction of your organization.&lt;/li&gt;
&lt;li&gt;Last responsible moment - wait to make decisions until the last possible moment.&lt;/li&gt;
&lt;li&gt;How do we build code that is auditable?&lt;/li&gt;
&lt;li&gt;How do we build code that increases code quality?&lt;/li&gt;
&lt;li&gt;Contract testing allows developers to ignore each other.&lt;/li&gt;
&lt;li&gt;Use AI for contract testing?&lt;/li&gt;
&lt;li&gt;LLM hallucinations are a feature, not a bug. How are you supposed to generate something new if you never make something up? The question is whether there are ways to bound the hallucinations (yes, with temperature).&lt;/li&gt;
&lt;li&gt;How do you test non-deterministic systems?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Monolith vs. Platform vs. Serverless&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Corwin Diamond&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This talk was generally biased against monoliths (seemed to imply a definition of a monolith as a giant legacy application, in something like an older ecommerce server application).&lt;/li&gt;
&lt;li&gt;CAP Theorem:&lt;ul&gt;
&lt;li&gt;Consistency - works correctly.&lt;/li&gt;
&lt;li&gt;Availability - always works.&lt;/li&gt;
&lt;li&gt;Partition Tolerance - works across different partitions.&lt;/li&gt;
&lt;li&gt;You can pick 2.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Distributed CAP: different services/teams within your ecosystem will have different CAP requirements.&lt;/li&gt;
&lt;li&gt;Multi-cluster platforms...&lt;ul&gt;
&lt;li&gt;Need to solve data replication.&lt;/li&gt;
&lt;li&gt;Sounds like classic SOA/microservice problems.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cellular architecture...&lt;ul&gt;
&lt;li&gt;Platform monoliths.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Modularize abstract abstractions.&lt;/li&gt;
&lt;li&gt;Minimize different types of deployment processes.&lt;/li&gt;
&lt;li&gt;Remove requireemnts that aren&apos;t required.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Panel&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;David Laribee, Rebecca Parsons, Michael Feathers&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remote work:&lt;ul&gt;
&lt;li&gt;How can we maximize the effectiveness of in-person time?&lt;/li&gt;
&lt;li&gt;Shoud do hybrid meetings remote first.&lt;/li&gt;
&lt;li&gt;Important to work on things together with remote work.&lt;/li&gt;
&lt;li&gt;Create venues where smaller collaborations can occur.&lt;/li&gt;
&lt;li&gt;Times when we get together should be treated as precious and valuable.&lt;/li&gt;
&lt;li&gt;Is the problem encouraging people to value social connections?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Modular Monoliths:&lt;ul&gt;
&lt;li&gt;Return to simplicity.&lt;/li&gt;
&lt;li&gt;Look into testcontainers.&lt;/li&gt;
&lt;li&gt;It is important at the early stages of a product development to develop a &lt;strong&gt;well-structured&lt;/strong&gt; monolith.&lt;/li&gt;
&lt;li&gt;Chris Richardson has good ideas on microservices.&lt;/li&gt;
&lt;li&gt;Event-driven applications can be done in process (and I do).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Functional programming:&lt;ul&gt;
&lt;li&gt;&quot;The little lisper&quot;, &quot;the little schemer&quot; books.&lt;/li&gt;
&lt;li&gt;If one spends too much time in the OOP world, it can become difficult to understand functional programming.&lt;/li&gt;
&lt;li&gt;More people are recognizing the benefits of functional programming.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How do we discern when we should adhere to new programming principles vs traditional principles?&lt;ul&gt;
&lt;li&gt;With low-code/no-code, you can get started very easily, but it&apos;s hard to scale to complex problems.&lt;ul&gt;
&lt;li&gt;It&apos;s easy to solve 80% of the problem, hard to solve the remaining 20%.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Be very cautious about de-scaling your development.&lt;/li&gt;
&lt;li&gt;Where have all the mid-level engineers gone :D.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Is agile dead?&lt;ul&gt;
&lt;li&gt;Agility was kind of jettisoned, and &quot;agile&quot; became a management practice.&lt;/li&gt;
&lt;li&gt;Good technology (and good process?) disappear, they just become standard operating procedure, like small commits, TDD, etc.&lt;/li&gt;
&lt;li&gt;There are different product domains: Simple, Complex, and Chaotic. Which domain your product fits in determines how &quot;agile&quot; you need to be.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;3 things developers can do to stay current:&lt;ul&gt;
&lt;li&gt;Need to start using AI.&lt;ul&gt;
&lt;li&gt;How are they going to make money off of it?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Everyone is using AI today which differs from the prior AI hype cycles of the 60&apos;s and 80&apos;s.&lt;ul&gt;
&lt;li&gt;And problematically, most people do not have a strong mental computational model that matches how it really works.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AI is good at ideation. It can also help increase your skill at asking questions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

  </content>
</entry>
<entry>
   <title>OSN 2025 Notes</title>
   <link href="http://davidvedvick.info/notes/2025/05/29/osn-2025-notes" />
   <updated>2025-05-29T00:17:00.000Z</updated>
   <id>http://davidvedvick.info/notes/2025/05/29/osn-2025-notes</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Open Source 2025 Notes&lt;/h1&gt;
&lt;h2&gt;Throwback Thursday: Old School Optimization Using Newfangled Machine Learning&lt;/h2&gt;
&lt;h3&gt;Linear Programming&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Programming&quot; in the sense of scheduling.&lt;/li&gt;
&lt;li&gt;Inequalities carve out regions of space. These are called &quot;constraints&quot;.&lt;/li&gt;
&lt;li&gt;Objective function: goal we are trying to maximize.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Linear Optimization Facts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Solvable when bounded.&lt;/li&gt;
&lt;li&gt;Min-Max duality.&lt;ul&gt;
&lt;li&gt;As an example - RPGs: Max strength == min weakness&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Deterministic - guarantees best answer given the input. Is susceptible to garbage input.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;When to use&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Making the best choice out of many available while satisfying constraints.&lt;ul&gt;
&lt;li&gt;Resource allocation.&lt;/li&gt;
&lt;li&gt;Matching.&lt;/li&gt;
&lt;li&gt;Routing problems.&lt;/li&gt;
&lt;li&gt;Inventory decisions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Best fit for batch decisions under constraints.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Expected Outcomes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Better use of resources.&lt;/li&gt;
&lt;li&gt;Stable operations planning.&lt;ul&gt;
&lt;li&gt;Better inventory management&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pros of Linear Programming&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Measured risk, explainable, and respects your contraints. Can be built quickly with a small team.&lt;/li&gt;
&lt;li&gt;Plays nice with forecasted values: making best prediction with the data available.&lt;/li&gt;
&lt;li&gt;Any vertex of the feasible region has a cone of normal vectors where it is the optimal solution.&lt;/li&gt;
&lt;li&gt;Strength of forecast affects the feasible region.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;How to Make One?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pyomo functions like an ORM for interfacing with solvers.&lt;/li&gt;
&lt;li&gt;CBC (COIN-OR Branch Cut) to solve.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;React at Work Post-Create-React-App&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Provided testing, bundling, and a dev server built-in.&lt;/li&gt;
&lt;li&gt;&quot;Kill it with Fire&quot; book looks interesting.&lt;/li&gt;
&lt;li&gt;Create React App officially deprecated in February 2025.&lt;ul&gt;
&lt;li&gt;React 19 doesn&apos;t work well with it.&lt;/li&gt;
&lt;li&gt;React is slowly becoming its own framework instead of just acting as a component in a bring-your-own-framework model.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;h4&gt;Next.js&lt;/h4&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tight coupling of backend and frontend.&lt;/li&gt;
&lt;li&gt;Built-in server runtime.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Remix&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Also tightly coupled.&lt;/li&gt;
&lt;li&gt;Gnarly nested routing structure.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Bun&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Really fast bundler.&lt;/li&gt;
&lt;li&gt;Too much magic.&lt;/li&gt;
&lt;li&gt;Incomplete ecosystem compatibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Vite&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Fast, flexible, and friendly.&lt;/li&gt;
&lt;li&gt;Pretty easy to migrate from CRA.&lt;/li&gt;
&lt;li&gt;Static by default.&lt;/li&gt;
&lt;li&gt;Unbundled dev server, optimized builds.&lt;/li&gt;
&lt;li&gt;Can use existing rollup plugings.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Open Source Tooling and Best Practices to Improve Vulnerability Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;VM: Vulnerability Management&lt;/li&gt;
&lt;li&gt;&lt;h2&gt;--Identification -&amp;gt; Reporting -&amp;gt; Evaluation -&amp;gt; Prioritization -&amp;gt; Remediation --
∧                                                                             |
|                                                                             ∨&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;Competency trap: people don&apos;t use new tools because building competency in a new tool is challenging.&lt;/li&gt;
&lt;li&gt;Mend Renovate: formerly Renovate.&lt;/li&gt;
&lt;li&gt;Renovate bot can work off of dependencies defined in comments in a dockerfile.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Beyond the Chatbot: Delivering Business Value with LLMs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;According to IBM &quot;Institute of Business Value&quot;, only 25% of AI initiatives have delivered expected ROI.&lt;ul&gt;
&lt;li&gt;16% have scaled enterprise wide.&lt;/li&gt;
&lt;li&gt;IBM&apos;s Advice: ignore FOMO, lean into ROI.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When to chatbot:&lt;ul&gt;
&lt;li&gt;Onboarding users (employees/customer) to complex systems.&lt;/li&gt;
&lt;li&gt;When users are lost, confused, or not even sure what they need.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Need metrics&lt;ul&gt;
&lt;li&gt;conversion rate&lt;/li&gt;
&lt;li&gt;% requests routed to a human&lt;/li&gt;
&lt;li&gt;manual time saved&lt;/li&gt;
&lt;li&gt;response/execution times.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When not to chatbot:&lt;ul&gt;
&lt;li&gt;Simple forms&lt;/li&gt;
&lt;li&gt;When users are experts&lt;/li&gt;
&lt;li&gt;LLM Assisted Automation (agents) can provide value by performing tasks on triggers.&lt;/li&gt;
&lt;li&gt;Using AI to capture business that you don&apos;t have the number of people to take in the business?!?!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Solving problems with GenAI:&lt;ul&gt;
&lt;li&gt;Classifying unstructured data.&lt;ul&gt;
&lt;li&gt;What kind of document is it? What needs to be done with it?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Convert unstructured so structured data?&lt;ul&gt;
&lt;li&gt;Parsing quote requests, emails, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Translate similar data between systems:&lt;ul&gt;
&lt;li&gt;Referencing information from external vendor systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Why was something not already automated?&lt;ul&gt;
&lt;li&gt;Complex SOPs (Standard Operating Procedures).&lt;/li&gt;
&lt;li&gt;Unstructured data&lt;/li&gt;
&lt;li&gt;Parsing information from multiple internal/external services&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Measuring GenAI Solutions&lt;/h2&gt;
&lt;h3&gt;LLM Evals&lt;/h3&gt;
&lt;p&gt;&quot;Answer true or false&quot; is the key.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example:&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;SYSTEM&lt;/strong&gt;: Act as a metallurgy expert. Do not explain your answer. Answer true or false.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;USER&lt;/strong&gt;: Steel is an alloy of iron and carbon?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Easy to apply to any business domain. Ask experts: what are the toughest questions you&apos;re asked? What are the perfect 20 year veteran answers? Then let the expert decide when the AI is trustworthy enough.&lt;/p&gt;
&lt;h3&gt;Metrics Driven Development&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Answer correctness&lt;ul&gt;
&lt;li&gt;True/false, multiple choice questions&lt;/li&gt;
&lt;li&gt;More complex questions:&lt;ul&gt;
&lt;li&gt;Determine ground truth&lt;/li&gt;
&lt;li&gt;Take intersection of model answers and ground truth and divide by intersection + model + ground truth.&lt;ul&gt;
&lt;li&gt;AnswerIntersections / (AnswerIntersections + Ground Truth + Model Answers)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Faithfulness - degree to which outputs align with facts&lt;/li&gt;
&lt;li&gt;Relevancy&lt;/li&gt;
&lt;li&gt;Context recall&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://phoenix.arize.com/&quot;&gt;Arize Phoenix&lt;/a&gt;: LLM evaluation tool&lt;/li&gt;
&lt;li&gt;guardrailsai.com&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These tools are generally used to test existing LLM&apos;s, not to fine tune or create a new model. Most things that are changed by the LLM implementer are the context that is fed in, or the prompt that is given.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Against Object Pools</title>
   <link href="http://davidvedvick.info/notes/2025/06/16/against-object-pools" />
   <updated>2025-06-22T13:39:56.000Z</updated>
   <id>http://davidvedvick.info/notes/2025/06/16/against-object-pools</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Against Object Pools&lt;/h1&gt;
&lt;h2&gt;Do not use object pools in your library&lt;/h2&gt;
&lt;p&gt;Instead expose an interface for applications to implement their own object pools, such as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-cs&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Lender&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-title&quot;&gt;T&lt;/span&gt;&amp;gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;T &lt;span class=&quot;hljs-title&quot;&gt;borrow&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;;
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt;(T obj);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Why? By definition, an object pool is a leaky abstraction. Quite literally, an object pool holds onto memory once it has allocated it (usually). This means users of your library will need to know about &lt;em&gt;your&lt;/em&gt; library&apos;s object pools when chasing down a memory leak. However, that is not to say that object pools are bad, they can play a crucial role in reducing allocation times, and help with garbage collection overhead. But whether this optimization is worth the trade-off can only be known at the application level.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>November 8th, 2025 Log</title>
   <link href="http://davidvedvick.info/notes/2025/11/08/log" />
   <updated>2025-11-08T00:59:40.000Z</updated>
   <id>http://davidvedvick.info/notes/2025/11/08/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;November 8th, 2025&lt;/h1&gt;
&lt;p&gt;If it can&apos;t be automated, then it&apos;s not a quality control process, it&apos;s just somebody&apos;s opinion of what quality is.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>Lenovo Slim 7 Pro-X Troubleshooting</title>
   <link href="http://davidvedvick.info/notes/2025/12/08/lenovo-slim-7-pro-x-notes" />
   <updated>2025-12-09T04:17:29.000Z</updated>
   <id>http://davidvedvick.info/notes/2025/12/08/lenovo-slim-7-pro-x-notes</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Lenovo Slim 7 Pro-X Troubleshooting&lt;/h1&gt;
&lt;h4&gt;USB-C Ports Not Recognizing Devices&lt;/h4&gt;
&lt;p&gt;If the USB-C ports are not recognizing devices — only accepting power delivery, or nothing at all — then try turning the device off, holding the power button for at least 30 seconds (you should see a power cycle on the screen), and trying again.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>My Ideal C#-Like Language</title>
   <link href="http://davidvedvick.info/notes/2025/12/14/my-ideal-c-sharp-like-language" />
   <updated>2025-12-22T13:43:47.000Z</updated>
   <id>http://davidvedvick.info/notes/2025/12/14/my-ideal-c-sharp-like-language</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;My Ideal C#-Like Language&lt;/h1&gt;
&lt;p&gt;Some of these ideas could live with the current language, some would be drastic changes.&lt;/p&gt;
&lt;h2&gt;An &lt;code&gt;on&lt;/code&gt; keyword for use after an &lt;code&gt;await&lt;/code&gt; statement&lt;/h2&gt;
&lt;p&gt;To make it trivial to switch your synchronization context, an &lt;code&gt;on&lt;/code&gt; keyword. Usage:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; updatedValue = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; service.GetValue() &lt;span class=&quot;hljs-keyword&quot;&gt;on&lt;/span&gt; UiSynchronizationContext;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I first had this idea &lt;a href=&quot;https://davidvedvick.info/notes/2022/06/20/async-await-implementation-details&quot;&gt;in 2022&lt;/a&gt; so I&apos;ve been on this one for a while.&lt;/p&gt;
&lt;h2&gt;Easy Implementation of Delegation&lt;/h2&gt;
&lt;p&gt;If you&apos;ve been doing this programming thing for a while, you&apos;ve likely come across the idea of composition over inheritance, that is, prefer delegating implementation to another type instead of inheriting it from a sub-type. Kotlin &lt;a href=&quot;https://kotlinlang.org/docs/delegation.html#overriding-a-member-of-an-interface-implemented-by-delegation&quot;&gt;provides this capability&lt;/a&gt; with the &lt;code&gt;by&lt;/code&gt; keyword, which seems fine to me. In C#:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;interface IAccess
{
    Task&amp;lt;Value&amp;gt; GetValue();

    Task SetValue(Value value);
}

class NetworkAccess(HttpClient httpClient) : IAccess
{
    public Task&amp;lt;Value&amp;gt; GetValue()
    {
        var response = await httpClient.GetJson&amp;lt;Value&amp;gt;();
        return response;
    }

    public Task SetValue(Value value)
    {
        var response = await httpClient.PostJson(value);
    }
}

class CachedAccess(ICache cache, IAccess innerAccess) : IAccess by innerAccess
{
    public Task&amp;lt;Value&amp;gt; GetValue()
    {
        var response = await innerAccess.GetValue();
        cache.Set(key, response);
        return response;
    }

    // SetValue is automatically delegated to innerAccess...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Even better would be if we could have automatic &lt;em&gt;decoration&lt;/em&gt;. This is a tougher one, how do we handle the infinite number of method combinations? Maybe visitors are a way?&lt;/p&gt;
&lt;h2&gt;Public Methods Async By Default&lt;/h2&gt;
&lt;p&gt;In the spirit of more extensive language additions, all public methods should be &lt;code&gt;async&lt;/code&gt; by default. A developer should always assume that public methods don&apos;t complete immediately. A developer has to instead declare a method &lt;code&gt;sync&lt;/code&gt; to state that the method executes immediately. Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;IAccess&lt;/span&gt; {
    &lt;span class=&quot;hljs-function&quot;&gt;Value &lt;span class=&quot;hljs-title&quot;&gt;GetValue&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;;
    &lt;span class=&quot;hljs-function&quot;&gt;sync Value &lt;span class=&quot;hljs-title&quot;&gt;GetValueImmediately&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;;
}

&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; access.GetValue();
&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt; = access.GetValueImmediately();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What I like about this idea is that method &quot;coloring&quot; works in reverse: the writer of a method has to instead say &lt;em&gt;&quot;this method executes immediately with no I/O access, no computations on another thread&quot;&lt;/em&gt;, since in the real world, &lt;strong&gt;all operations&lt;/strong&gt; execute asynchronously. One consequence of this idea is that the &lt;code&gt;Task&lt;/code&gt; type is hidden, and I do not like hiding &quot;magic&quot; too much, so this definitely has its flaws. Maybe the underlying &lt;code&gt;Task&lt;/code&gt;/&lt;code&gt;Promise&lt;/code&gt; could be exposed via reflection?&lt;/p&gt;
&lt;h2&gt;Public Properties Observable By Default&lt;/h2&gt;
&lt;p&gt;This is another thing that Kotlin/Jetpack Compose sort of has with &lt;a href=&quot;https://developer.android.com/reference/kotlin/androidx/compose/runtime/MutableState&quot;&gt;Mutable State&lt;/a&gt; and &lt;a href=&quot;https://developer.android.com/develop/ui/compose/side-effects#snapshotFlow&quot;&gt;snapshotFlow&lt;/a&gt;, but since it&apos;s not a default, you have to kind of guess whether a property is observable or not. In my new language I propose that properties are observable by default. The properties wouldn&apos;t need be an &lt;code&gt;IObservable&lt;/code&gt; and take on all the baggage of that type, they could just implement &lt;code&gt;IAsyncEnumerable&lt;/code&gt;. Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Person&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; Name { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;; }
}

&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; person = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Person();

&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; updateNameTask = Task.Run(() =&amp;gt; {
    person.Name = &lt;span class=&quot;hljs-string&quot;&gt;&quot;Bob&quot;&lt;/span&gt;;
    person.Name = &lt;span class=&quot;hljs-string&quot;&gt;&quot;David&quot;&lt;/span&gt;;
});

&lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;foreach&lt;/span&gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; name &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; person.Name)
{
    &lt;span class=&quot;hljs-comment&quot;&gt;// Prints &quot;Name: Bob&quot; and then &quot;Name: David&quot;&lt;/span&gt;
    Console.WriteLine(&lt;span class=&quot;hljs-string&quot;&gt;$&quot;Name: &lt;span class=&quot;hljs-subst&quot;&gt;{name}&lt;/span&gt;&quot;&lt;/span&gt;);
}

&lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; updateNameTask;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But you should also just be able to read the current value (see the &lt;a href=&quot;./notes/20231214-interaction-state-primitive.md&quot;&gt;Interaction State primitive&lt;/a&gt;), so you should also be to just call it like a normal property:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Person&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt; Name { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; &lt;span class=&quot;hljs-keyword&quot;&gt;set&lt;/span&gt;; } = &lt;span class=&quot;hljs-string&quot;&gt;&quot;John&quot;&lt;/span&gt;;
}

&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; person = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Person();
&lt;span class=&quot;hljs-comment&quot;&gt;// Prints &quot;John&quot;&lt;/span&gt;
Console.WriteLine(&lt;span class=&quot;hljs-string&quot;&gt;$&quot;Name: &lt;span class=&quot;hljs-subst&quot;&gt;{person.Name}&lt;/span&gt;&quot;&lt;/span&gt;);
&lt;/code&gt;&lt;/pre&gt;
  </content>
</entry>
<entry>
   <title>Easy Delegation with a C# Source Generators Library</title>
   <link href="http://davidvedvick.info/notes/2026/01/21/source-generators-easy-delegation-c-sharp" />
   <updated>2026-01-21T14:09:48.000Z</updated>
   <id>http://davidvedvick.info/notes/2026/01/21/source-generators-easy-delegation-c-sharp</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;Easy Delegation with a C# Source Generators Library&lt;/h1&gt;
&lt;p&gt;In &lt;a href=&quot;./20251214-my-ideal-c-sharp-like-language.md&quot;&gt;my last post&lt;/a&gt; I posted a wish list for C# that would make program construction easier. One of these was easy implementation of delegation, or in other words, &lt;a href=&quot;https://en.wikipedia.org/wiki/Composition_over_inheritance&quot;&gt;Composition over Inheritance&lt;/a&gt;; that is the ability to automagically do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;interface IAccess
{
    Task&amp;lt;Value&amp;gt; GetValue();

    Task SetValue(Value value);
}

class NetworkAccess(HttpClient httpClient) : IAccess
{
    public async Task&amp;lt;Value&amp;gt; GetValue()
    {
        var response = await httpClient.GetJson&amp;lt;Value&amp;gt;();
        return response;
    }

    public async Task SetValue(Value value)
    {
        var response = await httpClient.PostJson(value);
    }
}

class CachedAccess(ICache cache, IAccess innerAccess) : IAccess
{
    public async Task&amp;lt;Value&amp;gt; GetValue()
    {
        var response = await innerAccess.GetValue();
        await cache.SetValue(response);
        return response;
    }

    public Task SetValue(Value value)
    {
        return inner.SetValue();
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well, after I got over the flu this Christmas, I began looking in anger at how to build source generators for C#, with the hope that I could make something like this reality. Using &lt;a href=&quot;https://github.com/CodingFlow/decorator-generator/&quot;&gt;Decorator Generator&lt;/a&gt; as a base (which was very close to what I wanted - but I wanted less configuration), I created &lt;a href=&quot;https://codeberg.org/namehillsoftware/TypeAdoption&quot;&gt;TypeAdoption&lt;/a&gt;, which auto-wires up inner implementations using an &lt;code&gt;[Adopt]&lt;/code&gt; attribute. So taking the above example, you can do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;interface IAccess
{
    Task&amp;lt;Value&amp;gt; GetValue();

    Task SetValue(Value value);
}

class NetworkAccess(HttpClient httpClient) : IAccess
{
    public async Task&amp;lt;Value&amp;gt; GetValue()
    {
        var response = await httpClient.GetJson&amp;lt;Value&amp;gt;();
        return response;
    }

    public async Task SetValue(Value value)
    {
        var response = await httpClient.PostJson(value);
    }
}

// The class needs to be partial
partial class CachedAccess(ICache cache, IAccess innerAccess)
{
    [Adopt]
    private readonly IAccess _inner = innerAccess;

    public async Task&amp;lt;Value&amp;gt; GetValue()
    {
        var response = await _inner.GetValue();
        await cache.SetValue(response);
        return response;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will generate this implementation of &lt;code&gt;IAccess&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;partial&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;CachedAccess&lt;/span&gt; : &lt;span class=&quot;hljs-title&quot;&gt;IAccess&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;SetValue&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;Value &lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; _inner.SetValue();
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that &lt;code&gt;GetValue&lt;/code&gt; has no auto-generated implementation, since it was implemented in the actual class. This can also be useful for choosing between multiple implementations. For example, say there is another interface that has &lt;code&gt;SetValue&lt;/code&gt; with the same signature, and both are adopted, then you&apos;ll now have to determine how &lt;code&gt;SetValue&lt;/code&gt; works:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-csharp&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;ICache&lt;/span&gt;
{
    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;IsCached&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;;

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Value Value { &lt;span class=&quot;hljs-keyword&quot;&gt;get&lt;/span&gt;; }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;SetValue&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;Value &lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;;
}

&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;partial&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;CachedAccess&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;ICache cache, IAccess innerAccess&lt;/span&gt;)&lt;/span&gt;
{
    [&lt;span class=&quot;hljs-meta&quot;&gt;Adopt&lt;/span&gt;]
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; ICache _cache = cache;

    [&lt;span class=&quot;hljs-meta&quot;&gt;Adopt&lt;/span&gt;]
    &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;readonly&lt;/span&gt; IAccess _inner = innerAccess;

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task&amp;lt;Value&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;GetValue&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;/span&gt;)&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-comment&quot;&gt;// ICache memebers now available as first-class members of the class.&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (IsCached())
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; Value;

        &lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; response = &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; _inner.GetValue();
        &lt;span class=&quot;hljs-comment&quot;&gt;// Still just want to go directly to cache for this usage of SetValue()&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; _cache.SetValue(key, response);
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; response;
    }

    &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;async&lt;/span&gt; Task &lt;span class=&quot;hljs-title&quot;&gt;SetValue&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;Value &lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;
    {
        &lt;span class=&quot;hljs-comment&quot;&gt;// Set both inner values - set the network access first, once that succeeds, cache the value.&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; _inner.SetValue(&lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;);
        &lt;span class=&quot;hljs-keyword&quot;&gt;await&lt;/span&gt; _cache.SetValue(&lt;span class=&quot;hljs-keyword&quot;&gt;value&lt;/span&gt;);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Using these contrived examples, one can imagine how it would extend to interfaces with many members; perhaps you are using &lt;a href=&quot;https://github.com/reactiveui/refit&quot;&gt;Refit&lt;/a&gt; to implement an extensive API, and a few methods need manual intervention: manually implement those methods and delegate the remaining members to the Refit implementation!&lt;/p&gt;
&lt;p&gt;Again, the library is called &lt;a href=&quot;https://codeberg.org/namehillsoftware/TypeAdoption&quot;&gt;TypeAdoption&lt;/a&gt;, and it&apos;s already available on &lt;a href=&quot;https://www.nuget.org/packages/NameHillSoftware.TypeAdoption&quot;&gt;NuGet&lt;/a&gt;.&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>March 8th, 2026 Log</title>
   <link href="http://davidvedvick.info/notes/2026/03/08/log" />
   <updated>2026-03-08T18:59:40.000Z</updated>
   <id>http://davidvedvick.info/notes/2026/03/08/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;March 30th, 2026&lt;/h1&gt;
&lt;h2&gt;Combining Handheld and TV views&lt;/h2&gt;
&lt;p&gt;In my eternal &quot;wood-carving&quot; project, &lt;a href=&quot;https://github.com/namehillsoftware/projectBlue&quot;&gt;project blue&lt;/a&gt;, I am now attempting to whittle my two root view application (one for TV and one for handhelds) down into one view: the view will automatically assume the split-screen &quot;Browser&quot;/&quot;Now Playing&quot; view when the canvas is wider than it is tall; otherwise, it will still be split, but the Browser and the Now Playing view will be two pages that you swipe between. I&apos;m hopeful that this brings the entire design into one single design that is easier to maintain and use. &lt;a href=&quot;https://github.com/namehillsoftware/projectBlue/issues/614&quot;&gt;My plan so far&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;March 8th, 2026&lt;/h1&gt;
&lt;p&gt;When Cory Doctorow speaks of AI, he usually uses a &quot;centaur&quot; metaphor, split into two separate concepts: the &quot;centaur&quot;, where the human is assisted by the machine, and the &quot;reverse centaur&quot;, where the human has to help the machine. The &quot;centaur&quot; is preferable; a machine helping us do our jobs is the entire point of these things.&lt;/p&gt;
&lt;p&gt;Code review is one such case where a language model is a useful tool that assists the human instead of demanding the human help it. Deepseek r1:14b hits a sweet spot for me ― useful feedback that runs quickly on a local GPU with 12GB of ram. I&apos;ve also found that if the changes are so large that it starts spitting out nonsense, then that probably means that the changes in the commit are too large in the first place!&lt;/p&gt;


&lt;p&gt;&lt;em&gt;Keep this quote in your back-pocket&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Programs must be written for people to read, and only incidentally for machines to execute.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Harold Abelson, &lt;a href=&quot;https://www.goodreads.com/book/show/43713.Structure_and_Interpretation_of_Computer_Programs&quot;&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;&lt;/p&gt;

  </content>
</entry>
<entry>
   <title>April 3rd, 2026 Log</title>
   <link href="http://davidvedvick.info/notes/2026/04/03/log" />
   <updated>2026-04-03T15:22:23.000Z</updated>
   <id>http://davidvedvick.info/notes/2026/04/03/log</id>
   <content type="html" xml:base="http://davidvedvick.info">
     &lt;h1&gt;April 3rd, 2026&lt;/h1&gt;
&lt;h2&gt;New Picture of Home&lt;/h2&gt;
&lt;p&gt;Artemis II is already sending back beautiful images of home. When seeing this, although the picture is a much larger of our Earth than the &quot;pale blue dot&quot; seen from Saturn, I&apos;m reminded of Carl Sagan&apos;s essay on Earth:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Look again at that dot. That&apos;s here. That&apos;s home. That&apos;s us. On it everyone you love, everyone you know, everyone you ever heard of, every human being who ever was, lived out their lives. The aggregate of our joy and suffering, thousands of confident religions, ideologies, and economic doctrines, every hunter and forager, every hero and coward, every creator and destroyer of civilization, every king and peasant, every young couple in love, every mother and father, hopeful child, inventor and explorer, every teacher of morals, every corrupt politician, every &quot;superstar,&quot; every &quot;supreme leader,&quot; every saint and sinner in the history of our species lived there--on a mote of dust suspended in a sunbeam.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The Earth is a very small stage in a vast cosmic arena. Think of the rivers of blood spilled by all those generals and emperors so that, in glory and triumph, they could become the momentary masters of a fraction of a dot. Think of the endless cruelties visited by the inhabitants of one corner of this pixel on the scarcely distinguishable inhabitants of some other corner, how frequent their misunderstandings, how eager they are to kill one another, how fervent their hatreds.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Our posturings, our imagined self-importance, the delusion that we have some privileged position in the Universe, are challenged by this point of pale light. Our planet is a lonely speck in the great enveloping cosmic dark. In our obscurity, in all this vastness, there is no hint that help will come from elsewhere to save us from ourselves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The Earth is the only world known so far to harbor life. There is nowhere else, at least in the near future, to which our species could migrate. Visit, yes. Settle, not yet. Like it or not, for the moment the Earth is where we make our stand.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;It has been said that astronomy is a humbling and character-building experience. There is perhaps no better demonstration of the folly of human conceits than this distant image of our tiny world. To me, it underscores our responsibility to deal more kindly with one another, and to preserve and cherish the pale blue dot, the only home we&apos;ve ever known.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.planetary.org/worlds/pale-blue-dot&quot;&gt;— Carl Sagan, Pale Blue Dot, 1994&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/notes/content/2026-earth-from-artemis-II.jpg&quot; alt=&quot;Earth from Artemis II&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Source: &lt;a href=&quot;https://www.nasa.gov/image-article/hello-world/&quot;&gt;Hello, World - Nasa&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Events as state or events as notifications?&lt;/h2&gt;
&lt;p&gt;Much less interestingly, I came across a post on LinkedIn that perfectly crystallizes a difference I&apos;ve been struggling to define between event sources and event busses: events as state vs. events as notifications &lt;a href=&quot;https://www.linkedin.com/posts/dcomartin_the-term-event-driven-architecture-has-activity-7444866038204125184-QJ5J&quot;&gt;https://www.linkedin.com/posts/dcomartin_the-term-event-driven-architecture-has-activity-7444866038204125184-QJ5J&lt;/a&gt;&lt;/p&gt;

  </content>
</entry>
    </feed>