Friday, March 29, 2024

Squaresoft Died with Final Fantasy X

This post contains John Wick and Star Wars spoilers.

The Playstation 2 marked the end of Squaresoft's reign of glory. This is because they made the decision to feature voice acting in Final Fantasy X, while not supporting the PC platform. They stayed confined to a console box.

If you look at The Longest Journey, an RPG with voice acting, it was on the PC. I've never played this game (for a meaningful amount of time) but it did catch my interest as an onlooker. The game features voice acting and it's a PC game. It is, to me, of the same era as Final Fantasy X. And it feels remarkably different than Final Fantasy X does. Final Fantasy X feels like it's in a cage compared to The Longest Journey.

Final Fantasy X as an RPG hits the notes it's supposed to hit, judging by the number of people I've encountered who say it's a good game. Its battle system is fine. Its story is fine. Its music is fine. But it's in a cage on the PS2. I'm aware that it has more recently been ported to the PC. That's way too little too late to save the Squaresoft brand. AFAIK they went entirely through FF XIII without porting FFX to the PC.

This brings me to Final Fantasy XIV. It is just a generic MMO. It is the best chance that Square Enix has ever had at recapturing my respect, and it fails. It has nothing innovative to offer to compensate for the damage Final Fantasy X did. It is the best product that Square Enix has had since those old days, and it fails. I can't even try to see whether New World outranks it because they're both lame and generic. They feel like they're just checking off boxes, whereas World of Warcraft still sits on firm footing.

John Wick 3 killed its franchise. The plot twist of John having to go after Winston is critically in aristic error. I never purchased John Wick 4 after that.

The Force Awakens was picking up a story that was of the highest order. Its storytelling was way beyond what World of Warcraft tries to do. WoW's story is like a soap opera and it is up front with you about that. The gameplay is left to make up for this (and it does). And the story is kept fun.

Episodes 1-6 of Star Wars define a single saga, culminating in Luke Skywalker's ascension over his insecurities and enemy in the form of Darth Vader. It is inappropriate for him to be an overthrown recluse in The Force Awakens. It is inappropraite for Han Solo to be rewarded for his adventure with Luke by being murdered in The Force Awakens. I never bothered with episodes 8 and 9.

Tuesday, March 26, 2024

Programming on an iPad

I am launching a Java web app. It is 14k lines large. 45% of that I wrote using a 2024 12-inch iPad Pro.

You can't compile Java code on an iPad. You don't even have direct access to a hard drive. One of the first realizations I had when I decided to go down this road was that I would have to rent a server in the cloud just to do development on it. I could install openjdk on it and compile my source code there.

The next big decision you have to make is how to inform your remote cloud machine of the latest keystrokes you've typed to move around characters in a source code file. I read a guide that said that typing in things using an iOS text editor was fundementally too frustrating, and that one should use a web-based text editor that sits in front of your cloud machine. I did not reach this conclusion in my research and approach.

What I did was go ahead and choose Textastic as my text editor. As its accomplice, I chose ShellFish. What ShellFish does is allow you to enter SSH information into it, and it'll sync files via SFTP from your remote cloud filesystem into the Files iPad OS app. Textastic integrates with ShellFish, so you can open files that ShellFish knows about with the Textastic open file dialog. ShellFish was like $30 for a lifetime license. With it and Textastic, you can edit files on your remote cloud machine. Every time you save, your changes get pushed into your cloud machine.

ShellFish also provides support for moving files you download in Chrome directly into your cloud machine. It does this through the "Share" generic function that shows up when you're looking at different things on iOS. This was very handy when it came time to download my SSL certificate and key.

I think Textastic was $10 for a lifetime license.

There is a Git file manager called Working Copy. It's a feature-rich app but I haven't found any reason to use it. ShellFish and Textastic combine to give me all the Git happiness I need (Git is of course installed on my cloud dev machine). But of course to use Git and do a host of other things, you need real ssh access to your cloud machine. This brings us to terminal apps.

Textastic has terminal support but it's not very good. Fortunately there is another (free!) app called Termius. I say free - you can pay a monthly fee for additional features like agent forwarding but I've been living at the free level. Termius is really good. One thing it has to do is use the Location services on iOS to do its work when it's not in the foreground. Which I find fine.

