That last "micro"blog was a doozy. Maybe I don't need to add a "real" blog engine after all.
Since this is my site, the character counter is just a suggestion, after all. Hmm.
One issue that I've had since the beginning was "How do I represent the different item types (book, game, project) in a strongly typed way while also reducing the amount of boilerplate I need?"
In C#, I'd just make some interfaces and an object hierarchy and call it a day. And while one can do that in F#, it's against the spirit of what I'm trying to learn.
I went down a few paths (including some pretty
gnarly heroic reflection code, immortalized in this "delete all the old code" commit) but nothing ever really felt right. I ultimately just ended up copy-pasting a bunch of the same code into
Project.fs and moved on.
I've slowly been solving this, starting a couple weeks ago when I added some discriminated unions to represent each type (in this commit). That ended up with a lot of similar code in pattern matching blocks, but I felt okay about it because the compiler was going to help me out by noticing missed patterns.
Then, last weekend, I watched a talk from Mads Torgersen on "The functional journey of C#". He made a point that a big difference between OO and functional programming is that OO lets you put new behaviors in one place (encapsulated in the base class, perhaps) while functional programming makes you spread it out all over the place and duplicate things in each function. But the functional approach is more extensible since all the behavior is out in the open.
He said it better. Go watch the talk.
Anyway, I've taken that to heart and done a great big refactor today.
Before, I really wanted to be able to have a list of, like,
FormField<'t> to support things like
This is fine as far as it goes but:
- You can't put those in the same list because they're all different types
- You can't pattern match over the generic type so it's hard to do things with them
This wouldn't have been so bad in C#. I'd just have a non-generic
FormField interface or something. I don't know. But in F#, it's kind of a drag.
So I embraced what Mads was saying about duplicating behaviors as needed. I now have a new "FormField" concept where each FormField is a discriminated union of everything that a form field could ever be.
I wrapped up a bunch of pattern matched functions to do things with these and it's kind of annoying but really not that bad. The compiler and tooling helps a lot here.
I'm pretty pleased with it.
I know this is far from perfect and not what an F# master would write.
But I think this is a solid improvement and shows how much I'm growing into this new-to-me language and paradigm.
I can only imagine six months from now when all of this seems really gross to me and I have much better ways to accomplish all of it.
I can't wait.
Today's the day.
I've spent the week polishing all the rough edges I could find.
I've got a commit ready to go to change the index route from "Under Construction" to...well...this.
I still want to write up something to put on social media to tell people about it (I am kind of proud of how this has turned out!) and then I can push that commit.
Not sure if the first post-launch feature will need to be a no-context microblogging feature (possibly published to twitter) or a real blogging engine. Either way: do I actually have worth saying?
I've created a colophon. The site is feature complete! I'm not happy with the copy at all, though. So I need to spend a few days thinking about the writing. But I'll probably launch next weekend! Exciting stuff.
Added visible tags and individual item pages today. v1 of the site is nearly complete (indeed, I almost thought it was done until I remembered...) except for the colophon.
One more static page and then I'll just need to look at it very hard before making any small tweaks and going live.
I can't believe it's almost finished!
I got the "list" pages working under the "What am I...?" buttons in the sidebar. I am so excited about it. It looks so good.
Things are really coming together over here and I am starting to feel pretty proud of how it's turning out.
The front page now has dynamic microblogs (like this one!) on it.
I'm still debating if I'm going to support markdown in these or not. The time to make that decision one way or another is fast approaching.
The project code is also really starting to get away from me: a lot of that is to be expected since I'm learning F# as I go, but it might be time for a major cleanup refactor soon. I just need to learn more about what that should look like.
I've now got all of the static content on the main "About" page laid out in a responsive fashion. Will start working on the dynamic stuff next time.
It's looking good! I'm almost tempted to disable links to pages that don't exist yet and put this up instead of my "under construction" banner.
I started working on the user-facing site today! I've got the main layout built out and it's responsive and everything. One day, you may even see this very message in that layout! Exciting stuff.
I've put some real data into the backend so I'll actually have something to look at when I start styling the frontend. Probably next weekend. We'll see.
Today, I am "feature complete" for the backend: which has allowed me to write this, the inaugural microblog in the production database.
Next up, it's all about presenting the data in a pleasant frontend!