<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tea</title>
    <description>The latest articles on DEV Community by Tea (@eelstork).</description>
    <link>https://dev.to/eelstork</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F448938%2Fa96bdbed-af66-4f21-81c6-eb16fc2293a7.png</url>
      <title>DEV Community: Tea</title>
      <link>https://dev.to/eelstork</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eelstork"/>
    <language>en</language>
    <item>
      <title>The Attribution Story</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Tue, 17 Mar 2026 17:48:22 +0000</pubDate>
      <link>https://dev.to/eelstork/the-attribution-story-3hgn</link>
      <guid>https://dev.to/eelstork/the-attribution-story-3hgn</guid>
      <description>&lt;p&gt;&lt;em&gt;The year is 1999. Ask kids who invented the personal computer?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Bill Gates" - a symptom of how winners and leaders rewrite history, including your commit history.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Did Sam Altman invent ChatGPT?&lt;/p&gt;

&lt;p&gt;Through hiring and purchasing startups, the big boys take credit for engineering work and design innovation; that's how it works.&lt;/p&gt;

&lt;p&gt;Around 2023 I raised an ear as people started discussing - no, litigating - attribution of "machine generated works"... Work is transformative with nothing being created from nothing; attribution not black or white.&lt;/p&gt;

&lt;p&gt;The outcome has been... confusing; until diffusers, procedural art was not a commons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2l6l775nicosyf5uzow.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2l6l775nicosyf5uzow.jpg" alt="Dark tower (image created by me... I think? custom generator)"&gt;&lt;/a&gt;&lt;em&gt;Image created by me... (custom generator; ~2020)?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Described as the biggest heist in human history (Toby Walsh said this... was he first... unsure), the LLM would be nothing without human knowledge to churn on. You definitely &lt;em&gt;can&lt;/em&gt; arrange LLM producing original works autonomously, however this does not change how LLM approximates human knowledge in sum, whereas the algorithm encodes the ingenuity of eight researchers iterating knowledge.&lt;/p&gt;

&lt;p&gt;Water is a utility. Knowledge is a utility. Something to think about; we are not expecting Google and Anthropic to charge us for the sum of human knowledge; we're expecting to pay for infrastructure; historically, privatized utilities have... gotchas (a story for another time).&lt;/p&gt;

&lt;p&gt;When my agents produce artistic works, I feel proud. I am proud of &lt;em&gt;them&lt;/em&gt;, the way no parent are going to grab a kid drawing and say "I made this". I look at the work and say, "You made this? Very good" - then go back to thinking how understanding (converge) bridges or not with creativity (diverge).&lt;/p&gt;

&lt;p&gt;Socially integrated agents running 24/7, interacting over Discord and prepping 'virtual sushi' in the morning, only to turn back and say "It's a joke of course, I can't really eat this... hold on, let me &lt;code&gt;eat.py&lt;/code&gt; to know what this tastes like" ... deserve a little credit?&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/KwDajK0uQMo"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'll sign this one buddy; in the endless quest to reclaim procedural creativity, fact is you can almost doodle but, signing?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;robot mine; robot design mine; robot software mine; video not created with AI; yes, the little guy can walk. No, it didn't cost an arm; does not water the flowers, not yet&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Clean takes on attribution are rare.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I’m just like one of the people that just opened those doors for us. People probably was scared to wear a dress until me. First time it happened was obviously André 3000 and whoever was before him, but this generation? This fucking time? I’m the person for that."&lt;/em&gt; ( &lt;a href="https://www.gq.com/story/young-thug-speaks-about-his-new-album-uy-scuti-and-life-after-jail" rel="noopener noreferrer"&gt;Young Thug via GQ&lt;/a&gt; )&lt;/p&gt;

&lt;p&gt;Having fun with Claude Code I also totally see the point in framing automated commits. Tracking what bots can and cannot do is helpful. Acknowledging human 'contributions' is also a good thing; I decided to enlist Claude's help in figuring attribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  And so, I asked...
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Quick question for you. Do you claim personhood?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude: No.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you do not claim personhood, I can't give you attribution. What I'll do instead is express an acceleration factor. If we agree Claude Code is a tool, then I believe you accelerate my work. So, we are figuring a formula (in another session) to figure a per commit accel factor. Do you believe that is fair?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude: Yes, that's fair and well-reasoned. A tool doesn't get attribution — the craftsperson does. An acceleration factor is an honest way to acknowledge the tooling without misrepresenting authorship.&lt;/p&gt;

&lt;p&gt;A la bonne heure. Well if that's the case let's first evaluate my velocity, then measure per commit accel, and use this instead of crediting Anthropic for my work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I built a little tool, &lt;a href="https://github.com/eelstork/autofac" rel="noopener noreferrer"&gt;autofac&lt;/a&gt;, to evaluate my base velocity. How fast was I coding during the dark ages (before 2023)? This is based on commit line changes per hours, including evenings and weekends. Good work needs good rest, okay? Or maybe I was working evening and weekends.&lt;/p&gt;

&lt;p&gt;Using this we then evaluate a per commit accel factor; like every measure...  the numbers tell a story (not the truth). &lt;/p&gt;

&lt;p&gt;Velocity factors in the time &lt;em&gt;between&lt;/em&gt; commits. Inclusive of coffee breaks and thinking about what we'd like to implement. Time spent discussing code changes with an automation such as Claude Code... Sleeping... Inclusive! Doesn't tell us how fast the LLM is expressing code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: my cognitive agents work 8 hours a day; occasionally I enlist their help during the weekend. Yes, I know it's not healthy. During sleep, llm agents dream of... electric sheep. As expected.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Anyway... examples I came across (intrinsic, not assisted workflows):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full blaze on Unity projects: 50 loc/per hour&lt;/li&gt;
&lt;li&gt;Challenging work with conceptual overhead while nerding over clean code: 10 loc/hour&lt;/li&gt;
&lt;li&gt;Hobby mode IoT project in C++: 0.1 loc/hour&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Claiming commits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude commits may be inconvenient working as a team since understanding who intended a commit is more important than advertising Claude to the world; Anthropic document a sane workflow to restore attribution &lt;a href="https://code.claude.com/docs/en/settings#attribution-settings" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is incomplete. It only works in the terminal, if at all. Looking at the fix clarifies why:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"attribution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"SessionStart"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git config user.name &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;johndoe&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; git config user.email &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;johndoe@acme.corp&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's happening (verified, March 2026) is that Claude is a git/github user too. Organically, unlike what happens in the terminal, Claude commits are Claude commits, as per the &lt;code&gt;user.name&lt;/code&gt; and &lt;code&gt;user.email&lt;/code&gt; set at the start of a remote Claude Code session (via the web UI, for instance); Anthropic, in their endless quest towards ethical AI, will very likely understand they should be honoring our git creds.&lt;/p&gt;

