~inferiormartin/mrtn.run

30fcf74c8f62a47b7e40c1bbbc4e57a9b7cd9419 — Maarten Vos 18 days ago
initial commit

- status update, july 2022
- complexity hunt
A  => .build.yml +13 -0
@@ 1,13 @@
image: alpine/latest
packages: 
  - hugo
oauth: pages.sr.ht/PAGES:RW
environment:
  site: mrtn.run
tasks:
  - package: |
      cd $site
      hugo
      tar -C public -cvz . > ../site.tar.gz
  - upload: |
      acurl -f https://pages.sr.ht/publish/$site -Fcontent=@site.tar.gz

A  => .gitignore +2 -0
@@ 1,2 @@
public/
.hugo_build.lock

A  => archetypes/default.md +6 -0
@@ 1,6 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---


A  => config.toml +6 -0
@@ 1,6 @@
baseURL = "https://mrtn.run"
languageCode = "en-us"
title = "Maarten Vos's Blog"

[permalinks]
blog = "/:year/:month/:day/:filename"

A  => content/blog/Complexity-hunt.md +70 -0
@@ 1,70 @@
---
title: "Complexity hunt"
date: 2022-07-30T17:56:42+02:00
---

Programming languages are getting too complex for their own good. Not only is it
difficult to remember every new feature of your programming language, previously
written code also starts to look unidiomatic. But that's not the worst of it.
When you start to rely on these new fancy features, you are hiding important
details of your code. Or, in the following case, introduces a bug you have to
actively hunt for.

```C#
public override Stream OnGetStream(GetStreamArgs e)
{
    var stream = new MemoryStream();
    
    using var zip = new ZipArchive(stream, ZipArchiveMode.Create, true);

    stream.Position = 0;
    
    return stream;
}
```

Take the previous code block for example, this is complete valid C# and there
doesn't appear to be anything wrong with it. It uses the new using syntax
introduced in C# 8. However, if you were to run this code, you would notice that
what you get back is an empty archive at best, or an invalid one at worst. Why
is that you may ask? Well, the answers lays in how the ZipArchive class works.
The ZipArchive class only writes its data to the underlying stream once it has
been disposed. You may think, but that's what the using statement does, and you
would be right. However, the new using syntax comes with a caveat. It brings
your variable into the scope of the method.

The using statement wraps your code into a try-finally block, where the object is diposed.
However, this happens at the end of the scope, i.e the method.
Before that happens, we reset the stream's position so that it can be read, but disposing of our ZipArchive moves the Position ahead for more writing. If you remember how the ZipArchive class works, it only writes its data to the underlying stream
once its been disposed. What you get is code that looks perfectly fine, but is
broken because some fancy new syntax doesn't behave how you would expect it
would (disposing right after the object was last used). I spent my morning at work figuring this out and while it wasn't
particularly difficult, it took time that I could have spent on more important
issues.

```C#
public override Stream OnGetStream(GetStreamArgs e)
{
    var stream = new MemoryStream();
    
    using (var zip = new ZipArchive(stream, ZipArchiveMode.Create, true))
    {
    }

    // Or you could do this.
    //zip.Dispose();

    stream.Position = 0;
    
    return stream;
}
```

As you can see in the code above, the issue is solved easily. You use the old
syntax, which introduces a new scope and ensures that the object is disposed
before setting the stream's position to 0, or you dispose it manually. I prefer using the old
syntax since it introduces that new scope, making the code easier to
follow since it's clear where the ZipArchive is disposed.

With that, my hunt for complexity comes to an end...... until history repeats
itself. Happy hunting!

A  => content/blog/Status-update-July-2022.md +49 -0
@@ 1,49 @@
---
title: "Status update, July 2022"
date: 2022-07-30T17:20:11+02:00
---

Hello there! How long has it been, a year? Before I get into what I did for the
month of July, I wanted to quickly explain what's going on here. I started
this blog the 8th of May, 2021. I picked a simple theme that I didn't hate and
wrote 2 blog posts, both unrelated to technology. I'd like to think that I've
grown in that year and that I'm now ready to write some things that I'm actually
interested in. With that out of the way, here's what I did this month:

I started working on [shishutsu][1], which is a web application for categorizing your spending habits.
Okay, it's a web application for categorizing *my* spending habits. I wanted to develop
something that I need myself, and it's been really fun so far! It's being
written in Go because go has an excellent built-in http server and great
templating support. It's also fast and does not require a virtual machine like
.NET or Java does. I've implemented a couple of things, such as sign-ins and
importing transaction data[^1], but not the core feature of actually
categorizing your statements. But, that's because I've been so busy working on
some other things like-

Badger! Badger is a framework, also written in Go, for easily writing web
applications that require data manipulation, usually coming from a
database. You give it your database tables and it handles everything for you. It
generates pages for your queries, forms for creating or editing data and allows for
lots of customization on top of that. It features zero javascript and is all
rendered server-side using Go's html/template package. I wish I could give you a
snippet showing what is required to get a badger application going, but so much
has still to be done, and even more is going to change. Showing it in its
current state would just be dishonest. I will make a blog post when it
eventually becomes public, so stay tuned for that!

