I started out as a junior C# developer. Then-raw Xamarin, Android development, the whole shebang. My first steps at work were filled with pain. I had to write an Android app alone based on screenshots and gifs of the iOS version. It only compiled every other time, buga were all over the place, and the only feedback I got was — “why isn’t it like in the screenshot?”. It was a nightmare and I quickly left. I then spent half a year learning to code at home, and then got a job at a large outstaff. There it was a lot more organized — team, mentors, exams, patterns, code review, strict linters, high standards for code quality, readability and performance. In one word, everything was mature. And I thought that’s how it should work. But, as it turned out, it was an even bigger nightmare. For over a year our entire team was making a module for a tool that worked with tools that were used to make other tools. Probably the same ones we used to make the modules. Every day we had to call Indians and Americans and report on god knows what. At some point I realized that I was doing less and less, but nothing changed. I lied through my teeth in broken English: “All past week I search for bug. Still no success. Will continue”. “Ok Phil, sounds great” — my transatlantic partners answered. At one point, desperate and shameful I went to management and asked to fire me, but instead they for some reason gave me a raise. I’ve already told that story before. I wasn’t happy nor sad — it felt like some sort of a surreal joke, like the logic of this world was falling apart. Strangely enough, out of boredom and being ultra-ambitious I decided to develop things at home, and do everything “properly”. I had numerous ideas how to use software projects to make the world and my wallet better. I did everything by the book: a design document, architecture, system requirements, a VSTS projects. Everything was organized and mature, just like in corporations. It wasn’t getting anywhere. Natural conclusion — the idea was crap. Old code into the bin, new idea. Same result. Start over again. This continued a couple of times. I tell my coworkers and they’re confused. What am I doing wrong? I do it the exact same way as those who already got rich off the back of it. People with my (high) level of self-esteem are often better off than others, but have to pay for it sometimes. You need to lie to yourself to cope with failure. And I told myself: any developer is capable of anything. It’s all about how it’s done, and my requirements for “how” are too high. They’re not fit for a home startup and they’re not worthy of pointless business tasks. Next thought: “I’m not ready to abandon my quality standards”. Even if I need to make an app that farts when you tap the screen, I’ll make it as beautiful and thought-out as possible. So I set up a local business cargo-cult at home. Brought over everything — rituals, processes, standards — but not the actual meat of the thing. I played a business developer without a business, like a caveman who made a runway and a watch tower out of straw and expected steel birds to land on it. I wrote piles upon piles of formal, strict code that didn’t get me any closer to the end result, but the exact opposite. If you think about it, my career is a story of failure and disappointment. I gave it up entirely and just watched TV shows at work while drinking 16 cups of coffee a day. At rock bottom, I noticed a Habr article on F#, tried it out, and thought “Hm, not bad!”. My employer happily paid for a month of studying for me (though he doesn’t know it). F# wasn’t hard to learn, since it had the same runtime as C# and I already used the functional approach to programming in TypeScript every day. I realized that I can transfer any of my projects to F#. Let’s leave my technical skill out of the equation for a moment, since it’s all relative. In the teams I work in I’m great, but in a team of, say, F# developers I couldn’t be anything more than a janitor. But I could solve problems on a basic level, even though deep down I knew: I wouldn’t really solve anything. I’ll just continue throwing knowledge in the trash. I completely lost my faith in programming. One day I decided that enough was enough. I was going to quit. It was a cold, dark winter day. I exited the office, got in my car — and it doesn’t start. After a while, the engine finally came to life. I don’t know if I noticed the smoke of the smell of burning plastic earlier, but then a fire erupted from under the hood. A couple of seconds later I was running around the parking lot telling everyone to get their cars away from mine. Five minutes of panic and chaos later, only an old burning car carcass and a phone with stupid YouTube videos remained. It was -30C, and I was in a light coat of a man who intended to drive home in a warm car. Completely spent and morally destroyed. No money for a taxi and way too much care for myself to get on public transport. I walked home, 10km or so. Home I needed to help my wife with the kid, eat, get them to bed, do a thousand little things. But eventually there’s nothing to get distracted anymore and I remained face to face with my insomnia and a realization — I’m not worthy of anything, I won’t ever succeed. In this, worst evening of my life, still cold from a freezing walk home, I gave myself one last go at it.
I sat and wrote a small digital biome on F#, where machine-learning units interact with each other and develop, while I play with parameters and watch what happens. And yes, that night I probably went a little mad. Usually I use a mix of the ascending and descending model of programming. I outline a rough solution with pseudocode, then start writing the most important details as separate modules. From small to big. Moving on from pseudocode to real code,I complete one or two large modules and check whether anything’s working. Usually it doesn’t, so I start to iterate, repeating this process from start to finish until it works. But most often I just give up after the 5th or 6th iteration. I tried the same approach with F#. I had a general vision of the project, and then the solution was building, brick by brick, in my head. You come up with one case after another, and then at some point you realize that you know how to make it work. And then you start coding and realize that no, you don’t. Thoughts don’t translate into programming languages, even though you often think in it. I had this happen all the time. This time, though, it was different. I created a .txt file in VSCode and wrote the pseudocode for a function that describes the life cycle of my app. And I realized that my pseudocode is valid in F#. No need to translate anything, I just wrote the main function of my project. Okay, I changed the file extension, added it into the clean solution. There was my life cycle function. It accepts the current world state, a thing that processes it (the world itself) and spits out the updated state, a thing that translates it into a set of AI parameters and back, plus the AI itself that accepts parameters and spits out the solution. Then it was simple. You take the state, turn it into AI parameters, feed them to the AI, turn the result back into the world state, give it to the game, and the result goes back into the life cycle function. A beautiful recursion, a simple algorithm, sublime code, all the GoF out of the box. All that was left was to make it work. But the thing is, I don’t have to think about the architecture anymore. I write what Java and Sharp developers call “inversion of control container” — a function that takes the life cycle function and passes through the functions fro my modules (II, Game). VSCode highlights it in red because it doesn’t have either functions or modules, but I have what I need — as soon as the red highlights are gone, I can build the project and it’s done. I take the modules and make them, one by one, working in the same fashion. The whole project is 5 files. The AI file is 500 lines — a lot, but most if it works really well. The beauty of this approach is that I could write a working life cycle function — the heart of my app — without describing anything else at all. The entire architecture is 10 lines of code, written in a couple of minutes. No interfaces, abstract fabrics, locs, all of these DefaultInterfaceNameClasses and other crap I have to do in C# before I even understand what I want to create. You write dumb core that simply solves the problem, and it’s more beautiful than your enterprise-level sufferings in Java or Sharp. And I did it all just by typing my thoughts into the editor, like I was thinking in F#. Instead of outlining a plan in C# comments, I wrote working functions. Instead of describing tens or even hundreds of interfaces, there’s one small file with the domain model of the app. Clicked “build”. Received a working solution. In one night. With quality code I can confidently give to review. As simple as that.
I don’t know what’s the deal — if F# is a monumentally awesome technology, or if it simply fits me perfectly, or if it’s created for these tasks specifically — what’s the difference? What’s important is at that moment I was sinking and I needed a lifeboat. Life threw me F# and I pulled out of it. Now it’s not just another soulless technology to me — it’s a huge emotional deal. Now, when I hear someone scold F# — “A stillborn tech! A geek toy…” — I always remember the cold winter night, the burning car, the cigarette frozen in my mouth, depression and F# that pulled me out of it. It’s as if someone threw shit at my best friend.
It might look strange to an outsider, but if you lived that day in my place, you would’ve reacted the same. I think that’s common in any technology cultist. They fell in love with their languages, because they have an emotional attachment to the circumstances that made them discover it. And then I come and spit right into their soul. Who’s the idiot now? I am. I won’t do it again, I hope.