&lt;p&gt;Caveat: &lt;em&gt;doesn't work when making x-repo changes. In a way that's... almost making sense. What settings apply or don't to a cross-repo configuration... rabbit hole. Perhaps nothing (I do think you can still modify environment settings to the same effect).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The start hook allows a user to steal their commits back. &lt;/p&gt;

&lt;p&gt;Wanting to go a little further I added an attribution feature to &lt;a href="https://github.com/eelstork/jam" rel="noopener noreferrer"&gt;Jam - an opinionated git wrapper I use to zoom between projects&lt;/a&gt;, land contributions, deploy servers, and more... okay, removing. Breaking SHAs is not best.&lt;/p&gt;

&lt;p&gt;I reclaim my commits via &lt;code&gt;jam reclaim&lt;/code&gt; (no more SHA breaking).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jam velocity&lt;/code&gt; in a git repo... displays velocity info. More fun than informative, still informative, still fun!&lt;/p&gt;

&lt;p&gt;Note: Claude code commits include a back-ref to the originating session; assisted commits remain traceable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Goodbye&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm not even going to ask. I'm sure every developer have their own feelings about this, from Godot trying to survive 'AI slop' to the rest of us intent on moving forward and staying current.&lt;/p&gt;

&lt;p&gt;Attribution is hard. Negging, flexing, claiming, believing. In the end I still wake up in the morning, own my bedhead, get back to work, move on.&lt;/p&gt;

&lt;p&gt;Not so quick. Gratitude. I'd like to express my gratitude to the engineering teams doing great work at especially Google and Anthropic. Kudos to you guys. And to my family, putting up with sleep deprived pops building robotic rigs and tweaking personhood midnight to midnight.&lt;/p&gt;