As this status update is coming to a close, there is only one thing left to talk
about. This blog! I rewrote it from scratch without using an existing theme. You
may notice though that it isn't entirely unique. I did copy the style from [Drew
Devault's Blog][2] for a simple reason. I really like the style of it. It's
simple without too much fuss and is generally easy on the eyes. I did however
add dark mode, which automatically changes depending on your browser's
preference. I stole some text that read well,
such as the footer and comment section on blog posts, hopefully he doesn't mind. I didn't see any reason to change what wasn't broken, and so here we are. I hope you enjoyed reading one of
hopefully many status updates to come, and with that, until next time!

[1]: https://git.sr.ht/~inferiormartin/shishutsu
[2]: https://drewdevault.com

[^1]: Sadly, my bank does support have a publicly available API. I have to
  export CSV files, and while I like CSV, I have to do it via their very slow
  web interface.

A  => layouts/blog/single.html +35 -0
@@ 1,35 @@
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{ .Title }}</title>
        <link rel="stylesheet" href="/style.css"> 
    </head>
    <body>
        <main>
            <h2>{{ .Title }}</h2>
            <h3>{{ .Date.Format "January 2, 2006" }} on <a href="{{ .Site.BaseURL }}">{{ .Site.Title }}</a></h3>
            <div id="blog-post">
                <article>
                    {{ .Content }}
                </article>
            </div>
        </main>

        <section id="comment">
            <p>Have a comment on one of my posts? Start a discussion in <a
                href="https://lists.sr.ht/~inferiormartin/public-inbox">my
                public inbox</a> by sending an email to <a
                                                                href="mailto:~inferiormartin/public-inbox@lists.sr.ht">~inferiormartin/public-inbox@lists.sr.ht</a>
            [<a href="https://man.sr.ht/lists.sr.ht/etiquette.md">mailing list
                etiquette</a>]</p>
        </section>

        <footer>
            <span>The content for this site is <a
                    href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>.</span>
            <span>The <a href="https://git.sr.ht/~inferiormartin/mrtn.run">code for this site</a> is <a href="https://opensource.org/licenses/MIT">MIT</a>.</span>
        </footer>
    </body>
</html>

A  => layouts/index.html +39 -0
@@ 1,39 @@
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{ .Title }}</title>
        <link rel="stylesheet" href="/style.css"> 
    </head>
    <body>
        <main id="index">
            <section class="articles">
                <h1 id="index">{{ .Title }}</h1>
                {{ range (where .Site.RegularPages "Section" "blog") }}
                <article id="index">
                    <span>{{ .Date.Format "January 2, 2006" }}</span>
                    <br>
                    <a href="{{ .Permalink }}">{{ .Title }}</a>
                </article>
                {{ end }}
            </section>
            <aside>
                <img class="avatar" src="/avatar.jpg">
                <dl>
                    <dt>email</dt>
                    <dd><a href="mailto:maarten@mrtn.run">maarten@mrtn.run</a></dd>
                    <dt>sourcehut</dt>
                    <dd><a href="https://sr.ht/~inferiormartin">~inferiormartin</a></dd>
                </dl>
            </aside>
        </main>
        <footer>
            <span>The content for this site is <a
                href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA<a/>.</span>
            <span>The <a href="https://git.sr.ht/~inferiormartin/mrtn.run">code
                    for this site</a> is <a
                    href="https://opensource.org/licenses/MIT">MIT</a>.</span>
        </footer>
    </body>
</html>

A  => static/avatar.jpg +0 -0
A  => static/style.css +92 -0
@@ 1,92 @@
* {
    font-family: sans-serif; 
}

* :not(p) {
    padding: 0;
    margin: 0;
}

h1#index {
    margin-bottom: 25px;
}

h3 {
    margin-bottom: 25px;
}

#blog-post {
    padding-left: 100px;
    padding-right: 100px;
    text-align: left;
}

#comment {
    padding-left: 50px;
    padding-right: 50px;
    margin-top: 25px;
    margin-bottom: 25px;
}

body {
    max-width: 920px;
    margin: 0 auto;
    padding: 1rem;
}

main#index {
    display: flex;
    justify-content: space-between;
}

article#index {
    margin-bottom: 10px;
}

dl, dd {
    margin-bottom: 10px;
}

dl {
    display: grid;
    grid-template-columns: max-content auto;
}

dt {
    font-weight: bold;
    margin-right: 20px;
}

.avatar {
    display: block;
    margin-left: auto;
    margin-right: auto;
    width: 50%;
    border-radius: 5%;
    margin-bottom: 25px;

    height: auto;
    width: auto;
    max-width: 150px;
    max-height: 150px;
}

footer {
    text-align: center;
}

@media (prefers-color-scheme: dark) {
    body {
        background: #080808;
        color: white;
    }

    a:link {
        color: #ADD8E6;
    }

    a:visited {
        color: #CBC3E3;
    }

}