Termius provides an additional need which is port forwarding. When I run my app in the cloud, I need to be able to tunnel in to see it from my iPad. Termius supports such tunneling. So you can open the Chrome browser on your iPad and point it to http://localhost:3000 and as long as you've configured and turned on a Termius mapping from port 3000 on your local machine (127.0.0.1) to whatever port you want to connect to on your cloud machine, you're off to the races. As an aside, I had to use iptables to block public access to the port I listened to on the server. This way no one can see my dev server even though it's on a publicly reachable cloud server.

So with ShellFish, Textastic, and Termius I am up and running. My cloud dev machine i rented from Linode. I use a 4GB dedicated machine. It costs $36/month.

One thing I am pleased to discover that I don't miss is Emacs. People who know me might be surprised that I can do without Emacs. Textastic has a find feature, but it does not have a find-and-replace feature. To alleviate this, I found myself learning to use GNU Sed. You can do a lot with sed at the command line. I had to rename a package name on my app and sed, xargs, and find were able to make that not-so-difficult for me. I had to rename a model and sed came in handy there, too. Just be careful. Sed is powerful and I had to spend 20-30 minutes debugging a problem I introduced with it on one of my renames.

There are problems.

  1. Textastic and ShellFish don't work sometimes. Sometimes when opening and editing a file, especially one very recently generated outside of Textastic, one of these two apps starts creating collision-avoidance files. For a file like MyApp.java, the files I'm referring to get names like MyApp-2024-03-26.java, MyApp-2024-03-26-2.java, etc. I wrote a Ruby script that scans my source files and deletes files that look like this. I have to use it about once every 5 hours.
  2. Textastic and ShellFish sometimes take a moment to upload a file. This can be really confusing, because you'll see an error that you think you've already fixed. You trust the compiler and feel stupid, when really the problem is that the compiler just has out-of-date source code and your changes haven't propagated up to the cloud yet.
  3. The Chrome dev tools are not available on iOS. Neither are the Firefox ones. Goodbye JavaScript console. Goodbye hot-editing of CSS. Goodbye view source (yes, really). I had to write a custom logging feature to give me some feedback on JavaScript print statements I would add to my code. This was somewhat helpful but nowhere near what I would call a solution. Who knows when we'll get the dev tools on iOS.
  4. A 4GB RAM $32/month dev machine is not nearly as powerful as a recent MacBook Pro. I feel the pain on every compile and test suite run. Of all of the problems I've mentioned so far, this one is the most onerous. I tested an 8GB Linode, and it went faster, but it didn't feel worth the money to me. The 4GB dedicated CPU machine was an upgrade from where I started - a 2GB shared CPU machine.
  5. Sometimes Textastic is so lost that I have to reboot my iPad. I've even had to hard-reboot it once. This hasn't happened to me for about 2 weeks so maybe patches have helped?

I use a fullsize bluetooth keyboard.

The last thing I'll mention is that I am using an iPad with cellular service. I pay for a plan with Verizon. They say they throttle me down after 30GB of network transfer. I regularly exceed that monthly allowance within a week, but the throttled speed is still plenty fast. I've noticed no hardship from throttling.

I love programming on an iPad very much. One of the other things I've been using my iPad for is studying, using Kindle. I like that the act of doing tech stuff has been rendered relatively simple. Do we really need powerful PCs? If and when I work at a normal job, I would be pleased to use a "real" computer on-site. But if I'm doing stuff from a satellite location like my home, I like where development on an iPad is at.

From Ruby on Rails to Relatively Plain Java

The problem with the Ruby on Rails library, compared to other libraries like PostgreSQL, is that Rails is mostly trying to apply the DRY principle across multiple web server projects, whereas the PostgreSQL library is making difficult algorithmic design decisions. That PostgreSQL actually listens to a TCP socket while Rails establishes a shared runtime with your project is incidental to the argument I am making in this blog post. Libraries that are predominantly concerned with DRYing code disenfranchise the developers who make use of them. They add a layer of hardship because you typically don't have easy access to their source code if and when the shit hits the fan somewhere from within their complexity. Beyond the distanced access to the code, they add a challenge because their complexity is daunting even when your app is still relatively simple in scope (again, when problems emerge from within them).