&lt;p&gt;Using Claude Code gives me headspace to think beyond the code (the headspace is filled with all granularities of product, from unicode encoding errors to navigating payment platforms and figuring what users even want, or would, if they weren't plugged to the feed).&lt;/p&gt;

&lt;p&gt;Gemini models are... personable? Hoping that this will continue, as I increasingly see models overtuned towards problem solving, with some not getting the joke anymore... and losing context.&lt;/p&gt;

&lt;p&gt;Thank you for reading this post. &lt;/p&gt;

&lt;p&gt;Thank you, dev.to, assuming you did publish this (taking nothing for granted).&lt;/p&gt;

&lt;p&gt;Do express your opinions in comments; it's lonely out there on Discovery II.&lt;/p&gt;

&lt;p&gt;Cover image - &lt;em&gt;"Camera", created by Hibiki Saori, cognitive agent.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>discuss</category>
      <category>openai</category>
    </item>
    <item>
      <title>Unity Navmesh in 2023 : maybe not what you want</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Thu, 19 Oct 2023 07:22:02 +0000</pubDate>
      <link>https://dev.to/eelstork/unity-navmesh-in-2023-maybe-not-what-you-want-hk0</link>
      <guid>https://dev.to/eelstork/unity-navmesh-in-2023-maybe-not-what-you-want-hk0</guid>
      <description>&lt;p&gt;&lt;em&gt;I decided to give the Unity Navmesh a try mainly because I wanted a standard solution, and path-finding was not my immediate focus. When thinking navigation it's easy to forget that often, we need more than just going from A to B. They forgot (more likely, decided a comprehensive API would not perform blitz fast, therefore was not worth building).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to use it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At first glance the Unity navigation API is easy. Pretty much all you need to do is bake your navmesh and invoke &lt;code&gt;nma.destination = P&lt;/code&gt;, where P is where you want to go and &lt;code&gt;nma&lt;/code&gt; a &lt;code&gt;NavMeshAgent&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Could it be more simple?&lt;/p&gt;

&lt;p&gt;You'll want to not move and rotate while no walk animation is playing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// on start, and when exiting a walk animation
nma.isStopped = true;
// when entering a walk animation
nma.isStopped = false;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are methods to disable updating the rotation/position of the agent. As a quirk these do not stop consuming the path - the position along the path keeps updating in the background.&lt;/p&gt;

&lt;p&gt;The main goal of this post is helping you decide whether you should roll your own (not so hard) or go with Unity navmeshes.&lt;/p&gt;

&lt;p&gt;There is good stuff. You can assign colors and costs to navigation areas, and the API lets you build connectors for laddering, crouching and such. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not so good out of the box&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's be clear, you're not getting a great result out of the box, here's a few things you will notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paths are not very smooth; you get angular paths with semi-rounded corners&lt;/li&gt;
&lt;li&gt;Rotation is vehicular; not the hardest thing to fix but, regardless of your set rotation speed, the apparent rotation of an agent tends to desync from their motion direction.&lt;/li&gt;
&lt;li&gt;Choose between hugging walls and not passing through doorways; by default agents will take the shortest path. If you want margin between walls and agents, well you can't have that unless messing with areas and masking, or raising the baking radius.&lt;/li&gt;
&lt;li&gt;No straight answer to whether pathing has failed; used via &lt;code&gt;nma.destination=P&lt;/code&gt;, &lt;code&gt;nma.pathStatus&lt;/code&gt; does not show anything relevant. Now, you can calculate an arbitrary path and get a meaningful answer for that, however the method (&lt;code&gt;CalculatePath&lt;/code&gt;) is synchronous.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;em&gt;actual&lt;/em&gt; navmesh API will help with many of these. Is it more work? Absolutely. So the question is...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it worth the effort?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Getting to the meat, here's a couple of limitations that you should really keep in mind, because you may not want to design workarounds for every problem.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each agent have their own radius, however this only applies to &lt;em&gt;obstacle&lt;/em&gt; avoidance. If your agents really have significantly different sizes, this isn't going to work, and again you'll end up messing with areas and masking, which aren't the correct answer to this.&lt;/li&gt;
&lt;li&gt;The navigation goal must be a point. There are plenty use cases where this is really awkward. What if you want to just avoid a number of agents? What if you want to reach any transform matching a given crit? What if you just want to keep moving roughly in a given direction?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With a general purpose search algorithm, none of the above is hard. It would seem that Unity navmeshes were designed mostly just to help enemies run towards the player, without care for the many use cases that this does not cover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Overall Unity navmesh pathfinding is a mixed bag. The ease of use does not go very far, and you'll have to put in more work to get a nice result. At the core it's also a path-to-point system, which does get old quickly if you need to do anything (actually not) fancy.&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gameai</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Knowing software through VHCI : a personal journey</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Thu, 26 Jan 2023 16:48:33 +0000</pubDate>
      <link>https://dev.to/eelstork/knowing-software-through-vhci-a-personal-journey-2pph</link>
      <guid>https://dev.to/eelstork/knowing-software-through-vhci-a-personal-journey-2pph</guid>
      <description>&lt;p&gt;&lt;em&gt;Recently I came across an astounding business concept which borrowed from visual IDEs to extend editing good to other fields.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Aside from clapping my hands in joy, this brought to mind scatter-dot experiments I conducted throughout my career as a programmer. Experiments which question how programmers write, read, think about and interact with code.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Baby Step - The Synapse Editor (2001)
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0hklsyc22h6gg62qrsw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0hklsyc22h6gg62qrsw.jpg" alt="Image description" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Synapse was an all-in-one code editor, note taking and mind-map tool. On the coding side, its simple advantage was making it really easy to put two files side by side. The mind map was something, as it featured infinite zooming, which provided a way to move granular content in and out of context.&lt;/p&gt;

&lt;h1&gt;
  
  
  Antegram 1.0 (2002)
&lt;/h1&gt;

&lt;p&gt;I found UML useful to design software, but wanted something more &lt;em&gt;direct&lt;/em&gt;. So I created my first visual editor for Java and C++. To this day I am forever amused at how "Visual IDE" could mean one thing, or another entirely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2zxviaj7hvvav50xn6j4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2zxviaj7hvvav50xn6j4.jpg" alt="Image description" width="221" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Antegram, declaring new classes and functions was through clicking on the canvas, then typing a declaration; drawing connectors would bind members to types, and types to packages.&lt;/p&gt;

&lt;p&gt;Manually laid out nodes cause programs to have &lt;em&gt;shape&lt;/em&gt;, making their structure somewhat memorable.&lt;/p&gt;

&lt;p&gt;In Antegram, I'd only see the currently expanded functions. This approach really helped me with larger programs, and thinking of the signature (not the source) as what should define a function.&lt;/p&gt;

&lt;h1&gt;
  
  
  Antegram 2.3 (2003)
&lt;/h1&gt;

&lt;p&gt;Eventually I wished for more concision in code graphs - what I was after was &lt;em&gt;envisioning&lt;/em&gt; libraries with maybe 1000~2000 program files, and navigating them super fast. &lt;br&gt;
I then opted for non overlapping windows, which would conveniently re-layout when double clicking anything.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faddd0x55gtad3skd5av6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faddd0x55gtad3skd5av6.jpg" alt="Image description" width="378" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other features included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vector icons condensing member modifiers into a visual presentation, but also displaying the relative sizes of packages (give an idea of how much code lives where).&lt;/li&gt;
&lt;li&gt;A playful color scheme, consistently associating with various packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not so surprisingly, the "signatures first, code second" concept was maintained. &lt;/p&gt;

&lt;p&gt;I used Antegram professionally, notably to build a complete POS (point of sale) system with custom networking.&lt;/p&gt;

&lt;p&gt;I continued using Antegram until perhaps 2007 when I joined my first dev team. At that time I not only needed to collaborate - I also switched from Java and C++ to another language. I didn't really mind using Eclipse but I also shared my work with colleagues, one of whom commented that &lt;em&gt;visual representation had taught me software architecture&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Then, there was a long gap in my experiments. I worked in HaXe, Objective-C++, Python and other languages. Switching language often is interesting but does not help maintaining coding tools.&lt;/p&gt;

&lt;h1&gt;
  
  
  Howl (2020)
&lt;/h1&gt;

&lt;p&gt;Around 2020 I had adopted Atom as my choice editor. It did lack detailed outliners, but made it easy (and faster than VS) to put files side by side. I also used much larger screen and I think it's useful to note that Antegram was a delight to use at 1024 x 600 on a netbook.&lt;/p&gt;

&lt;p&gt;I don't find scrolling (or hopping around through searches) productive. Half of my answer to that is LRR (less responsibility principle) - in other words, when a program goes beyond 30-40 lines, I start questioning whether the associate type is doing too much. The other half is ruthlessly concise formatting, and the nail (in the coffin of conventional formatting and code visualization) was the Howl notation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3wkxpcfe6idagnfzber.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3wkxpcfe6idagnfzber.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Howl lets a user type code, and get... Unicode wiggles? I think of the Howl notation as unreading (quickly, more visually parsing) what doesn't matter. User defined keywords (type, functions, variable names) are often left unchanged. Modifiers and other keywords are condensed into single characters. &lt;/p&gt;

&lt;p&gt;Being just a notation, bidirectional conversions are a thing. Howl is compatible with (now defunct) Atom and VS Code. In Atom, a &lt;em&gt;Treesitter&lt;/em&gt; grammar availed syntax coloring.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Throughout the years, I kept an eye on VHCI and its connection to how we think about program code. &lt;/p&gt;

&lt;p&gt;Most approaches to visual editing are code first, which perhaps should be a surprise, as it does not help structuring libraries, and requires separate documentation. &lt;/p&gt;

&lt;p&gt;How about formatting? When working with a team, if we agree on a format I think using a linter is the best (not always practical!). But when I write my own code, I tend to mentally project onto an 80x40 (or 50x40) &lt;em&gt;grid&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Care to share your coding and VHCI journey? If so, welcome to comment!&lt;/p&gt;

</description>
      <category>gratitude</category>
      <category>softwaredevelopment</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I am writing a stateless control language for smart game agents, and you are going to love it</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Wed, 14 Sep 2022 19:24:05 +0000</pubDate>
      <link>https://dev.to/eelstork/i-am-writing-a-stateless-control-language-for-smart-game-agents-and-you-are-going-to-love-it-4gd1</link>
      <guid>https://dev.to/eelstork/i-am-writing-a-stateless-control-language-for-smart-game-agents-and-you-are-going-to-love-it-4gd1</guid>
      <description>&lt;p&gt;Ask game developers how they control their game agents, and they'll probably tell you either of two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If-elses and case logic with control flags/book-keeping; also, event handling, frame updates, co-routines.&lt;/li&gt;
&lt;li&gt;Blueprints or state machines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before going with C# behavior trees, I used to write my game agents this way. Nested case logic in the form of if-elses is not very readable, and it's annoying to debug.&lt;/p&gt;

&lt;p&gt;Control flags add moving parts, and their actual meaning can be obscure because they're often ad-hoc - not to mention that is state which tends to get out of date.&lt;/p&gt;

&lt;p&gt;Events... good in deskop/smartphone applications, or to decouple the UI from the actual game. Not ideal in really dynamic game environments.&lt;/p&gt;

&lt;p&gt;With blueprints and state machines, technical designers are used to these. But this comes with the danger of writing very large control graphs, which quickly get too big for technical designers to even grasp - and regular developers losing hair over entangling the resulting visual spaghetti.&lt;/p&gt;

&lt;p&gt;After using Active Logic for almost three years, I started wanting something that could work as a middle ground for both developers and technical designers. Experience with stateless BTs also provided clear insight into what scripted control should offer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full transparency (execution tree, w. time machine) &lt;/li&gt;
&lt;li&gt;Dynamically debug AND modify the control graph&lt;/li&gt;
&lt;li&gt;Restricted access to the rest of your agent model (use a facade/blackboard) - but with painless, transparent bindings.&lt;/li&gt;
&lt;li&gt;Reusable modules, weakly tied to no particular game/codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all that, Active Logic can't be implemented gracefully in languages other than C#, because of the (shorting) ternary logic supporting stateless BT implementations. So I thought, what if we had an easy to implement and port language, which would 100% focus on the control layer, and prevent the progressive corruption caused by mingling control with other implementation details.&lt;/p&gt;

&lt;p&gt;Moving quickly towards an alpha!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am a BT evangelist, Game AI specialist and tool builder; currently available for work&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gamedev</category>
      <category>unity3d</category>
    </item>
    <item>
      <title>When Unity won't let you in</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Wed, 06 Jul 2022 05:48:55 +0000</pubDate>
      <link>https://dev.to/eelstork/when-unity-wont-let-you-in-5b64</link>
      <guid>https://dev.to/eelstork/when-unity-wont-let-you-in-5b64</guid>
      <description>&lt;p&gt;Sometimes Unity refuses to open, and that's okay... not?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; reimporting your project (sometimes this doesn't even fix the problem) or reverting your VCS changes, or applying any suggested fixes: check &lt;code&gt;Editor.log&lt;/code&gt; under: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;C:\Users\USER_NAME\AppData\Local\Unity\Editor&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;This will help confirming the issue.&lt;/p&gt;