To join my side on this, you have to be able to hold a B-Tree index implementation as distinct from a piece of ORM code that merely generates an SQL Insert statement, based on a struct instance and table schema it found somewhere. Otherwises you're just going to counter that nobody wants to write B-Tree indexing 10 times in their life when they can just count on PostgreSQL to do it one time for them (and everyone else).

If you wrote B-Tree indexing on two projects, and decided to pull that logic out into a library that the two could share, you would not call that "refactoring". "Encapsulation" would be a better term.

I decided about a year ago that I wanted to write a web app using Java. It would be my first time seriously using Java to perform a task. I was coming from a 10+ year background in Ruby on Rails. What were my goals?

I wanted my app to be simple. I started off by investigating Spring, both the framework and the Spring Boot wrapper. I investigated the ORM facilities in it and Hibernate. I decided that I wanted my app to be simpler than a spring project. I didn't even want to use dependency injection. I started out with Spring Initializr and spring-boot-starter-web. Slowly, I pulled out the Spring Boot wrapper, and eventually even spring-beans. I pulled out the spring-webmvc support. I pulled out Hibernate. "Simple" for me meant that I wanted to spend a lot less time reading documentation and more time writing code.

Without Spring, I needed to do some work to get to what I thought was minimal infrastructure on which I could start addressing project-specific requirements. I determined that I wanted infrastructure for at least these features:

  1. The concept of a MVC Controller
  2. The ability to test a controller action, e.g. a GET request from start to response body.
  3. Asset fingerprinting
  4. Database migration support
  5. Basic SQL statement support
  6. SQL transaction support
  7. Simple app configuration
  8. The ability to launch the app as an executable from the command line
  9. Related to 8, a systemd service unit for the app
  10. A way to store user sessions within a signed browser cookie

I also made use of some libraries to provide me with some features. These included:

  1. Embedded Tomcat and the Jakarta API for the bottommost webserver layer, and basic Request/Response encapsulation, respectively.
  2. Hikari for a database connection pool
  3. log4j2 for logging to STDOUT with log levels
  4. Thymeleaf for templating
  5. The Typescript, esbuild, and scss npm projects for building frontend CSS and Javascript
  6. JUnit for unit testing, and Mockito for mocking support. I built my own factories.
  7. Jackson for JSON help

None of the things on these two lists really had any instrinsic relation to my application's requirements. They were very generic needs. But, I couldn't start to work on my application until these pieces were in place.

I spent what felt like a month migrating from a Spring boot "hello world" project to a place where all of the above was taken care of, without the use of Hibernate, spring-beans, spring-webmvc, or spring-context.

The most obvious consequence of my approach was that writing features took longer. There was one task that I estimated writing in Rails would have taken 10 minutes, but which I spent 3 hours on. It was very easy for me to forecast 5 hours for a feature that I thought was kind of small, but here I was. I didn't have the powerful ORM features at my disposal. I had to write SQL for any database need I had. I had to write unit tests, both at the model level and controller level, for every feature. And of course I had to strongly type my app.

Another concern I have about Rails is that it is dynamically typed. This means that there is no compiler to help you find type errors at a compile phase, whereas with Java and Typescript, you do get support with that. Yes, it takes a little longer to write your code but at least you don't feel hopeless when it comes time to refactor a big chunk of your project. Refactoring in Rails is a nightmare and your unit tests become extremely important in that context. You breathe far easier when you know the Java compiler is going to see what wires you did not reattach correctly.

I do not feel like I escaped writing unit tests. There is the argument that if you're just going to write unit tests anyway, then what is the point of typing? Is it not redunant with the unit testing? My response to this is that as a developer, you want to know in the fastest amount of time that you've made a mistake, and unit tests are not the fastest way to know that. The compiler is faster.

Even though the there was a greater expense of time on this project, the result that I arrived at was more sturdy. If you were developing a video game, wouldn't you want it to never crash? If so, why would you not embrace static typing? Video games are silly wastes of time, as everyone knows. But we still want them to work. Where pride is concerned, I think you want your video game to work just as much as you want code in the NASA Space Shuttle to work. Aren't you willing to wait a longer priod of time for your code to be done, then? This way your app is sturdy. When I say sturdy, I particularly am referring to when refactoring time comes. You can make adjustments and not feel so terrified that you're going to break what was working yesterday.

I wrote above that libraries like Rails disenfranchise the developers who work with them. On this project of mine, I went to use the Devise gem on a toy Rails project while building a tour of some Ruby code. There is a step in the Devise setup where you invoke a Rails generator. All the crypticness of Rails came back to me when I invoked that. I had no idea what it was doing. Why are there ~50 files in a Rails project when I haven't even done anything yet? The Rails library is supposed to support the thousands of Rails projects out there. When you use it, all of the if-statements that have gone into supporting 9,999 other projects besides yours suddenly become your responsibility. It doesn't seem that way, but that's the reality, isn't it? You're responsible for what your app does even if you choose to use Rails. But do you really feel responsible for all of the code inside of Active Record? You're responsible to your customers regardless of what library philosophy you choose. If you choose Rails, you're inheriting responsibility for thousands of lines of code that you know very little about. That places you in an unfair position of powerlessness. And as I mentioned, when it's time to debug that code, it's not in the Zeitwerk watch list, so you have to restart your app every time you edit the outside source. That's after you've navigated outside of your project folder and into the gem sources to find it.

You could wonder how I feel about Sinatra. That's simple, right?

If I were to pursue the above philosophy with Rails, I would write a Rack app without Sinatra. Rack would be where I draw the line. I'd use rspec, still. I'd get controller infrastructure going on my own. I'd use haml or erb for my views. But I wouldn't use Rails, Sinatra, or Active Record.

There is an enormous movement called convention over configuration. I think it would be redundant for me to evaluate it here, given what I've already written. I am much less of a fan of that movement as of today.

Saturday, March 9, 2024

Coming to Terms with the Work in Front of Me

On approximately March 3rd, I made a good-size donation of money to a streamer on twitch.tv. Twitch, over at www.twitch.tv, is a place where streamers can play videos games with a web cam focused on themselves, and audience members (like me) can watch them react to the video game they're playing. There is a chatroom where the streamer can read messages that I type. Others in the chat also type in messages. So there is communication going back and forth.

Over the years, I have donated a lot of money to streamers on twitch. I've made a couple sizable donations to male streamers, but most of my donations have gone toward female streamers.

Sometimes the reason I donate is because the streamer provides an environment wherein I can find attention. I mostly do not care that much about what other chatters are saying. Mostly, I care about what the streamer has to say to me. That's been true for awhile.

When I donated to the streamer on March 3rd, she got happy. She is young and friendly and she thanked me. She also asked me how I was doing.

There is a specific situation that arose leading up to that day, which is that I finally was able to overcome much of my fear of studying. So, there was something I wanted to celebrate.

Many, many times I have donated to a young female streamer on twitch because I feel like having someone to celebrate a good thing in my life. The attention that I get gives me a high. Years ago, I used to frequent strip clubs and when I would buy a VIP dance from a stripper, I would get a high. I felt at those times like I was in a symbiotic relationship with the stripper: I was paying her to entertain me and excite me. Afterwards, the stripper almost always said thank you. Sometimes I got a kiss on the cheek.

I stopped attending strip clubs in 2017, but at the same time I took up donating to women on twitch. Again, I felt like I was in a symbiotic relationship with the women there. I would support their streaming in exchange for their moral support of my life.

Today, I got up and did a couple hours of studying. Last night I did five hours of programming and two hours of studying. I am putting all of this effort into my skillset as a programmer because I want to be independent again some day. I want to show that I can support myself. I want to thrive as a programmer. I don't want to live paycheck to paycheck. I want to have a savings account.

Mentally, I've reached a point where I am really losing my desire to seek the company of streamers on twitch. I've worked about 30 hours during the past 7 days. I haven't earned any money for that effort. Yet, I know it is what I want to do. How is it that I am able to do this?

To cut closer to the chase, do I want to continue to celebrate my motivation to work with streamers on twitch? What for? I could, if I wanted, uncork some more money and donate again to someone in the near future. I could share the positive news with them that I am working diligently, and that this is something that I am proud of. But what for? They can respond "Hey that's great Mike!" but how would that make my life any better? How would they be informing me of anything I don't already know?