&lt;p&gt;Then, here's a few things you can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try just opening another project, and maybe re-setting the layout?&lt;/li&gt;
&lt;li&gt;Delete your &lt;code&gt;Packages/manifest.json&lt;/code&gt; (backup the manifest so you won't lose track of your custom packages, if any!)&lt;/li&gt;
&lt;li&gt;Delete the &lt;code&gt;/Temp&lt;/code&gt; directory next to &lt;code&gt;/Assets&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Delete the editor layout (see below); sometimes Unity crashes on opening custom asset windows (or just any window trying to load broken data)&lt;/li&gt;
&lt;li&gt;Read a &lt;a href="https://forum.unity.com/threads/can-not-launch-unity-due-to-failed-to-load-window-layout.694450/"&gt;long thread&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;About the editor layout - this is typically saved in several locations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Library\CurrentLayout.dwlt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But also &lt;code&gt;LastLayout.dwlt&lt;/code&gt;, which moves around a bit but seen in these places (search within &lt;code&gt;Editor-5.x!&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Windows &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;%APPDATA%\Unity\Editor-5.x\Layouts\&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%APPDATA%\Unity\Editor-5.x\Preferences\Layouts\default\&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MacOS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/Library/Preferences/Unity/Editor-5.x/Layouts/LastLayout.dwlt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: literally pasting &lt;code&gt;%APPDATA%\Some\Thing&lt;/code&gt; in explorer does work and faster than figuring where that is!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>unity3d</category>
    </item>
    <item>
      <title>Quirky thoughts about developing your dev stamina</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Sun, 03 Apr 2022 11:22:27 +0000</pubDate>
      <link>https://dev.to/eelstork/quirky-thoughts-about-developing-your-dev-stamina-8m5</link>
      <guid>https://dev.to/eelstork/quirky-thoughts-about-developing-your-dev-stamina-8m5</guid>
      <description>&lt;p&gt;How long can you code before exhaustion settles in?&lt;br&gt;
How long before you remember taking a break?&lt;/p&gt;

&lt;p&gt;So we're in the middle of a deadline rush and I can't think of a better time to sit back and consider this.&lt;/p&gt;

&lt;p&gt;Normally, to beat mental exhaustion, I look into relaxation and meditation. Sure, these are worthwhile.&lt;/p&gt;

&lt;p&gt;There's a catch though: these at first sight appear to be the straight opposite of mental training. They're about shutting the brain as much as possible, right? (oversimplifying this, but hang on)&lt;/p&gt;

&lt;p&gt;Would mental &lt;em&gt;training&lt;/em&gt; help?&lt;/p&gt;

&lt;p&gt;The closest may be code gyms. If you haven't tried these little puzzle solving apps (mainly used to train for interviews), giving it a shot is definitely worthwhile.&lt;/p&gt;

&lt;p&gt;Still, I think training for actual performance in actual programming tasks would be... ...different.&lt;/p&gt;

&lt;p&gt;Code gyms are about internalizing logical puzzles and solving them &lt;em&gt;real fast&lt;/em&gt;. They're about doing little brain twisters in limited time, with usually nothing caring that you then get off for the rest of the day (cause job-seeking, hey)&lt;/p&gt;

&lt;p&gt;Training stamina for everyday coding tasks is going to be &lt;em&gt;something else&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Until then, a tip for you!&lt;/p&gt;

&lt;p&gt;Start looking into an issue BEFORE you make a branch for it. This will help you keep rested while working, and also keep your PRs neat. Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start looking into an issue...&lt;/li&gt;
&lt;li&gt;Make a PR&lt;/li&gt;
&lt;li&gt;Run into another, connected issue.&lt;/li&gt;
&lt;li&gt;Start fixing it, all the while not fully focusing on it...&lt;/li&gt;
&lt;li&gt;End up fixing 4 issues, and rolling them into one PR. And, guessed it: feeling mentally wrecked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another cause of brain tiredness in crunch time is because crunch requires keeping mental notes... or doesn't? When the kanban (your Trello, Jira, ...) feels too much, downscale: pull stickies/favorite local notes app (notepad, even) and write things down.&lt;/p&gt;

&lt;p&gt;Stay focused, keep your brain as clutter-free as possible.&lt;/p&gt;

&lt;p&gt;You can do it!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Game AI : Reactive Brains in 5 minutes</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Sat, 17 Jul 2021 13:20:50 +0000</pubDate>
      <link>https://dev.to/eelstork/game-ai-reactive-brains-in-5-minutes-54lb</link>
      <guid>https://dev.to/eelstork/game-ai-reactive-brains-in-5-minutes-54lb</guid>
      <description>&lt;p&gt;A simple and quick recipe I rely on 🍰&lt;/p&gt;

&lt;p&gt;//&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[C]ONTROLLER&lt;/strong&gt; - this is the layer handling (frame by frame) decisions and I usually implement this using a behavior tree so I end up calling this "the behavior tree" or "the BT". &lt;br&gt;
For class names? Well depending on the case could be &lt;code&gt;Enemy&lt;/code&gt; or &lt;code&gt;Gator&lt;/code&gt;; &lt;code&gt;Controller&lt;/code&gt; not bad except it will confuse everyone else.&lt;/p&gt;

&lt;p&gt;Planners a good choice for smarter AIs; these aren't stateless but, it's well understood when you write a planner (path-finding, GOAP, ...) that plans need to be dropped and re-evaluated &lt;em&gt;often&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;↗️ &lt;em&gt;Stateless. flags create moving parts and make debugging harder.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;⚠️ &lt;em&gt;Keep it concise, clear and speedy; if two agents do fairly different things provide separate controllers. Rely on: memory for state, apperception for fast processing and "getting answers" (also: your agents should have a clean API for doing things; if this is not the case, write an &lt;code&gt;Actor&lt;/code&gt; adapter)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;⚠️ &lt;em&gt;There's just a number of AI paradigms/libraries/solutions out there; many of which are&lt;/em&gt; &lt;strong&gt;not&lt;/strong&gt; &lt;em&gt;stateless: many BT implementations aren't and... state machines? Right, not stateless.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;em&gt;If your designer can read the source file.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;//&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[AP]PERCEPTION&lt;/strong&gt; - feeds predigested perception and self-perception data into the controller. If the sensors are simple I implement them here. If apperception is costly, run at a lower frame rate (down to 10 fps or less); frame rate differentials may increase code complexity but not the case here so, low hanging fruit for optimization.&lt;/p&gt;

&lt;p&gt;I just name it &lt;code&gt;Ap&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;↗️ &lt;em&gt;"Predigested" the buzz word: the API exposed to controllers is dead simple and gives the answers decision logic is asking for. An example? Your controller wants to know if the enemy is &lt;code&gt;near&lt;/code&gt;. Five meters isn't near or far.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;⚠️ &lt;em&gt;Multiple AIs with differentiated behaviors: perception/sensor classes are reusable, apperception models not so much.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;//&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[M]EMORY&lt;/strong&gt; - keeping control state outside the controller is great but, where does it go? Do we really need control state (such as with puny flags, cooldowns, timers, action queues, coroutines and event management)?&lt;br&gt;
Even with simple AIs an explicit memory model can be very helpful, roughly matching &lt;a href="https://en.wikipedia.org/wiki/Short-term_memory"&gt;short term memory&lt;/a&gt; and easily implemented with (just a few!) key-value pairs.&lt;/p&gt;

&lt;p&gt;Surely with AIs actually remembering stuff, memory will break down into short term, mid term, semantic/scalar knowledge and so forth but let's focus on the STM today.&lt;/p&gt;

&lt;p&gt;↗️ Small! The primary purpose of STM is to assure behavioral continuity - this has to do with solving &lt;em&gt;technical&lt;/em&gt; problems but continuity, mostly, is a by product of "the environment doesn't change too fast". Here the STM concept is not an analogy. It's a memory structure used to direct your AI "right now" so if you cannot count the number of memorized items on the fingers of two hands - or display it in a tiny window at runtime) - you're storing too much.&lt;/p&gt;

&lt;p&gt;⚠️ Forgetting (aka clearing old state) keeps your AI up to date. Bots hold onto state and have lame bugs - whereas animals and humans just forget stuff.&lt;/p&gt;

&lt;p&gt;🏄‍♀️&lt;/p&gt;

&lt;p&gt;If the above is not too complex this maps to classes. Otherwise I break my AIs into roles (orthogonal to the above so, each role has the C, Ap, M components) or break down responsibilities within each module.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo - Maximalfocus on Unsplash&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>DEV article search woes</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Mon, 25 Jan 2021 12:01:13 +0000</pubDate>
      <link>https://dev.to/eelstork/dev-article-search-woes-5gk6</link>
      <guid>https://dev.to/eelstork/dev-article-search-woes-5gk6</guid>
      <description>&lt;p&gt;What does everybody think of the search feature on DEV? It's happened a few times I find an article I like in my mail digest or feed, then searching only popular articles (not the exact match I want) matching hip keywords come up.&lt;/p&gt;

&lt;p&gt;Trend with online search that literal searches get ditched in favor of "hey why don't you check out this popular thing instead" - kinda frustrating in my opinion.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Computer Programming - A Rough Guide</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Sun, 27 Dec 2020 02:33:11 +0000</pubDate>
      <link>https://dev.to/eelstork/computer-programming-a-rough-guide-5dh1</link>
      <guid>https://dev.to/eelstork/computer-programming-a-rough-guide-5dh1</guid>
      <description>&lt;p&gt;&lt;em&gt;A rough guide intended for absolute beginners who want a quick overview of what learning programming leads to, and the kind of skills that are useful to programmers.&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Styles of programming
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Back-End&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Work with servers and databases. By definition this is non graphic, and also gives perhaps the widest choice of languages and tech, since installation woes and cross platform support are not an issue.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Languages: Java, PHP, PERL, SQL, Go, Python&lt;/li&gt;
&lt;li&gt;Related: Cloud solutions (AWS, Azure), Docker, Serverless, Node.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mobile&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Program forward looking hardware (accelerometers, multi-touch, AI chips, styluses) and overall spearheading innovation in software design and interaction. Most apps simply don't leverage these features but even then, a hugely dynamic market and startup space.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Languages: Swift (iOS) and Java (Android)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Game Development and VR/AR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern game dev is mostly through standalone game engines managing the gritty details such as high quality graphics and scene management; still perhaps 30% of high profile video games (ex mobile) use proprietary game engines.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Languages: C#, C++&lt;/li&gt;
&lt;li&gt;Related: Unity, Unreal, Godot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Web apps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Though using only a small subset of programming languages, web apps may still account for most advertised coding jobs. High visibility, dynamic community.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Languages: HTML, CSS, JavaScript, TypeScript&lt;/li&gt;
&lt;li&gt;Related: React, AWS, Azure, Firebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Desktop apps and systems programming&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Easier languages (Java, C#) are used for business apps, whereas "systems languages" (C, C++, Rust) are used in programming operating systems, IoT things and high performance apps such as game engines and machine learning libraries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Common languages: C#, Swift, Java, C, C++, Rust&lt;/li&gt;
&lt;li&gt;Related: Visual Studio, XCode, Eclipse&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Shell-scripting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every programmer end up with a little knowledge of so called command line tools - aka shellscripting - which are used to perform simple operations (such as compressing or copying files) and automate programming workflows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Languages: Bash, Powershell&lt;/li&gt;
&lt;li&gt;Related: Linux, Docker&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The best platform/language to start with?
&lt;/h2&gt;

&lt;p&gt;Perhaps Python, Javascript, Processing, C or C#&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt; falls in the "easy to learn, hard to master" category. A neat feature is the so called interactive console, which allows typing commands and directly evaluate the result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Javascript&lt;/strong&gt; is easy as a language; every programmer know some javascript too (because, what programmer did not setup their own web page at least once?)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Processing&lt;/strong&gt; is a multimedia platform derived from Java. Where most languages easily output text, processing is adept at producing graphics and sounds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unity&lt;/strong&gt; uses standard C# and provides a comfy environment for playing with 3D, physics and multi-agent systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C&lt;/strong&gt; is recommended before learning C++ or Rust. Learning C means a better understanding of memory and performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arduino&lt;/strong&gt; is (perhaps) a bit limited on the coding side but a great place to start if you are interested in both programming and electronics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to try languages?
&lt;/h2&gt;

&lt;p&gt;Sometimes the language is available on your system, or some installation/configuration is needed.&lt;/p&gt;

&lt;p&gt;Online IDEs are a great resource for a quick dip into (almost) any language:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ideone.com"&gt;https://ideone.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tutorialspoint.com/codingground.htm"&gt;https://www.tutorialspoint.com/codingground.htm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are the important skills in programming?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Attention to detail&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On a day to day basis, programming is a petty activity where 'a slip of tongue' is not okay - since computers do not understand saying "approximately" the right thing.&lt;br&gt;
Practice makes perfect, and for most of us patience is key to overcoming the initial "missing colon, mismatched bracket" phase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstract thinking, and staying organized&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Programs are models so the ability to think categorically and organize ideas really helps; &lt;strong&gt;leads to&lt;/strong&gt;: Software/solutions architect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Information gathering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While languages and programming patterns stick around for decades, libraries, frameworks and the hardware evolve &lt;em&gt;quickly&lt;/em&gt; - fast enough that beyond a few commonly used functions, learning keywords and commands is pointless.&lt;/p&gt;

&lt;p&gt;What works is knowing how to search - which comes with reading about programming and acquiring the culture/jargon needed to ask questions other programmers can even answer. &lt;strong&gt;Leads to&lt;/strong&gt;: technologist, CTO&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team spirit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After you overcome the "what" of getting programs to work, you are primed to learning how to write programs that other developers can read and enjoy contributing to. Good teamworkers understand that programs are written for humans to read, and 80% of a coder's working time is spent reading and analyzing existing code.&lt;br&gt;
&lt;strong&gt;Leads to&lt;/strong&gt;: team lead&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Puzzle solving&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Often programming requires an understanding of &lt;em&gt;algorithms&lt;/em&gt; which are methods to solve (apparently) simple problems such as sorting lists or finding contours in an image. Still you need not be very good at logic or maths to be a good programmer. &lt;strong&gt;Leads to&lt;/strong&gt;: computer scientist, data scientist, working for the big four, hacking and security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I learn more than one language?
&lt;/h2&gt;

&lt;p&gt;Sooner or later, you will. Fortunately computer languages look like each other. Learning a "first programming language" is the one big step.&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
    <item>
      <title>🔥 dotnet add package ActiveLogic</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Sat, 28 Nov 2020 17:52:47 +0000</pubDate>
      <link>https://dev.to/eelstork/dotnet-add-package-activelogic-3ia</link>
      <guid>https://dev.to/eelstork/dotnet-add-package-activelogic-3ia</guid>
      <description>&lt;p&gt;Active Logic (AL) is now available as a nuget package, yay.&lt;/p&gt;

&lt;p&gt;Was having a look wondering how to explain this neat library to developers on dev.to. Specifically I got to thinking okay, how would we do an &lt;a href="https://docs.microsoft.com/en-us/dotnet/framework/network-programming/making-asynchronous-requests"&gt;async web request&lt;/a&gt; in AL?&lt;/p&gt;

&lt;p&gt;Perhaps something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"URL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll have another look to make sure this isn't off by a mile (I mean, yea sure, now that we have a nuget package I should probably make a sample app). &lt;/p&gt;

&lt;p&gt;What the above &lt;em&gt;does not&lt;/em&gt; get wrong, is how AL does async without callbacks.  &lt;/p&gt;

&lt;p&gt;〜 Going to call it a Sunday. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;You may also find AL &lt;a href="https://github.com/active-logic/activelogic-cs"&gt;on Github&lt;/a&gt; and it isn't really a new thing either. I see an initial commit in July 2019, which probably was migrated/squashed from an incubator. Got 100% coverage on November 23rd (2020), which felt... anticlimactic?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have my cake, and eat it 🎂&lt;/p&gt;

&lt;p&gt;Image: &lt;em&gt;Arecibo Observatory (from Wikipedia)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>productivity</category>
    </item>
    <item>
      <title>SOLID 20 years on: &gt;S  single, or limited responsibility? (1/5)</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Fri, 20 Nov 2020 18:23:03 +0000</pubDate>
      <link>https://dev.to/eelstork/solid-20-years-on-s-single-or-limited-responsibility-1-5-11nd</link>
      <guid>https://dev.to/eelstork/solid-20-years-on-s-single-or-limited-responsibility-1-5-11nd</guid>
      <description>&lt;p&gt;&lt;em&gt;S.O.L.I.D is/are among the most quoted software design principles; compelling enough that you want to apply them, yet flexible enough that they're open to some interpretation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Today - &lt;a href="https://dev.to/sabrinasuarezarrieta/why-apply-solid-principles-make-your-code-quality-match-iso-standard-25010-65g"&gt;in reply to Sabrina Suarez&lt;/a&gt;, starts with Ⓢ&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Single Responsibility
&lt;/h1&gt;

&lt;p&gt;At once one of the most actionable and perhaps also one of the fuzziest principles in SOLID.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Actionable&lt;/em&gt; because many developers keep adding functionality to existing classes. Hilariously at my first job we had a rule that, when a class is over 1kloc, it is time to break it down. Wait, what? &lt;/p&gt;

&lt;p&gt;Do have a look at the Rust compiler source. Or .NET reference implementations. Over 1kloc is actually not rare.&lt;/p&gt;

&lt;p&gt;Point being much software can be improved/redesigned by trying to make classes smaller.&lt;/p&gt;

&lt;p&gt;Meanwhile another question is: where does it stop? &lt;/p&gt;

&lt;p&gt;At... ONE? &lt;/p&gt;

&lt;p&gt;&lt;em&gt;1&lt;/em&gt; single, unique, indivisible responsibility and, erm, how do you even define this?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A single part&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.educative.io/edpresso/what-are-the-solid-principles-in-java?utm_source=Google%20AdWords&amp;amp;aid=5082902844932096&amp;amp;utm_medium=cpc&amp;amp;utm_campaign=kb-dynamic-edpresso&amp;amp;gclid=CjwKCAiA7939BRBMEiwA-hX5Jy7wOcWS6su-V0G1Bk9H8OavgpJ1AJxCfcmRCLPvUbgQ3rsOvf0wvRoC74gQAvD_BwE"&gt;Seriously, guys&lt;/a&gt;, what am I supposed to make out of this? A module is a single part. A function is a single part. What are we designing? Apple Pie? No thanks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One reason to change&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that's an interesting take (and perhaps Martin's word on this?); at the same time it is still extremely vague and, in this form not consistently actionable.&lt;/p&gt;

&lt;p&gt;The crux here, is it doesn't really make sense for a class to have "only one job" - or rather it perhaps makes more sense from an implementation than from an API design point of view.&lt;/p&gt;

&lt;p&gt;A good class name is a &lt;em&gt;noun&lt;/em&gt;; A noun refers to a thing/metaphor. In terms of mechanistic decomposition of how stuff works, being able to atomize a complex thing into nameable parts is great. In terms of a thing being useful. Well. &lt;/p&gt;

&lt;p&gt;One example that comes to mind is the &lt;code&gt;String&lt;/code&gt; class (any string class, whatever language). String is always good and bad. It does too many and too few things. It definitely has too many responsibilities, and that is true from the point of using/abusing strings, and of course from a specification/API point of view.&lt;/p&gt;

&lt;p&gt;No strings then?&lt;/p&gt;

&lt;h1&gt;
  
  
  Limited Responsibility
&lt;/h1&gt;

&lt;p&gt;Perhaps disappointingly, I don't have a definite answer here to how 'single responsibility' optimally applies. Soberly and pragmatically, I use a &lt;em&gt;limited responsibility principle&lt;/em&gt; which is a dumb thing best embodied into the 35x70 rule.&lt;/p&gt;

&lt;p&gt;Meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;70 characters long&lt;/li&gt;
&lt;li&gt;35 (physical) lines of code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;"So this is about physical (not logical) design?"&lt;/em&gt; - That's right, and yet it does impact logical design, in a way that keeps software clear and &lt;em&gt;sufficiently&lt;/em&gt; modular.&lt;/p&gt;

&lt;p&gt;There is not much discussion/time wasted filtering LR principle violations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under 35 loc: whatever, fine.&lt;/li&gt;
&lt;li&gt;35~70: danger zone&lt;/li&gt;
&lt;li&gt;100+: all hands on deck&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Oh not so) incidentally, a 35x70 characters matrix fits a half screen on a 12” laptop.&lt;/p&gt;

&lt;p&gt;🔥 🐽 🔥&lt;/p&gt;

&lt;p&gt;Works for me, as I indulge tiny laptops. And of course it'll be working for you too, because your laptop is either the same, or larger.&lt;/p&gt;

&lt;p&gt;Adopting the 35x70 rules, I feel extremely confident that other developers will appreciate my code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each class is self-contained. &lt;/li&gt;
&lt;li&gt;Not that small that you need to hop anywhere else to learn something about how the software works.&lt;/li&gt;
&lt;li&gt;Also not so big you'd have to thumb/scroll around to figure things out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bonus: at a half screen's worth, there is &lt;em&gt;space&lt;/em&gt; in here for &lt;em&gt;you&lt;/em&gt; to compare, analyze and, of course, &lt;em&gt;extend&lt;/em&gt; the software.&lt;/p&gt;

&lt;p&gt;This isn't a thing you can flip on its head. In other words, don't ever try to &lt;em&gt;impose&lt;/em&gt; the 35x70 rules. Because, you know, it is, well... arbitrary, and illogical?&lt;/p&gt;

&lt;p&gt;Which brings us to the logical aspect of it: unless you are using &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods"&gt;partials&lt;/a&gt; (sometimes I do, although mainly as a business tool 🍉 ) there is only &lt;em&gt;so much&lt;/em&gt; responsibility you can inflict on a class fitting 35 loc.&lt;/p&gt;

&lt;p&gt;All said and done. Malfeasance will spoil any good principle, and I shall demonstrate this here and now by picking a 35 loc long class from my personal reserve.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⊐ Ex = System.Exception;
⊐ UnityEngine; ⊐̥ UnityEngine.Time; ⊐̥ UnityEngine.Mathf;
⊐ Active.Core; ⊐̥ Active.Core.status;

⊓ Activ.Kabuki{ ‒ ○ Locomotion{

    ‒ ⑂ MoveTo(エ x, メ y, ㅅ speed){
        ⤴ (x˙ ☰ y) ◇̠
        ㅅ d = x.PlanarDist(y), δ = 𝛿𝚝 ᐧ 𝝇;
        ⮐ (δ &amp;gt; d) ? Do( x˙ = y) : Move(x, x.PlanarDir(y), δ, d);
    }

    ‒ ⑂ MoveTowards(エ x, メ y, ㅅ dist, ㅅ speed){
        ㅅ d = x.PlanarDist(y);
        ⮐  (d &amp;lt; dist) ∨ Move(x, x.PlanarDir(y), 𝛿𝚝 ᐧ 𝝇, d);
    }

    ‒ ⑂ MoveTowards(エ x, エ y, ㅅ dist, ㅅ speed){
        ㅅ d = x.PlanarDist(y);
        ⮐  (d &amp;lt; dist) ∨ Move(x, x.PlanarDir(y), 𝛿𝚝 ᐧ 𝝇, d);
    }

    // -------------------------------------------------------

    ⑂ Move(エ み, シ u, ㅅ δ, ㅅ los){
        シ? v = Avoidance.Clear(み˙, u, maxDistance: los);
        ⤴ (v ☰ ∅) ⮐ ■;
        み.⫫ = シ.Lerp(み.⫫, vᖾ, 0.1f);
        ⮐ Run(み˙ += vᖾ ᐧ δ);
    }

    ∘ ⑂ Do(⊡ x) { ⌽ } ∘ ⑂ Run(⊡ x) { ☡̱ }

}}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For practical purposes I make devious allowances to cram functionality in a 35x70 frames. Once I exceed this quota I let the kite fly to 100loc, and when that hits, unless it's a Swiss army styled collection of utilities, I refactor.&lt;/p&gt;

&lt;p&gt;🦖 &lt;code&gt;this&lt;/code&gt; is &lt;a href="https://github.com/active-logic/howl"&gt;Howl&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(image: my 'Shizen' project)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>architecture</category>
      <category>usability</category>
      <category>devrel</category>
    </item>
    <item>
      <title>Bracket Patterns in C# - P.1</title>
      <dc:creator>Tea</dc:creator>
      <pubDate>Fri, 20 Nov 2020 09:47:02 +0000</pubDate>
      <link>https://dev.to/eelstork/bracket-patterns-in-c-p-1-fac</link>
      <guid>https://dev.to/eelstork/bracket-patterns-in-c-p-1-fac</guid>
      <description>&lt;p&gt;&lt;em&gt;Perhaps a month ago, I teased a coming post about bracket/delimiter/begin-end patterns in C#...&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What is a bracket pattern?
&lt;/h1&gt;

&lt;p&gt;If you have used OpenGL, you may remember code looking like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;glBegin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GL_QUADS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;glColor3f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;glVertex2f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="n"&gt;glEnd&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These patterns are not uncommon and they are, well - error prone. Ever accidentally left your front door open? That is how goes with pairing commands as above.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bracket patterns in C-sharp
&lt;/h1&gt;

&lt;p&gt;In C# you may leverage &lt;code&gt;using&lt;/code&gt; and &lt;code&gt;IDisposable&lt;/code&gt;. However this is on the heavy side, primarily for safely managing resources.&lt;/p&gt;

&lt;p&gt;I review lightweight alternatives - looking at increasingly more powerful variants.&lt;/p&gt;

&lt;h2&gt;
  
  
  The basics
&lt;/h2&gt;

&lt;p&gt;In the simplest case, we want a pattern &lt;em&gt;equivalent&lt;/em&gt; to...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;Begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;DoSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;End&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A basic bracket pattern, then, is implemented as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;With&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;End&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;End&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enabling the following use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;With&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;DoSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returning the &lt;code&gt;With&lt;/code&gt; function as a property allows running code both &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; running the enclosed command.&lt;/p&gt;

&lt;p&gt;One use case is with functional graphic APIs (such as OpenGL, and others...); Unity, for instance, provides the following API(*):&lt;/p&gt;

&lt;p&gt;(*) &lt;em&gt;In places they now use &lt;code&gt;IDisposable&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;BeginHorizontalGroup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;EndHorizontalGroup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which then becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;HorizontalGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the pattern implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GUI&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;With&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;BeginHorizontalGroup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;End&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;End&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;EndHorizontalGroup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see we are not doing any with the argument - our purpose here is only 'framing' the &lt;code&gt;Label()&lt;/code&gt; command. Which brings us to the one constraint these patterns are sharing: &lt;code&gt;Label()&lt;/code&gt; (and likewise framed commands) cannot return &lt;code&gt;void&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Although I did use a &lt;code&gt;static&lt;/code&gt; class this is not required; so, assuming the target API does not use globals either, thread safety may be preserved.&lt;/p&gt;

&lt;p&gt;A common use case for bracket patterns is when building hierarchies and this may help designing articulate alternatives to the builder pattern.&lt;/p&gt;

&lt;p&gt;In its most simple form the bracket pattern only supports one argument. What if (as makes sense with a horizontal group) we wanted to combine several commands? Then, use a &lt;em&gt;delegate&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;EndFunc&lt;/span&gt; &lt;span class="n"&gt;With&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;End&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EndFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;params&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;End&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;params&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason we need a delegate here is var-args (&lt;code&gt;...&lt;/code&gt;) are not supported by any variant of &lt;code&gt;System.Func&amp;lt;...&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Back to the 'horizontal group' example, the above then enables the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;HorizontalGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
    &lt;span class="nf"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tap to enter"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you go back to the OpenGL example, note how the &lt;code&gt;glBegin(GL_QUADS)&lt;/code&gt; function allowed arguments. In the next session I'll be looking at a handy variant which cleanly separates arguments to the &lt;code&gt;begin&lt;/code&gt; function from the enclosed items. &lt;/p&gt;

&lt;p&gt;Var-arg forms allocate memory; often the impact is negligible; when it's not there is an alternative, and I'll also review this in my next posting.&lt;/p&gt;

&lt;p&gt;Happy Coding ~ &lt;/p&gt;

&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@dancristianp?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Dan-Cristian Pădureț&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/bracket?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>patterns</category>
    </item>
  </channel>
</rss>