Forget about work for a second. Today I had tacos from Chipotle. Do I want to share this fact with a streamer on twitch? What for? What do I care whether they share or do not share my appreciation for chicken tacos. When I take a bite of a taco at Chipotle, and I chew on it, I can taste the chicken in my mouth, and I feel happy. How is someone else's opinion of tacos going to make me any happier?

These arguments I'm making didn't used to be effective. But tonight I feel exhausted of something. I just don't see the point in seeking praise from other people about what I am doing in my life anymore. I am incredibly confident that I am doing everything in my power to take care of myself. I wasn't working 30 hours a week two months ago. But I am now. I'm doing it for no pay. And a sizable portion of that work is just me studying my computer textbooks. This is a lot of stress for me to be taking on but I'm doing it.

The fact that I'm doing as well as I am - motivation-wise - has made me question my old longings for companionship or support. I am mostly thinking of the support of young, pretty women when I say this, but it goes just as much for men too. I don't feel like my life will be better if I find out a male peer or female peer endorses Chipotle tacos.

I had a special experience a few months ago when my sister offered her perspective to me during a stressful situation, and that experience really made me see how friendship could be a boon in my life. But there is distance between that, and the moral support that I've been describing above. I feel like I am mostly feeling a sense of loss when it comes to having moral support. I feel apathetic about it, as you can see from what I've written.

There is a group of software developers that hold meetings coordinated through meetup.com. I plan to attend those meetings, in the hopes of making friends. I tried to attend one a couple weeks ago but there was some miscommunication about our virtual meeting room. The group is all local people. So this could lead to something for me.

I don't know what I'm going to have to say to the people at these meetings. I guess conversation is easy enough to make, but are they going to help me with my work? No. Work is what I have to perform. Work is how I can gain money and support myself. Friends can help you move from one place of living to another, but so can movers if you pay them.

I really like how entertaining a young, pretty woman can be. This is a big reason I like K-Pop as much as I do. I go on YouTube and watch K-Pop music videos a lot. It's very easy. It's conversationless, too.

I don't know what I have to say to an attractive woman anymore. Now in particular, since I seem to have come to terms with the need to perform in my career. It's very obvious to me, the path forward to gain employment again. I think it's obvious to most people, but so many of us want to party in the name of comfort to relieve ourselves from stress. I am regaining a certain arrogance that I used to have when I was younger. The pressure of life is me. It's not some employer. It's not the threat of financial difficulty. It's me. I'm the one who makes me work. Not need. Not fear. Fear is what I proactively overcome, now.

And so this is where I find myself.

Wednesday, March 6, 2024

Famous

If I were a cool guy, how would my life be different during downtime?

Right now, I am in the habit of either studying one of my two computer textbooks, or writing code for one of my apps. So I'm doing work.

I get tired of doing those things. It feels like general fatigue. It's as if I want to take a break from concentrating.

At the end of my day, it is common for me to conclude that I am relatively exhausted. When this happens, I go and lay in bed. I bring my iPad with me and I open the YouTube app, and I watch Arrested Development clips. I do this even when it's not bed time and I just want to do something other than work.

Arrested Development is off the air. No new episodes are coming out. I don't pay for episodes - I only want to watch the free clips that I can get on YouTube (although I do pay for YouTube Premium). Both of these facts mean I'm constantly rewatching the same favorite clips from the small pool that I have available to me.

I face a similar situation if I want to watch The Office clips.

Watching full episodes of either of these shows is off the table. I don't want to pay money to watch a full episode. The actual shows at hand are not fun to watch, in my opinion. They hit gold once in awhile and that's what makes the content on YouTube very enjoyable. At least, up to a point.

I tire of my YouTube recommended feed. The grassroots content of YouTubers isn't really interesting to me. Video essays have a low ceiling on them for some reason. I feel that all the content creators are only producing content with a voice suitable for addressing people no more mature than what we'd find in a high school classroom.

I like working lately. I feel like I'm doing a good job and not running from challenges. If I become a cool guy by keeping this up, how will my life be different? Will I still feel bored during my downtime?

What if I were the president of the United States? Let's say it's 10pm, and my responsibilities are taken care of. It's my downtime. What do I do?

What if I were a rock star? It's 10pm. It's my downtime. What do I do?

I don't know the answer to this question.