# Gökmen Görgen > Hello there. I'm a polyglot programmer, a former startup founder, and a car guy. My career started with contributing a Linux distribution called [Pardus](/2024/04/18/how-did-i-meet-pardus/). I worked as a software engineer on web projects for a long time. Now I'm busy with data engineering on artificial intelligence technologies, and try to be an indie developer. ## Posts ### 2026 Software Trends > URL: https://gokmengorgen.net/2026/06/07/2026-software-trends/ | Published: 2026-06-07 00:00:00 +0000 UTC | Categories: software-engineering | Tags: opinion, trends, generative-ai _This article was originally written in Turkish in December 2025 as a contribution to the "2026 Trends in the Software World" series. The original collection can be found here: [Yazılım Dünyasında 2026 Trendleri](https://mhkoca.medium.com/yazılım-dünyasında-2026-trendleri)._ --- Hello, this is my third article. For four years now, I've been talking about mass layoffs, recessions, emerging business sectors, and working frameworks like the hybrid model. As someone who has been coding in Python for over 15 years and working without interruption, 2025 turned out to be the year where I had to learn the most new things, gain the freshest experiences, and constantly reinvent myself compared to any previous year. Moving forward, I foresee that **"captain" developers**—those who can adapt swiftly to dynamic conditions, work cross-functionally, remain highly productive, and manage tiny, agile teams—will become incredibly valuable. Back in 2023, I wrote that NO-CODE would become a trend once again. What I had in mind was a development environment built around visual programming tools—similar to Unreal Engine Blueprint—where people with absolutely no programming background could build software. N8N is a wonderful example of this. But what I failed to anticipate was that despite the long-standing antipathy toward the terminal even among seasoned software engineers, the terminal itself would be embraced so universally as a prompt interface. This shift has radically impacted the interface components of editors and IDEs alike. Are we truly ready for editors that will soon eliminate the file explorer and code viewer entirely, leaving nothing but a single prompt input block? Editors that show changes in the code rather than the code itself, or better yet, don't even show that but instead explain what modifications were made using natural human language? These shifts are causing anxiety for some of us. Yet, similar metamorphic processes have happened in the past. From the old-school concept of a "Webmaster" splitting into Front-End / Back-End / Full-Stack, to Cloud Engineers evolving into Platform Engineers, roles have always transformed. ActionScript or SymbianOS developers felt these exact same shifts in their time. At the end of the day, we have one singular purpose: to deliver value. To generate the most sustainable value through the most optimal path with the fewest resources. This was true yesterday, and it will remain true tomorrow. Only the tools and methods change. Simply being developers with old-school analytical intelligence is no longer enough. We now need to be developers who command human language. We need to be engineers who excel at writing, speaking, and communicating—highly social, connected, and deeply open to the outside world. From now on, every single one of us must become a **generative developer**: someone who takes the initiative, manages projects, and captains a crew of AI agents. Rather than writing code manually, our primary job will shift to making machines write code, reviewing that code, optimizing it, boosting its efficiency, correcting its flaws, and preventing those flaws from recurring. In fact, doing quite the opposite—deleting code and ruthlessly cleaning up codebases—will become our main focus. Newcomers entering the industry can count themselves lucky instead of falling into despair, as they will naturally adapt to this new definition of a developer much faster. They might want to take a close look at emerging fields like Data Engineering, Platform Engineering, AI Governance, Generative AI, and MLOps. If code optimization is what excites them, they can dive deep into Interoperability and CUDA; being a polyglot engineer is a brilliant advantage right now. On the other side of the equation, companies desperately need to solve their own adaptation issues. Currently, instead of opening new roles, they are trying to force an internal transformation. The catch is, they don't even know what positions to open or what the actual requirements for those roles are. I don't know if things will completely settle down in 2026, but it is certainly going to take some time. Of course, I am keeping macroeconomic and geopolitical developments entirely out of this equation. I wish everyone a happy, peaceful year ahead—one where technological opportunities are accessible to all developers in a truly fair and equitable way. ### The Real EV Bottleneck: Not Range > URL: https://gokmengorgen.net/2026/06/07/the-real-ev-bottleneck-not-range/ | Published: 2026-06-07 00:00:00 +0000 UTC | Categories: lifestyle, family | Tags: ev, opinion, range Is it technically impossible to build a smartphone with a battery that lasts a full month? I suppose it would either be a heavy brick, take an eternity to charge, or just be too expensive to make any sense. Even if a company fixed all those issues and started mass production, I’d probably still be sitting here thinking: "I don't mind plugging my phone in once a day, why on earth do I need more?" Even though the technology evolved differently, I feel exactly the same way about electric vehicle range. People seem to think that once EVs hit 600, 800, or even 1000 km of range, they will finally become a real alternative to internal combustion engines. Honestly? I don't think they will—not even if they reached a 2000 km range. Here is why. First, unless I’m going on a massive road trip, I have never actually needed to charge the battery to 100% (I use NMC, by the way). My time is valuable and I absolutely hate waiting. Yes, I plug it in frequently, but the charging stations happen to be at the exact same places where I eat or grab a coffee. I am not going out of my way. I already need to park the car somewhere to do quick grocery shopping mornings, for example. Second, even on long road trips, I take at least a 30-minute break every two or three hours anyway. The result is exactly the same. What I am trying to say is: **There is already a perfect harmony between the car’s charging speed, its range, and my personal driving habits.** Back to the smartphone analogy. Most people charge their devices while working or driving; they rarely wait for the battery to hit zero, nor do they meticulously track when it reaches 100%. If the goal is to minimize time spent waiting by a plug, the automotive industry needs to embrace a similar "destination charging" model. The most practical solutions are: 1. **Frequent, opportunistic charging:** Topping up the vehicle during a daily commute or while running errands. 2. **Extended destination charging:** Utilizing Level 2 AC chargers at the workplace or at home while the vehicle is parked for hours. If you can't utilize these two solutions where you live, an EV simply won't make sense—no matter how much range it has or how fast it charges. Unless these infrastructure changes are implemented, using an EV will continue to involve unnecessary friction. The future does not rely on centralized stations resembling modern gas stations. Instead, charging infrastructure must be integrated directly into environments where people already spend their time—whether that is residential street parking in dense cities like Berlin or dedicated charging bays within modern housing projects. Therefore, discussions about waiting by the charger will lose their meaning, regardless of range. Ultimately, the only genuine problem an excessively long range solves is facilitating cross-country road trips on a single charge. However, if frequent long-distance travel is a primary requirement, waiting for battery technology to bridge that specific gap is unnecessary; traditional ICE vehicles remain the optimal tool for that exact purpose. ### Making an Easy-to-Install Application in Python > URL: https://gokmengorgen.net/2025/11/02/making-an-easy-to-install-application-in-python/ | Published: 2025-11-02 00:00:00 +0000 UTC | Categories: software-engineering | Tags: python, pyapp, astral-uv, dosh, conda, pyinstaller, pyapp, nuitka, self-executable, self-contained In our projects, I had a simple script named `do.sh` to quickly define and run tasks. I don’t remember why we didn't use `Makefile`, but it had similar functionality. It's just a BASH script: you can define environment variables, add functions and easily run other CLI commands. We wanted to be able to do that without having an extra dependency, so we could tell the developers, "Just download the script and run the command `sh do.sh setup`." That's it! It was much better than writing all the steps and other instructions in the `README.md` file. One day, however, I decided to switch from Linux to Windows and start using PowerShell. This meant that I could no longer easily run all these BASH scripts. Also, I didn't want to put in the extra effort for converting the scripts into PS1, so I created a new project in Python called [DOSH](https://github.com/gkmngrgn/dosh). So I will download just a single program called `dosh`, I'll write a single script in Lua language and it will work on all operating systems and shell types (Oh yeah, maybe that's why I didn't want to use `Makefile`, it's not a real cross-platform tool actually). But a few new problems emerged with DOSH: 1. **The zero-dependency rule.** When it was a Bash script, you didn't need to install anything extra to run it on MacOS and Linux (or even on Windows with WSL). I'm okay to download one program but it must be very easy installable. How can we do it in a Python application? 2. **The need for continuous development.** The needs never end. As with [yt-dlp](https://github.com/yt-dlp/yt-dlp/tree/master/yt_dlp/extractor), everyone needs to grab a part of it for a special purpose and write a function for the project to have meaning. For example, I use tinypng to reduce the size of images on my blog. Instead, I would like to do it with just a command like `dosh compress-images`, or to run it in each deployment automatically (`dosh deploy-blog`). Let's set the second point aside and return to our topic. _How can we ensure the zero-dependency rule in a Python project?_ I recommend you take a quick look at the headings before you start reading. ## The Purpose I want to make an application that is easy to install and doesn't require extra instructions to use. Meaning, I shouldn't have to go to [python.org](python.org) and download Python to run the application. It should be **self-executable**. Our application can be a single file, making it easier to download and install, or it can consist of multiple files and directories within an archive file. Both methods have advantages and disadvantages. For example, our first choice will probably be to download a single-file application; but every time we run the command, it will lose time parsing and interpreting that file. For a desktop application, this delay might be negligible, but for a CLI application, waiting at the start, even for milliseconds, will become annoying at some point. There's another concept, it's **self-contained**. In this method, as the name suggests, it's not just the interpreter, but also the dependencies that are kept inside the package; it's meant to have all the minimum requirements not just to start the program, but to run with all its functions. There's a subtle but clear difference. Let me repeat: We need a Python interpreter for running a Python application. But the application also has dependencies. For example, if you use Qt for the interface and you haven't installed Qt and its Python bindings on your computer, the application won't run due to missing dependencies. "Well, if you're embedding the interpreter, why wouldn't someone include the dependencies?" you might think. We don't really use or need the concept of a shared library in Python. That's a situation more needed in languages like C++, C#, and Java. You might have encountered this: You install a game from Steam, and when you try to run it, a popup opens saying "Please install Microsoft Visual C++ 2015 Runtime" blah blah, and the game closes. That is a shared library issue. Instead of embedding it into thousands of games one by one, you install it once, and all the games run using the same library. When there are many common components like this, it makes sense to use shared libraries to reduce the download cost per game. Now, let's decide on the method. ## Which Method Should I Choose? Let's review the options we have. We'll evaluate all options specifically for Python: ### Using the Operating Systems' Package Managers WinGet on Windows, Homebrew on MacOS, and on Linux... a .deb package for Ubuntu, .rpm for Fedora, PKGBUILD in AUR for Arch Linux, or Flatpak, or Snap for all distros... There are too many package managers. Is it worth spending this much effort on a single application? It would be reasonable if we only needed to support MacOS. Alternatively, if you have a very strong community, everyone can contribute and make the app available to install via multiple package managers. However, the community would then be busy updating, maintaining and automating them. It also slightly bends the zero-dependency rule I mentioned at the beginning. You prepared the Homebrew package for macOS, but what if the user doesn't use Homebrew? Some users may prefer MacPorts – should you create a package for that too? If you did, would it be easy to get it accepted into the repository? How long would it take? In short, there might be special cases where it's reasonable, but not for DOSH. This method is an example of self-executability. ### Using Python Package Managers Some applications may require a Python interpreter to be installed on the system. For example, you're a research engineer and you use Anaconda. If my application is intended for Anaconda users, it might make sense to create a [conda package](https://docs.conda.io/projects/conda-build/en/stable/user-guide/tutorials/build-pkgs.html). If I need to support other Python distros, uploading to PyPI might be more logical. Since I designed DOSH as a language-independent application, this method didn't work for me. However, there is one exception: [astral-uv](https://docs.astral.sh/uv/). Uv has -almost- every features that other Python package and dependency managers do. I mean, you can have users try your application without installing a Python interpreter, or even without installing your application beforehand. With just two steps, you will tell your users: 1. Install Uv. 2. Run this command: `uvx ` It's quite simple; all you need is that your application should be released on [PyPI](https://pypi.org/). This method is neither a self-executable nor a self-contained example. Because we are installing the interpreter, and trying to install its dependencies with its package manager, or we are just installing `uv`. ### Zipapp Frankly, I expect a self-contained application to also be self-executable, but [zipapp](https://docs.python.org/3/library/zipapp.html) is a method that falls a bit outside of this. You need an interpreter installation, but you don't need to install any dependencies. Because thanks to zipapp, you create an archive package that contains all the dependencies. When is this method useful? The first things that come to mind: 1. You have an internal company tool that you can't send to PyPI, but you don't want to deal with registry systems like CodeArtifact. 2. You want to just package and deploy the application for simple projects instead of dealing with Docker containerization. 3. Or you can use it as part of a code obfuscation process for an on-premise service. I'm not sure if it's useful, need to investigate. In short, this method also has areas where it's reasonable; but not for DOSH. ### PyInstaller, Nuitka, PyApp, and Others As a final option, let's review the projects made for preparing zero-dependency, ready-to-use packages. Why didn't we look at these from the start? Because they are not as easy as they seem, they require extra effort and maintenance, and "there's no silver bullet". I mean, like the other options, none of these completely solves a problem. My advice is to try to solve the problem with the other simpler options as much as possible, and only when they don't work, convince ourselves that tools like PyInstaller will solve the problem. Each of these has a different approach and priority. You can make it a single file or a single directory. You can make it just self-executable and have the dependencies installed later. Or you can turn it into a completely offline-workable installation package. Some of these are automatically added to the executable path, making the command directly accessible; for others, you might need to move the directory or file to the correct path. Some can even solve code obfuscation problems themselves, which might be a reason for preference if you have concerns about code privacy. But every option has a downside. Making it a single file reduces performance; if you only make it executable, you become dependent on the internet to install dependencies, and so on. ## My Choice Since DOSH is already an application that depends on the internet, I didn't care about it being self-contained. All I wanted was to make an application that even someone who knows no Python at all can install and use. [PyApp](https://ofek.dev/pyapp/latest/) was the best in my opinion regarding CLI performance and the size of the created package, so I chose it. First, I wrote a BASH script to create the executable file: ```bash export PYAPP_PROJECT_NAME="dosh" export PYAPP_PROJECT_PATH="$(find $(pwd)/${{ inputs.dist-path }} -name "dosh*.whl" -type f | head -1)" echo "Packaging DOSH binary: ${{ inputs.dosh-binary-name }}" echo "Using wheel: ${PYAPP_PROJECT_PATH}" # download pyapp source code, build it curl https://github.com/ofek/pyapp/releases/latest/download/source.tar.gz -Lo pyapp-source.tar.gz tar -xzf pyapp-source.tar.gz mv pyapp-v* pyapp-latest cd pyapp-latest cargo build --release # and rename the binary mkdir -p ../${{ inputs.output-path }} mv target/release/pyapp "../${{ inputs.output-path }}/${{ inputs.dosh-binary-name }}" chmod +x "../${{ inputs.output-path }}/${{ inputs.dosh-binary-name }}" echo "Binary packaged successfully at ${{ inputs.output-path }}/${{ inputs.dosh-binary-name }}" ``` Next, I defined this script as an [action](https://github.com/gkmngrgn/dosh/blob/main/.github/actions/package-dosh/action.yml) to run automatically on Linux (x86_64, arm64), MacOS (Apple Silicon), and Windows (x86_64) platforms in GitHub Actions every time I release a new version. You can find the entire workflow [here](https://github.com/gkmngrgn/dosh/blob/main/.github/workflows/release.yml), I'm just showing an example from Linux: ```yaml package-on-linux-arm64: runs-on: ubuntu-24.04-arm needs: - build steps: - uses: actions/checkout@v4 - uses: ./.github/actions/package-dosh with: dosh-binary-name: dosh-linux-arm64 dist-path: dist output-path: bin ``` Every time I add a version tag, this workflow will run, create the binaries, and store these files as artifacts. By the way, don't be fooled by the binary sizes; when you package an application with PyApp, it bootstraps the application when you first run it, so you are dependent on the internet at least for the first run. But for me, it's an acceptable disadvantage: ![](/images/dosh-github-actions.png) As the next step, we will publish these built executable files on GitHub Releases to make them available to the end-user: ```yaml - uses: ncipollo/release-action@v1 with: artifacts: "dosh-*/dosh-*,release-dists/*" ``` ![](/images/dosh-github-release.png) Now the application is available to the end-user! They can download and use it. Since this is a CLI application, I created [`install.sh`](https://github.com/gkmngrgn/dosh/blob/main/install.sh) and [`install.ps1`](https://github.com/gkmngrgn/dosh/blob/main/install.ps1) scripts to provide a bit more practicality. This way, in the `README.md` file, I recommend users to install from the terminal: ```shell sh <(curl https://raw.githubusercontent.com/gkmngrgn/dosh/main/install.sh) ``` For Windows users: ```powershell iwr https://raw.githubusercontent.com/gkmngrgn/dosh/main/install.ps1 -useb | iex ``` As a second option in the same workflow, I send the package to PyPI. I leave the user the chance to install the app with uv as a simple and backup installation alternative: ```yaml - name: Publish release distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: release-dists/ ``` ```shell $ alias dosh="uvx --from dosh-cli dosh" $ dosh ``` Now, as long as there are no structural changes, I don't need to spend any more effort on packaging. ## Epilogue When choosing your packaging method, you also need to consider licenses and code obfuscation if you are developing a closed-source project. I hope this has been a guide for those dealing with this problem. DOSH is not yet a finished or ready-to-use project; however, I welcome your contributions if it interests you. You can reach me for your comments via social media or email. ### Running Ray Tracing on a GPU Server > URL: https://gokmengorgen.net/2025/10/10/running-ray-tracing-on-gpu-server/ | Published: 2025-10-10 00:00:00 +0000 UTC | Categories: software-engineering, artificial-intelligence | Tags: python, rust, nvidia, cuda A few years ago, to better understand ray tracing, I read the book [Ray Tracing in One Weekend](https://raytracing.github.io/books/RayTracingInOneWeekend.html). The original code samples were in C++, and as I read, I was translating and writing them in Python. Yes, I knew from the start that it was a terrible idea, but I was curious. One of the best ways to observe Python's performance inadequacy is to test the ray tracing algorithm by generating an image with a width of 1000 pixels. But even 300 pixels takes a lot of time. Therefore, you resort to alternative solutions such as interoperability, multiprocessing, or GPU usage. This appeared as a fun and extra task that I had to solve while learning ray tracing. The code is in the [GitHub repo](https://github.com/gkmngrgn/rayt), you can download and use it from the terminal. You can also try it on [Hugging Face Spaces](https://huggingface.co/spaces/goedev/rayt-web); but if you want to test it with GPU, you need to fork the repo and run it on a server with a GPU. There are a few topics I want to share about this work: 1. Why is Python, one of the most popular languages in the world, so slow? 2. Running Rust code on a Hugging Face server, cross-compilation. 3. Understanding CUDA, using the GPU in backend projects. 4. Considering the information here as a template. ## Why is Python Slow? Actually, the answer is simple: Python is an interpreted language. There is an interpreter between the machine and you, and the optimizations you can do at the language level are limited. For example, the GIL (Global Interpreter Lock), the biggest benefit of the interpreter, automates many tasks that are done manually in languages like C/C++, which provides code readability and helps you focus on the main task; but on the other hand, it prevents you from taking full advantage of the CPU's performance. As the number of pixels in ray tracing increases, the for loops increase, and in each loop, the costs of creating objects, running the algorithm, and cleaning up memory increase exponentially. There is also something that most Python programmers have heard frequently: "In Python, almost everything is an object.". So it's absolutely not the same thing using data types in C++ and in Python. So is the performance issue in Python such a hopeless case? It all depends on what we expect and what result we can be happy with. First of all, it must be admitted from the beginning that using the CPython interpreter for ray tracing is a bad choice. But as I said, instead of making a specific thing, we want to satisfy our curiosity and see what we can do when we need something similar in the future. Let's start with the first one, **interoperability**. ## Python - Rust Interoperability When I first started writing RAYT, it was pure Python, with a single CPU core, and it was terribly slow. The first solution that comes to mind is multiprocessing. But I decided to postpone this idea because of two reasons: 1. I plan to test it with No-GIL, free-threading feature which coming with Python version 3.14 later. 2. I was not sure that multiprocessing would give the improvement I expected. But I was sure that interoperability would have a contribution to the performance. The only problem is that we need to learn the helper language we will choose besides Python. So a little question at this point: Since we are going to get support from another language, why don't we just write in that language completely? Let me remind you of my motivation from time to time. My goal is not to write a ray tracer. It has been written many times by different developers in dozens of languages. My goal is to find answers to what I can do when I have to solve a performance problem in any Python project I work on. First, I thought about making the C++ code runnable in Python with [pybind11](https://github.com/pybind/pybind11) while the C++ code was ready. But then I thought I would spend less effort in Rust for packaging, loading dependencies, and cross-compilation. The packaging is important, even Python could not solve this problem successfully. I know how to solve these kinds of problems myself, but if you are not familiar with the Python community, these tools will seem like chaos to you: Using pip inside Conda, poetry with pyenv or pipenv, having a `pyproject.toml` file but using `requirements.txt` to install packages... A complete chaos; but the fault is with the package managers. Anyway, I'm not going to get into this topic. [uv](https://docs.astral.sh/uv/) is the best for me until something better comes along, and its Rust interoperability support is very good. After all, it is a Python tool written in Rust: ```shell uv init --build-backend maturin rayt-rust ``` This magic command creates the necessary files and directory structure for you to use Rust code in Python: ``` rayt-rust └── src └── lib.rs └── rayt_rust └── __init__.py └── _core.pyi └── README.md └── Cargo.toml └── pyproject.toml 2 directories, 6 files ``` The Rust code will be in the `src/` directory, and the dependencies will be written to the `Cargo.toml` file. That's roughly it. When we run the `uv build` command, the `rayt_rust` package will be ready to use in Python. But there is a problem, if we go back to our motivation, our goal is not to write the whole code in Rust; just to move the performance-critical part to Rust and keep the rest in Python. There are two ways to do this: 1. Prepare a separate library for performance-critical parts and install it as a dependency to the Python project. 2. Host all modules in a single package. I chose the second one for RAYT. This is the reason why there are two different directories named `rayt/` and `rayt_rust/` in the `src/` directory. Thus, when I run the `uv run one-weekend` command, the Rust code is automatically built and ready to use. However, I will also show an example of the first option on the Hugging Face page. ## Using RAYT on Hugging Face Spaces [Gradio](https://www.gradio.app/) is a simple and useful Python library that allows you to prepare a web interface for ML models. Hugging Face Spaces is a service with similar practicality where you can run Gradio, with GPU support. Now let's put the GPU part aside and run RAYT with a simple web interface. You can try the web application made with Gradio [here](https://huggingface.co/spaces/goedev/rayt-web) and examine its source code. The first thing I want to draw your attention to is the `requirements.txt` file: ```requirements.txt gradio numba-cuda[cu13] https://huggingface.co/spaces/goedev/rayt-web/resolve/main/rayt-0.1.0-cp310-abi3-manylinux_2_34_x86_64.whl ``` I wrote all the necessary dependencies to run both locally and on HF Spaces. RAYT has to be a link, because I think HF Spaces copies the `requirements.txt` file to a different directory during deployment and cannot find the `.whl` file. Since the repo is open to the public, so it won't be a problem to download the wheel file publicly. This was the first solution that came to my mind, another solution is to prepare your own Dockerfile. The second problem is that since RAYT is now a compilable library, you need to be careful about which Python version you use and for which operating system you compile. Since HF Spaces uses Python 3.10 and Linux by default, you need to prepare a development environment accordingly. Normally, to test RAYT locally, you need to install [rustup](https://rustup.rs/) (for Rust and cross-compilation) and [uv](https://docs.astral.sh/uv/) (for Python), and then follow these steps: ```shell gh repo clone gkmngrgn/rayt && cd rayt uv build ``` If I remember correctly, rustup will install the necessary [target](https://rust-lang.github.io/rustup/cross-compilation.html) according to the platform you are using when it is first installed. When you wanted to try running RAYT CLI locally, it will probably work, but you may not have the same target on your HF Spaces server, so there's one more step. This is one of the reasons why I chose Rust for interoperability, when I think about the somersaults I did to run C++ code in WASM, I realize the comfort provided by [Maturin](https://github.com/PyO3/maturin) better. Now let's try to install the correct target and build it: ```shell rustup target add x86_64-unknown-linux-gnu uv tool install maturin uvx maturin build --target x86_64-unknown-linux-gnu ls target/wheels/ ``` ```shell rayt-0.1.0-cp310-abi3-manylinux_2_34_x86_64.whl ``` Nice, Python distro is CPython, version 3.10, operating system is Linux, processor architecture is x86_64. Alles gut. Now we can use this in our web application. Since this is a simple template project, I avoid complexity as much as possible. Because the needs of each project and the preferred tools are different. Normally, this should be part of the DevOps process; when a new version is released, the build process should start on CI/CD servers, artifacts should be uploaded to a service like CodeArtifact, and web projects should be able to install packages from this service. The second thing I want to draw your attention to about the repo is the `.gitattributes` file: ```.gitattributes *.parquet filter=lfs diff=lfs merge=lfs -text *.pb filter=lfs diff=lfs merge=lfs -text *.pickle filter=lfs diff=lfs merge=lfs -text *.pkl filter=lfs diff=lfs merge=lfs -text *.pt filter=lfs diff=lfs merge=lfs -text *.pth filter=lfs diff=lfs merge=lfs -text *.rar filter=lfs diff=lfs merge=lfs -text *.safetensors filter=lfs diff=lfs merge=lfs -text saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.tar.* filter=lfs diff=lfs merge=lfs -text *.tar filter=lfs diff=lfs merge=lfs -text *.tflite filter=lfs diff=lfs merge=lfs -text *.tgz filter=lfs diff=lfs merge=lfs -text *.wasm filter=lfs diff=lfs merge=lfs -text *.xz filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text *.whl filter=lfs diff=lfs merge=lfs -text ``` Keeping large files in the repo is not a good idea. For example, sometimes you don't need these files to work on projects, and as the size of these files increases, cloning the repo takes unnecessary time. [Git LFS](https://git-lfs.com/), [Xet](https://xethub.com/), [DVC](https://dvc.org/) are some of the tools used to solve this problem. It's not a big problem for a 304 kb package, but it is useful to take precautions from the beginning in professional projects. So let's take a look at how `.gitattributes` is created. First, you need to install `git-lfs`: ```shell git lfs install git lfs track *.whl git add .gitattributes ``` From now on, when you commit and push a `*.whl` file, LFS will keep this file in a separate storage. Finally, We know how to use a Python library written in Rust in a web project. ![RAYT HF Interface](/images/rayt-hugging-face.png) ## Did Rust Solve RAYT's Performance Problem? It's not as fast as C++, probably not even as fast as a CLI written entirely in Rust. But, it's many times faster than Python. We can say that it has largely solved the performance problem; but what if we want to use a GPU? Both Rust interoperability and access to the GPU via Rust?? May be a good idea but I've no time for testing it. But it is probably possible to do that too, if there is a CUDA-supported GPU on the server, why not? But let's put Rust aside for now and focus on another topic. Can we take advantage of the power of the GPU by writing Python code and using CPython? I'm sure there is more than one way to do this; I tried it with Numba. ## Numba and Numba CUDA - [Numba](https://numba.pydata.org/) is a Just-In-Time (JIT) compiler that uses the LLVM compiler library to translate Python code into optimized machine code at runtime and run it on the CPU. - [CUDA](https://developer.nvidia.com/cuda-toolkit) (Compute Unified Device Architecture) is a platform that allows us to use the enormous processing power of NVIDIA's graphics processing units (GPUs) for general-purpose computing, also known as GPGPU. - [Numba CUDA](https://nvidia.github.io/numba-cuda/) is an additional package that translates Python code into PTX code (Parallel Thread Execution) and runs it on CUDA GPU cores. In summary, you can think of Numba as a JIT Compiler and CUDA as a target. It includes the same basic motivation as rewriting RAYT in Rust. But you don't need to learn another programming language to use Numba CUDA, you just need to know how the CUDA architecture works, other than that you don't even need to do anything for GPU memory allocation/deallocation. But Numba CUDA has two disadvantages: 1. JIT compilers have a waiting time for code translation and compilation on the first run. It is a negligible time when you consider the total time. 2. As you can imagine, you need a graphics card, drivers, and additional packages to use CUDA. Now let's go back to the RAYT code and review the other options besides Rust. To prevent some code repetition, I moved some functions that I thought were critical to Numba and continued to use the Rust code for the rest, but let's assume that there is no Rust code in it and we only used Numba, I don't think we will need both in a real project. Although we are only writing Python code, there are some limitations: - We cannot use `try - except`. - There is no context management (`with`). - There are no generators. - There are no comprehensions made with list, dict, set. - Debugging is a little different than we think. - Worst of all, typing support is limited and a bit unconventional. But we can use NumPy and let me explain its importance as follows: You will use CPython, you will have your values defined in Python in certain data types, and you will be able to convert them to NumPy arrays and pass them as parameters to Numba functions. Likewise, you will be able to get the values returned by these functions back as NumPy arrays or send them to each other between functions. The best example to understand how I did this is the `_prepare_scene_data` method: ```python import numpy as np import numpy.typing as npt from rayt_rust._core import Camera, HittableList, get_color, Color from rayt.numba_optimized import render_pixel_numba class NumbaRenderer: """Numba-optimized ray tracer renderer""" def __init__(self) -> None: self.spheres_data: npt.NDArray[np.float64] | None = None self.materials_data: npt.NDArray[np.float64] | None = None self.camera_data: npt.NDArray[np.float64] | None = None def _prepare_scene_data(self, world: HittableList, camera: Camera) -> None: """Convert scene objects to NumPy arrays for Numba""" # Sphere data: [center_x, center_y, center_z, radius] self.spheres_data = np.array(world.get_sphere_data(), dtype=np.float64) # Material data: [type, param1, param2, param3, param4] # Type 0: Lambertian [type, albedo_r, albedo_g, albedo_b, unused] # Type 1: Metal [type, albedo_r, albedo_g, albedo_b, fuzz] # Type 2: Dielectric [type, ref_idx, unused, unused, unused] # Default to Lambertian with white color self.materials_data = np.array(world.get_material_data(), dtype=np.float64) # Camera data: [origin, lower_left_corner, horizontal, vertical, lens_radius, u, v] self.camera_data = np.array(camera.get_data(), dtype=np.float64) ... ``` I started by [moving](https://github.com/gkmngrgn/rayt/blob/main/src/rayt/numba_optimized.py) some performance-critical code from Rust to the JIT compiler to test this. You can try it by selecting `numba` as the `Engine` in our [web project](https://huggingface.co/spaces/goedev/rayt-web). Before you try, think about how its performance would be compared to Rust. The hint is on the same page. We are using CPU in both. My impression is that we need to understand the requirements of the project we are working on really well and calculate the cost correctly by subjectively presenting the advantages and disadvantages of the two options. Numba also provides a performance contribution compared to pure Python, but not as much as Rust. Do we need more, do we have the knowledge, time, and capacity to do it? All should be considered. I think the real story in Numba starts with CUDA. The first thing we need to understand while making Numba code work with CUDA is Thread Hierarchy. ## Kernel and Thread Hierarchy The most important thing that CUDA achieves at its core is that it gives us programmers the ability to start thousands of cores for repetitive tasks simultaneously, that is, parallel processing. This process roughly happens as follows: 1. **Moving data from RAM to VRAM.** VRAM is the video random-access memory used by the graphics processing unit. The data has to be moved here first because we will have the GPU do the processing. 2. **Running the computation called a kernel on the GPU.** We give this instruction to the CPU, and the CPU transmits it to the GPU thanks to Numba CUDA. The GPU performs the computation simultaneously using the data in VRAM, using all its cores in parallel. 3. **Moving the computed data back from VRAM to RAM.** Since we use the CPU as the host and we always communicate through the CPU, we also need this stage. When we say `python run main.py`, we are instructing the CPU to run this program. But when we want a computation to be run on the GPU, we need to define special functions that we call kernels. The kernel function in RAYT is [very long](https://github.com/gkmngrgn/rayt/blob/0e79a0e20048b2c4d06f909c182511a02462fc30/src/rayt/cuda_optimized.py#L426-L545), but I want to touch on a few points by trimming it here: ```python @cuda.jit def render_pixels_cuda(image_width, image_height, samples_per_pixel, ...): i = cuda.blockIdx.x * cuda.blockDim.x + cuda.threadIdx.x j = cuda.blockIdx.y * cuda.blockDim.y + cuda.threadIdx.y if i >= image_width or j >= image_height: return ... # Store result (note: j is flipped for correct image orientation) output[image_height - 1 - j, i, 0] = pixel_color[0] output[image_height - 1 - j, i, 1] = pixel_color[1] output[image_height - 1 - j, i, 2] = pixel_color[2] ``` The `@cuda.jit` decorator allows our `render_pixels_cuda` kernel function to be converted to native GPU code (PTX). Then we run this function over the grid and block size parameters: ```python # Calculate optimal block and grid sizes block_size = 16 grid_size = ( (image_width + block_size - 1) // block_size, # Point.x (image_height + block_size - 1) // block_size, # Point.y ) render_pixels_cuda[grid_size, block_size](image_width, image_height, samples_per_pixel, ...) ``` **What are Grid and Block size?** To understand this, let's think that we are programming on a single thread and CPU. Normally, we need to calculate the ray color for each pixel of the image we want to generate: ```python for j in range(image_height, 0, -1): for i in range(image_width): ... ``` The two nested `for` loops actually create a grid for us. But there's a problem here: It cannot move on to the second one before the ray color calculation at one point in this grid is finished, everything proceeds sequentially. On the other hand, we have a grid proportional to the width and length of the image we want to obtain on the GPU, even before we run the kernel function. So when the GPU runs the kernel function, the ray calculation will be ready to start at every point of the image at the same time. I think it's clear what we meant with grid size. Imagine an image you want to generate in your mind, and there're separate blocks to calculate ray colors of each pixel of this image. And there're also threads in each block, which is defined by the second parameter `block_size`. Don't confuse this thread with a CPU thread, it works in a very different logic. The threads in a block perform the instruction related to a point on the grid simultaneously by dividing the data sets. Now it is clear why we don't need a `for` loop to define `i` and `j` in CUDA, right? ```python i = cuda.blockIdx.x * cuda.blockDim.x + cuda.threadIdx.x j = cuda.blockIdx.y * cuda.blockDim.y + cuda.threadIdx.y ``` Actually, this information contains an important clue about the question we asked at the beginning, "Why is Python slow?". We are trying to have the color calculation done 307,200 times one by one, even to calculate a tiny image of 640x480 pixels. On the other hand, the GPU saves us from this bottleneck thanks to this grid structure, every block in the grid, and the threads in each block, totaling hundreds of thousands of threads. This structure is called **Thread Hierarchy**. ## So Is It Possible To Use CUDA On Hugging Face? Theoretically, it is possible. Practically? I haven't tried it, but I think it's possible. You can try it by selecting `cuda` as the engine in the RAYT web interface, but first you need to deploy it to a server with a GPU. But you know, it's not free, and it's not worth for burning money for ray tracing. ![Hugging Face Spaces GPU Options](/images/hugging-face-spaces-gpu-options.png) Just try it on your local machine if you have NVIDIA GPU. I don't see any reason why it shouldn't work after you installed the CUDA toolkit and numba-cuda packages compatible with the GPU. Then you can compare the results with different engines. ## Epilogue ![TIOBE Index Programming Languages Popularity Ranking 2025](/images/tiobe-index-programming-languages-2025.png) There was a discussion on social media about how Python became the world's most popular language despite being a slowest language (is it?), and whether performance is important or not. The increase in GPU usage in Machine Learning and NLP jobs already explains the importance of performance, but in addition, the cost must also be taken into account. Speed and performance will always be important to me, whether with GPU and CUDA programming, with Rust/C++ interoperability, or by using Python subinterpreters or free-threading. On the other hand, developments are progressing very fast and nobody has time to lose with languages that are difficult to learn, code, compile, and read. This is why Python is so popular. ### Python 3.14 Released, It's Time to Drop 3.9 > URL: https://gokmengorgen.net/2025/10/08/python-314-released-time-to-drop-39/ | Published: 2025-10-08 00:00:00 +0000 UTC | Categories: software-engineering | Tags: python, gil, uv I took a quick look at the new features in Python 3.14. To try the code below on your local machine, install [uv](https://docs.astral.sh/uv/) and run the REPL with the following command: ```shell uv python upgrade 3.14 uvx python@3.14 ``` # [PEP 750](https://peps.python.org/pep-0750/): Template Strings Template strings (t-strings for short) were a proposal to address a significant shortcoming in existing f-strings, and it's now ready for use with version 3.14. First, let me show you the problem: ```python >>> name = "Gökmen" >>> f_hello = f"Hello, {name}" >>> t_hello = t"Hello, {name}" >>> type(f_hello) >>> type(t_hello) ``` Since the type of `f_hello` is `str`, extra code was needed to understand what the variables were or which parts were static. However, when the type is `Template`, all this information is accessible: ```python >>> dir(t_hello) ['__add__', '__class__', '__class_getitem__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'interpolations', 'strings', 'values'] >>> t_hello.values ('Gökmen',) >>> t_hello.strings ('Hello, ', '') >>> t_hello.interpolations (Interpolation('Gökmen', 'name', None, ''),) ``` Why was this needed? It makes string operations on dynamic values more practical: ```python >>> from string.templatelib import Interpolation >>> "".join([part.value.upper() if isinstance(part, Interpolation) else part for part in t_hello]) 'Hello, GÖKMEN' ``` With `Template`, you can even build a simple [Jinja](https://jinja.palletsprojects.com/en/stable/) clone. # [PEP 649](https://peps.python.org/pep-0649/), [PEP 749](https://peps.python.org/pep-0749/): Eliminating `NameError` in Annotations The following code gives a `NameError` in Python 3.13 because we are trying to define the type of `a` while `X` is not yet defined: ```python >>> a: X | None = None ... class X: ... ... Traceback (most recent call last): File "", line 1, in a: X | None = None ^ NameError: name 'X' is not defined ``` To solve this problem, we either had to make `X` a string or use [`__future__.annotations`](https://docs.python.org/3/library/__future__.html#future__.annotations). Now, neither is necessary: ```python >>> a: X | None = None ... class X: ... ... >>> ``` # [PEP 734](https://peps.python.org/pep-0734/): New Module for Using Multiple Interpreters: `interpreters` It is now possible to run Python code through multiple interpreters within the same process without getting lost in the depths of the [C-API](https://docs.python.org/3.14/c-api/init.html#sub-interpreter-support), staying within Python code. Normally, all sub-interpreters you start under the main interpreter are isolated from each other. Even if you started the same Python code in 100 interpreters, it didn't contribute to performance as long as there was no communication or data transfer between them. Now, this new module makes communication possible through shared objects. Perhaps I can demonstrate this later by optimizing [RAYT](https://github.com/gkmngrgn/rayt), but for now, I'm sharing an example code from [here](https://peps.python.org/pep-0734/#synchronization): ```python import interpreters from mymodule import load_big_data, check_data numworkers = 10 control = interpreters.create_queue() data = memoryview(load_big_data()) def worker(): interp = interpreters.create() interp.prepare_main(control=control, data=data) interp.exec("""if True: from mymodule import edit_data while True: token = control.get() edit_data(data) control.put(token) """) threads = [threading.Thread(target=worker) for _ in range(numworkers)] for t in threads: t.start() token = 'football' control.put(token) while True: control.get() if not check_data(data): break control.put(token) ``` # [PEP 758](https://peps.python.org/pep-0758/): No Longer Necessary to Use Parentheses for Multiple Exceptions This was one of the most common syntax errors I made. Now, writing exceptions without using parentheses is valid syntax: ```python >>> try: ... x() ... except NameError, ValueError: ... print("achtung!") ... achtung! ``` # [PEP 765](https://peps.python.org/pep-0765/): Plan to Deprecate `return`/`break`/`continue` Inside `finally` To maintain backward compatibility, we only get a `SyntaxWarning` for now. Since `finally` always executes, using `return` within it was quite confusing: ```python >>> def bool_return(): ... try: ... return True ... finally: ... print("you tried to return True but you will also see this message?") ... return False ... :6: SyntaxWarning: 'return' in a 'finally' block >>> bool_return() you tried to return True but you will also see this message? False ``` By the way... The REPL has really turned into a text-based editor; the syntax highlighter works beautifully. ![Python 3.14, REPL Syntax Highlighter](/images/python-314-repl-syntax-highlighter.png) # [PEP 768](https://peps.python.org/pep-0768/): Ability to Debug Without Adding Breakpoints This is a bit like open-heart surgery, I guess; in production and production code, not even a single piece of code related to the testing and development process is allowed to be committed to the repository. Services like Sentry are generally used for this, and the best thing to do right now is to use logging effectively. Rarely, we might wish for easier debugging. PEP 768 could be an alternative for that. A function named `remote_exec` helps us with this. The first parameter of this function is the PID number of the Python process we want to debug: ```python import sys import uuid # Execute a print statement in a remote Python process with PID 12345 script = f"/tmp/{uuid.uuid4()}.py" with open(script, "w") as f: f.write("print('Hello from remote execution!')") try: sys.remote_exec(12345, script) except Exception as e: print(f"Failed to execute code: {e}") ``` # Other Innovations and Python 3.9 The Free-Threaded mode introduced in 3.13, garbage collection, the REPL, and standard modules have been improved. Error messages can now offer suggestions for typos (if you type 'whillle', it asks, 'did you mean "while"?'). By the way, with every new major release, the most significant thing holding us back from these innovations is the continued support for older versions. Python 3.9 will no longer receive security updates. I think it's time to stop supporting 3.9 in our projects. By doing so: 1. We will be able to use Structural Pattern Matching (`match - case`). Take a look [here](https://peps.python.org/pep-0636/). 2. We will be able to [use parentheses](https://github.com/python/cpython/issues/56991) to manage multiple contexts with a single `with` statement. 3. Pipe usage like `bool | None` will be valid, so you can use pipes between types instead of `Union[bool, None]`. If you are looking for a guide to keeping Python projects up to date, you can check out this article of mine: - [Keeping Python Projects Up to Date](https://gokmengorgen.net/2025/03/30/keeping-python-projects-up-to-date/) # Resources - [What's New in Python 3.14](https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-free-threaded-cpython) - [New features you'll have when you stop supporting Python 3.9](https://docs.python.org/3.10/whatsnew/3.10.html) ### My Next 10 Year PC Setup > URL: https://gokmengorgen.net/2025/09/07/my-next-10-year-pc-setup/ | Published: 2025-09-07 00:00:00 +0000 UTC | Categories: hobbies, remote-working | Tags: mini-itx, pc-build, gaming-pc, ryzen-9900x, rtx-5080 I assign a minimum lifespan to things I want to own. This habit helps me calculate how much budget I can allocate for them, understand whether that thing comes cheap or expensive, and whether it's worth it. My 6-year-old Alienware laptop was a bit of a disappointment for me. I wanted it to be something I could game on at home, code on, and also be my portable computer. I also wanted to be able to increase RAM and SSD capacity when needed in the future. None of my expectations were met satisfactorily. It was hard to carry, the charger was like a brick. The battery swelled twice and I had to replace it. Upgrading any hardware was difficult \- those curious should definitely check out Alienware 15 R3 battery replacement videos. Despite everything, it served me for 6 years. Now it will continue to serve for my daughter's education and gaming. Now I know better what I want, and I'm sure it's not a laptop. I thought about Steam Deck for a long time. A system I'm sure works properly with Linux, developed for gaming, and a portable device I can use as a desktop computer. But I could never be sure I could use it for a long time. Then I researched Mini PCs. I've seen a lot of Mini PC setups shared thanks to Omarchy lately, and they're all beautiful. But when you wanted to make the hardware a bit better, the price became as expensive as building a mini-ITX case. Buying and assembling computer parts from scratch is a troublesome job. When I looked at ready-made setups, I either had to pay for a part I didn't like, or it was more expensive than I expected. Therefore, I decided to choose all the parts myself and prepare the machine myself. This also had its risks: parts not being compatible with each other, lack of Linux support, the possibility of any part arriving broken, bottlenecks, learning the features of almost all parts and extra effort to assemble them. I took this risk. While reading my steps, you may witness my amateurism. I'll summarize what I learned afterwards. # **Starting Small: Case** Honestly, I wasn't sure I was making the right start, but I wanted to first determine what kind of case I wanted to see on my desk. At first, I thought about so-called sandwich cases, where the graphics card and motherboard are mounted back-to-back like a sandwich. But I encountered too many handicaps. I had too many questions in mind like how heat management would work, whether I could install the graphics card I wanted, whether I could organize the cables, which power supply would fit this. Later, on my friend's advice, I researched the Cooler Master NR200P and really liked it. I didn't have very specific requirements for fans and cooling systems. Therefore, I preferred the NR200P V2 Max model, which has two fans at the top exhausting heat, a liquid cooler for the processor, and an 850W PSU. ![](/images/pc-setup/cooler-master-nr200p.png) When it arrived, I was genuinely surprised by how compact it was. I knew the dimensions, of course, but seeing it next to my keyboard really drove home just how small this build would be. # **The Overwhelming Cable Management Reality** Now that I had a clear framework in hand, my mind was somewhat relieved. Now I can start by buying a motherboard, I said. The processor would be AMD, it shouldn't be too expensive or too old. Having two memory sockets, one graphics card, and one NVME SSD slot was enough for me. I preferred ASRock B850I. ![](/images/pc-setup/asrock-b850i.jpg) I hadn't anticipated that mounting the motherboard to the case would challenge me this much when no other parts had arrived yet. I was placing orders one by one and as soon as parts arrived, I couldn't help myself and immediately started assembly. Inexperience\! Also, cables seemed so big to me that I struggled quite a bit to understand what to plug where. After finishing the setup, I couldn't understand why I panicked so much. It turns out it's almost impossible to plug some cables wrong or backwards. All I had to do was calmly read the installation booklet. # **CPU** My next order arrived: AMD Ryzen 9 9900X. Actually, I was thinking of buying the Ryzen 7 series, but when there was a discount, I found it more economical compared to the 7 and bought the 9\. I realized later that this was a wrong decision. I should have considered not only the price but also energy consumption and heat management. I'm not sorry, but it was an unnecessary investment. The 7 would have been enough for me. ![](/images/pc-setup/amd-ryzen-9-9900X.jpg) After installing the processor, I immediately mounted the cooler that came with the case, plugged in the cooler and fan cables, and waited for my next order to arrive. # **Memory and Storage: The Easy Wins** ​​A total of 64GB, two Crucial Pro DDR5 RAM sticks and a P510 SSD from the same brand were the next parts to arrive. When choosing RAM, I paid attention to data transfer rate and storage capacity. 5600 MHz is sufficient for games, but I thought it would be useful to be able to reach 6400 MHz thanks to AMD Expo technology for my AI works. ![](/images/pc-setup/crucial-memory-and-storage.jpg) Similarly, I paid attention to read/write speed on the SSD (10000/8700). 2 TB storage probably won't be enough, but my motherboard allows me to install more SSDs and HDDs. # **First Run for Testing** Now I could install the operating system and check if everything was working properly. I installed Arch Linux. I could write a different post about the installation, but I'd like to briefly mention this: Arch Linux has become a system that's easier to install after all these years\! Moreover, thanks to distributions like EndeavourOS, Manjaro, Omarchy that are very easy to install, you don't have to do step-by-step installation from the terminal. After installing the system, I activated AMD Expo for faster memory data transfer rate and checked whether the amdgpu kernel module was working correctly for integrated graphics. My first impressions were very good. ![](/images/pc-setup/first-boot.jpg) I even played a few games with low graphics system requirements on Steam and they worked very well. However, the screen freezing for a second or two bothered me, and I started researching what the reason could be for a long time. The dmesg and journalctl outputs were full of error outputs related to the amdgpu kernel module, but I couldn't find anything about the solution. I tried different kernels, looked at BIOS settings, but to no avail. It didn't always happen, but when it did, it bothered me. For now, this problem was temporarily solved by buying a graphics card and disabling the integrated card. # **The Fan Dilemma: Function vs. Form** As far as I observed, there was no problem with the system, but when I noticed that there was nothing to provide cold air intake, I bought two Noctua NF-A12x15 fans for the bottom of the case. I planned for cold air to enter from the bottom of the case and hot air to exit from the top. My first assembly was both very difficult and looked terrible. ![](/images/pc-setup/noctua-first-try.jpg) The biggest feature of the brown mounting kit used instead of screws was to prevent vibration and noise, but it stood high and there wasn't much space for the graphics card inside the case. I also couldn't install the gray dust filter. Therefore, I used screws later. There was no disturbing increase in noise and vibration. I didn't like that the RAM was white, I couldn't find the black color. Similarly, I couldn't find the black color of Noctua fans. I didn't worry about these too much because the inside isn't visible anyway after closing the case. But for those who care about appearance, incompatible colors will be a bit disturbing, I noticed that. Now that only the graphics card was left, I started to gradually secure the cables. I needed to make sure that no part would move when I had to move the case. # **The Final Component: GPU Installation** I couldn't decide whether it was the hardest or easiest to assemble. I realized how important cable organization was when installing my NVIDIA RTX 5080 graphics card. If the cable passed in front of the card, it would block the fan; if it passed from behind, the length wasn't enough; if you extended the cable, there was a possibility of it getting caught in the fans below. I wasted quite a bit of time with this. But after organizing the cables, the rest was really very easy. ![](/images/pc-setup/nvidia-rtx-5080.jpg) I used both the card support brackets that came with the Cooler Master case and the graphics card together. After finishing the assembly, I closed the case. I disabled the integrated graphics card from BIOS settings and installed the necessary NVIDIA drivers. For a long time, I did my tests with both games, Ollama, and the [ray tracing application](https://github.com/gkmngrgn/rayt) I wrote myself. All fans are working as I want, temperatures are at the level I expected, and there are almost no problems. Everything is working as I want. # **Living with the Imperfections** Even now, looking at photos of the finished build, that one fan cable still catches my eye. But everything is mounted securely and won't budge. At this point, my only hope is that this setup will serve me well for at least the next 10 years. # **Lessons Learned** 1. When buying the case, I should have calculated whether the 850W PSU would be enough for me. When I want to update my graphics card in the future, I'll probably have to buy a PSU as well. 2. Trying to mount other parts after mounting the motherboard to the case was very difficult. It would definitely have been easier for me to wait for all the orders. Memory, SSD, and CPU should be mounted to the motherboard first, then the motherboard should be mounted to the case. 3. Sometimes parts change for various reasons like price, delivery date, whether they're in stock, second-hand, etc. When they change, you need to recalculate some things from the beginning. For example, at first I had in mind to buy AMD Ryzen 7, when the price of 9 dropped, I bought it without thinking, but I remembered much later that 9 consumes more energy than 7\. 4. Even if you know what you're going to do before starting assembly, it's useful to definitely look at the booklet. Plastic protections on parts that need to be removed make themselves quite obvious, but it's still useful to be very careful. You don't want to forget and find them melted from heat inside. Building a PC after six years reminded me why this hobby is both frustrating and rewarding. The technology has evolved, form factors have gotten smaller, and cable management remains the eternal struggle. But there's something deeply satisfying about assembling your own machine, knowing every component and connection intimately. Here's to the next decade of computing – may this little powerhouse prove as reliable as the Alienware that came before it. ### Keeping Python Projects Up to Date > URL: https://gokmengorgen.net/2025/03/30/keeping-python-projects-up-to-date/ | Published: 2025-03-30 00:00:00 +0000 UTC | Categories: software-engineering | Tags: python, devops I had the experience of upgrading Python in the projects from 3.8 to 3.12 in one step, and I realized that keeping the Python versions up to date is just as critical as keeping the dependencies up to date. Maintenance should not be a separate task, it should be part of all the other tasks. If you can check and update package versions in a timely manner, you don't have to tell anyone that it's going to hold up your business in the future. Of course, there are exceptions to this rule. Suppose you need NumPy for completing a task, you also noticed that the required numbering types[^1] are not defined in the version what you used in a project. It's a good time to make the major update in NumPy dependency, right? On the other side, Python version of the project prevents you to update the package. Also, if you drop the old Python version support from the projects, you see that some web services will not work because of version mismatching or your some teammates are still working with the older version of Python and you don't want to break their development environments without letting them know. I can think of so many example scenarios like this one. I suggest you to prepare **a guideline document** and start by convincing your teammates to comply with this document. And in the Acceptance Criteria section of the tasks, there will be a new secret clause like checking code coverage in the unit tests: **Guideline document compliance will be reviewed.** The guideline should include the following sections: 1. **Introduction about the document.** Also share the preferred Python version and distribution. 2. **Pre-requirements** for the development environment. 3. **Development in the existing projects.** This section should include the repository access, environment setup, task management, and CI/CD access. 4. **Starting a new project.** This section should include the template repositories and how to create a new project. 5. **Style guide.** This section should include the code style, docstrings, imports, type hints, testing, and documentation. 6. **History.** This section should include the date, version, and description of the changes of the guideline document. 7. **Sources.** This section should include the sources of the guideline document. I asked [Claude AI](https://claude.ai/) to generate a template for the guideline. It turned out to be a pretty good example, almost perfect. Copy this template and modify it according to your needs. You can also use it as a starting point and add more sections if you need. --- ## Python Project Development Guide This document provides guidelines to maintain technical stack consistency across Python projects within our organization. Following these standards ensures all developers can easily work on different projects, reduces onboarding time, and improves code quality and maintainability. | | | | ----------|------------ | | **Python Distribution** | CPython is the standard implementation.
PyPy is supported for performance-critical applications. | | **Supported Python Versions** | Minimum: v3.10
Maximum: v3.13
Default: v3.12 | | **Package Manager** | uv (v0.6.0+) | | **Minimum Supported Dependencies** | [Dependabot](https://github.com/dependabot) is mandatory for all our projects. We also follow [SPEC 0](https://scientific-python.org/specs/spec-0000/). | ### Pre-Requirements Before starting development on any project, ensure you have the following tools installed: - **[pipx](https://pypa.github.io/pipx/)**: For installing and running Python applications in isolated environments. - **[uv](https://github.com/astral-sh/uv)**: Fast Python package installer and resolver. - **[pre-commit](https://pre-commit.com/)**: Framework for managing git hooks. - **[AWS CLI](https://aws.amazon.com/cli/)**: For accessing CodeArtifact and other AWS resources. You can install all the required tools using `pipx`: ```bash brew install pipx pipx install uv pre-commit awscli ``` ### Development in the Existing Projects 1. **Repository Access:** - Clone the repository using: `git clone ` - Configure AWS credentials for CodeArtifact access: `aws configure` 2. **Environment Setup:** ```bash # Install the required Python version uv python install 3.12 uv pin 3.12 # if there's no `.python-version` file # Create a virtual environment uv sync # Test the environment uv run main.py # Initialize pre-commit hooks pre-commit install ``` 3. **Task Management**: - All projects use GitHub Issues for task tracking - Pull requests require a linked issue and at least one reviewer approval - Commit messages should follow [Conventional Commits](https://www.conventionalcommits.org/) format 4. **CI/CD Access**: - CI/CD pipelines run on GitHub Actions - Pipeline configurations are stored in `.github/workflows/` - AWS deployment credentials are managed via GitHub Secrets ### Starting a New Project When creating a new project, use one of our template repositories[^2]: - [Python Internal Library](https://github.com/organization/python-lib-template): Base template for reusable internal libraries - [Python Flask Web Service](https://github.com/organization/python-flask-template): Template for RESTful API services - [Python FastAPI Service](https://github.com/organization/python-fastapi-template): Modern API service with automatic documentation - [Python Data Science Project](https://github.com/organization/python-datascience-template): For data analysis and machine learning projects To create a new project: 1. Navigate to the template repository on GitHub 2. Click "Use this template" > "Create a new repository" 3. Follow the setup instructions in the generated README.md 4. Update the project metadata in `pyproject.toml` 5. Commit and push your initial changes ### Style Guide Our code style is enforced through pre-commit hooks. All projects should include the following `.pre-commit-config.yaml`: ```yaml repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: "v4.3.0" hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-toml - id: check-added-large-files - id: check-docstring-first - repo: https://github.com/Lucas-C/pre-commit-hooks rev: "v1.3.1" hooks: - id: forbid-crlf - id: remove-crlf - repo: https://github.com/pre-commit/mirrors-mypy rev: "v0.982" hooks: - id: mypy args: - --strict - --ignore-missing-imports additional_dependencies: - types-click - types-python-dateutil exclude: ^tests/ - repo: https://github.com/astral-sh/ruff-pre-commit rev: "v0.11.0" hooks: - id: ruff args: [ --fix ] - id: ruff-format ``` Additional style guidelines: 1. **Docstrings**: Use Google-style docstrings 2. **Imports**: Group imports in the following order: standard library, third-party packages, local modules 3. **Type Hints**: All code should use type hints 4. **Testing**: Minimum 80% code coverage required 5. **Documentation**: All public APIs must have documentation ### History | Date | Version | Description | |------|---------|-------------| | 2025-03-30 | 1.0.0 | Initial document creation | ### Sources Our guidelines are based on the following resources: - [Python Developer's Guide](https://devguide.python.org/) - [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html) - [Scientific Python Development Guide](https://learn.scientific-python.org/development/) - [PEP 8 -- Style Guide for Python Code](https://peps.python.org/pep-0008/) - [Astral Python Development Guidelines](https://github.com/astral-sh/ruff/blob/main/CONTRIBUTING.md) [^1]: [`np.int` is deprecated](https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations) [^2]: [GitHub Template Repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository) ### The Best Size Of A Laptop > URL: https://gokmengorgen.net/2025/03/17/the-best-size-of-a-laptop/ | Published: 2025-03-17 00:00:00 +0000 UTC | Categories: lifestyle | Tags: minimalism, apple, mobility, a4, envelope 17 years ago, Steve Jobs stood on stage with a manila envelope in his hand and pulled out a laptop. At that time, mini-laptops called [netbook](https://de.wikipedia.org/wiki/Netbook) were very popular, and the first Macbook Air had far superior features in every way. I had a Lenovo IdeaPad S10e. If I remember correctly, the screen resolution was 1378x768, but it was good enough for me. It fit in my small bag, it was light, and I could open it up and even use it on the food tray on my long bus rides. Now we have stronger CPUs, faster read and write speeds on storages, thinner bezels, longer-lasting batteries, etc. But I always missed that tiny size. I don't care about extra wide displays, I don't care about mechanical keyboards, I don't want to see more things on my desk than a tiny laptop. Maybe a phone and a wired headphone like Beyerdynamic DT 990 Pro, and of course a good internet connection could be enough for me to do all my work. I have always dreamed of laptops as clients for remote workstations. 17 years ago, uninterrupted Internet connectivity was a distant dream. But now we are very close. I also think that instead of carrying around powerful machines for AI all the time, we will need more self-hosted servers at home. A monster machine in our homes and a tiny laptop that connects to it.. I already wrote a [blog post](https://gokmengorgen.net/2022/03/06/remote-development-environment/) about my setup, but I tried using a tablet instead of a laptop. Unfortunately, the results were disappointing. Of course it is important for a laptop to have good specifications, but in my opinion the best laptop could be an A4-sized Macbook Air. Or a **Macbook Mini**.. --- Thanks to [Santiago](https://x.com/svpino/status/1900896021217243415) for being the inspiration for this blog post. ### Reliability Matters For Minimalism > URL: https://gokmengorgen.net/2025/03/06/reliability-matters-for-minimalism/ | Published: 2025-03-06 00:53:46 +0100 CET | Categories: lifestyle | Tags: minimalism, automobile, toyota, apple Sometimes I see this photo when Apple announces a new product and there are some really funny jokes about it on social media. Frankly, I don't understand the criticism that "Apple is exhausted, it can't produce anything new" for technological products that have reached a certain maturity. How do you compare them? I used the iPhone 11 for more than four years and upgraded to the iPhone 16e. I agree that there's not much difference in appearance, there's still a notch at the top of the screen, it's lighter. There's a single-lens camera, but the quality is better than the older one. I didn't notice any improvements on the screen because I was happy with the old one too, but the iPhone 11 has a lot of improvements like 5G connectivity, longer battery life and the ability to charge multiple devices with the same cable thanks to USB-C. If I were using an iPhone 14 or 15, I wouldn't understand these innovations, and When the iPhone 17 comes out, I probably won't find the innovations that come with it remarkable. I assign a lifespan to the technological devices I own and try to keep them as long as possible. In return, I expect these products to be reliable or durable. Reliability has two important benefits for the consumer: 1. When you divide the price of the product over its lifetime, many reliable products that seem expensive become cheaper than their alternatives. It may not always be Apple for everyone. It could be Samsung, Huawei or Xiaomi, depending on your expectations. 2. More important than the first point I wrote is to avoid unnecessary consumption, and therefore unnecessary production. I am aware that this issue triggers other issues like a butterfly effect, but ultimately the reliability of a product gives you the freedom not to buy anything new for a long time. This perspective also explains why I love Japanese cars. I often hear people say, "If you're buying a second-hand car, buy a Toyota", because people knows the service costs won't be that high. Cars are expensive things that depreciate very quickly, also they are not seen as an investment especially in the country I live in. Then the importance of longevity, durability and reliability is much better understood. ### Don't Schedule The Update On Your Tesla > URL: https://gokmengorgen.net/2025/02/16/dont-schedule-the-update-on-your-tesla/ | Published: 2025-02-16 00:00:00 +0000 UTC | Categories: family, lifestyle | Tags: automobile, opinion, tesla I had an incident that was as fortuitous as the alignment of the holes in Swiss cheese and, frankly, I wanted to take the vehicle to an open field, pour petrol on it and burn it. Fortunately, I am calm now and I think I will pay special attention to prevent that from happening again. Let me tell you what happened first. The fire alarm went off in the building next to our apartment and soon after I saw three or four fire trucks, police cars and ambulances and I realised how serious the situation was. There was an air of panic and I tried to stay as calm as possible and take precautions. I even didn't have time to think about if there was a possibility of the fire spreading or not. At that moment I just wanted to get my family into the car and get away from the crowd for a while. We wouldn't get cold and my wife and kids could sit in the car for a long time, or even sleep if necessary. I had in mind to switch on the camping mode, listen to music, put on cartoons and keep my daughters occupied. Guess what happened? No, it was charged, don't worry. Even if the charge was 10%, that was no problem. There was a bigger problem: ![](/images/tesla_upgrade-edited-scaled.jpg) Yeah, when I needed the car the most, it started updating for half an hour. The car wouldn't move, I couldn't get the air conditioning to work. I also couldn't open the doors in my first try, I had to use the manual handle to get out. I had to deal with this stupid thing while my neighbours were leaving the building with or without their cars. And Tesla didn't help me when we needed it most. We had to wait outside in the cold. Now that I think about it, I realise that **scheduling the update** is actually a feature that shouldn't be there. When I first got the car, I tried it in a supermarket car park to learn how to do the update. It took 45 minutes, and if it had taken another five minutes I probably would have got a ticket, Germany is very strict about parking. I then got into the habit of doing these updates at night, but I have learnt first hand that this is also a very bad idea, as you never know when you will really need the car. I have some questions to Tesla: Does it really make sense to you that for one reason or another you can't drive the car for 45 minutes? I am okay with 2-3 minutes, but how about 45 minutes? Another question, I can imagine how technically difficult this is, but why can't I drive the car during the update? At least that should be possible for a short distance to be able to get away from the scene, and at least I should be able to use the air conditioning. I also have to say that the black screen during this update is very annoying. I didn't know until I tried it that I could wake up the car by touching the screen randomly, or at least use the door openers. I still don't know if it was possible to stop the update somehow. It would be better to see some instructions instead of a black screen. For now, I will keep the following rules in mind for future update: - Update the software as infrequently as possible. Read the changelog and if there is no important update, skip it. - If you're going to update, make sure you don't really need a car. Choose a time and place where it is easier to get a taxi, take the bus or hire a car for a short time. - Ask for an update when you return the car to the service center, or ask for an update when you collect the car and carry it out there. Many EV lovers tell that you don't need to leave your car to the service for updating the software, however it's not such a harmless advantage. I would never ignore the positive aspects that an electric car has brought to my life, but at that moment any internal combustion engine car would have been more than enough, and believe me, I wanted it. I hope that never happens to anyone else. ### Better Enumerations in Python > URL: https://gokmengorgen.net/2024/12/08/better-enumerations-in-python/ | Published: 2024-12-08 00:00:00 +0000 UTC | Categories: software-engineering | Tags: python, rust When dealing with more than one language, we look for similar approaches across languages. In Rust, there's a keyword called `enum` to define and use enumerations. It's easy to use, let's look at this example from the [official document](https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html#enum-values): ```rust enum IpAddrKind { V4, V6, } struct IpAddr { kind: IpAddrKind, address: String, } let home = IpAddr { kind: IpAddrKind::V4, address: String::from("127.0.0.1"), }; let loopback = IpAddr { kind: IpAddrKind::V6, address: String::from("::1"), }; ``` If we want to write this code in Python, we can define two classes and two variables simply. Let’s start with a simple alternative first: ```python class IpAddrKind: V4 = 1 V6 = 2 class IpAddr: def __init__(self, kind: IpAddrKind, address: str) -> None: self.kind = kind self.address = address home = IpAddr(kind=IpAddrKind.V4, address="127.0.0.1") loopback = IpAddr(kind=IpAddrKind.V6, address="::1") ``` It’s absolutely not the same thing with the Rust one but it can help you to meet your expectations about keeping the parameter consistencies between the IP address objects and you can group or filter the objects when you need it. I could also use `dataclass` for `IpAddr`, it came with the version [3.7](https://docs.python.org/3/whatsnew/3.7.html): ```python import dataclasses @dataclasses.dataclass(frozen=True) class IpAddrKind: V4 = 1 V6 = 2 @dataclasses.dataclass class IpAddr: kind: IpAddrKind address: str ``` But as you know, they’re not enumerated indeed. Let's discuss why we need a specific keyword or a language feature for enumerations: - The enumeration class should only do one thing. Currently it's just a class, there's nothing to explain that it's an enumerator. Even if we set the values manually, we don't know which are enumerated types. There's no relationship between the members of the class. - When I read the code, I should quickly understand that it's an `enum` with unique constants, so I can use these constants to define types of some objects and compare them. In other words, if I have an enum type for colors and I want check the type of a color, it should be a `Color` for example. Not integer, not string, I expect a custom enum type. - All enumerations have common basic functionalities. Members should be immutable, iterable, accessible by value and by name, and it should also be possible to get members as a list. I should not have to create a base class to add them to. Actually there's an `Enum` type since [version 3.4](https://docs.python.org/3/whatsnew/3.4.html#enum). But the feeling of using enum in Python is like using an external package like `dateutil`. You're importing `Enum` class, and inheriting it on your enum type. Let me show: ```python from enum import Enum import dataclasses class IpAddrKind(Enum): V4 = 1 V6 = 2 @dataclasses.dataclass class IpAddr: kind: IpAddrKind address: str ``` I think it's still better than using `dataclass`, because it gives some expectations of what we want, there's a specific enum type, there are `value` and `name` attributes for each member, the values of members are immutable, if you try to redefine it, it will give an `AttributeError`, etc. All is fine. ```python-repl >>> home = IpAddr(kind=IpAddrKind.V4, address="127.0.0.1") # type type is enum. >>> home.kind >>> type(home.kind) # there's a value and the type of value is integer. # the best practice is not using the value directly, because 1 is meaningless. >>> home.kind.value 1 >>> type(home.kind.value) # it's also possible to access to name of member. # sometimes we need it if we're getting a data from an external service and want to remap the values, it depends. >>> home.kind.name 'V4' ``` Technically, we have achieved what we want, but let's think about what we can do about usability. Do I have to assign a numerical value to the members? Partially yes, it's not possible to define just member names without values, as in Rust. But there are some options: ```python from enum import auto, Enum # option 1 class IpAddrKind(Enum): V4, V6 = range(1, 3) # option 2: functional way IpAddrKind = Enum("IpAddrKind", "V4 V6") # option 3: just assign the first value class IpAddrKind(Enum): V4 = 1 V6 = auto() # or you can leave it as `None` ``` I'm not sure which option is better, I guess the first one doesn't improve readability, **option 2** is better than **1**. Also I would prefer to write the values manually instead of `auto()` in **option 3**. But yeah, it depends again. It's also possible to set the value of a member by its name. I haven't written all the features of the enum module in this article, but it's also possible to support bitwise operators using `Flag` instead of `Enum`, to determine the member values `str` instead of `int` using `StrEnum`, or to force the value types to be numbers using `IntEnum`, etc. See the [official documentation](https://docs.python.org/3/library/enum.html) for more information. * * * Before I conclude my article, I would like to add one last thing about `enum` use in Rust. I remember that it's possible to use algebraic data types in Rust, but you probably won't need it in Python. Because Rust is not a dynamically typed language and it forces you to work with types every time. Actually there's a better example in [Kobzol's blog](https://kobzol.github.io/rust/python/2023/05/20/writing-python-like-its-rust.html) (see the section Algebraic data types) but let's keep in the same sample here: ```rust enum IpAddr { V4(String), V6(String), } let home = IpAddr::V4(String::from("127.0.0.1")); let loopback = IpAddr::V6(String::from("::1")); ``` How could we write it in Python? Should we use `Enum` or `dataclass`, or just a `class`? ### Syntax Errors in Logical Operators > URL: https://gokmengorgen.net/2024/11/29/syntax-errors-in-logical-operators/ | Published: 2024-11-29 00:00:00 +0000 UTC | Categories: software-engineering | Tags: python Python favours letters and meaningful keywords for the logical operators, and all of them return a value depending on the conditions: 1. `not`: The opposite of a condition, the reverse of the logical state of its operand. If the condition is `True`, it returns `False`, or vice versa. 3. `and`: It needs to compare two operands, It returns `True` if both operands are `True`. 5. `or`: It's similar to `and`, but it returns `True` if at least one of the operands is `True`. The operands do not have to be boolean, Python will return the condition itself through the comparison logic to keep the code writing simple. Now let's look at this output to see the difference between `not` and the other operators, focusing on the position of the hats (^): ``` >>> not File "", line 1 not ^ SyntaxError: invalid syntax >>> and File "", line 1 and ^^^ SyntaxError: invalid syntax >>> or File "", line 1 or ^^ SyntaxError: invalid syntax >>> or 0 File "", line 1 or 0 ^^^ SyntaxError: invalid syntax ``` The syntax error starts in the first character of `and` and `or`, but the end of `not`, after `t`. Is this normal? Absolutely, yes. As I said before, we don't need a comparison for using `not`, but we can not say the same thing for the others, the keyword should be between in two conditions. Now let's try to give a condition for `not` to solve the syntax error: ``` >>> bool(1) True >>> not 1 False >>> bool(0) False >>> not 0 True ``` `1` is a truthy value, it's something like **YES** or **ON** in programming logic, but it returned `False` when we added `not` keyword before `1`. I am aware that I am explaining very simple and boring things but please be patient. Let's make the syntax a bit confusing: ``` >>> not(1) False >>> not(0) True >>> not() True >>> bool() False ``` Wait.. Is there also a built-in function for `not`? No, it's definitely not a function. Honestly, I would expect a syntax error because of the missing space between the `not` keyword and the parentheses, but the formatter tools will probably add it automatically anyway. So, you can consider using parentheses to group the conditions, that's all. And, when you ran `not` with an empty parentheses, it will return always `True` because empty tuples, lists, dictionaries are **falsy** values: ``` >>> not{} True >>> not[] True >>> not () True ``` The best thing to do is to use a code formatter and read the code that way. This is not always possible, so we have to get our eyes used to strange syntax. Let me end the article with a more ugly syntax (but meaningful): ``` if not(False or False) and(True): print("This will print") ``` Will it print the expected output, or raise a syntax error? ### The Future of Mobility > URL: https://gokmengorgen.net/2024/09/01/the-future-of-mobility/ | Published: 2024-09-01 00:00:00 +0000 UTC | Categories: lifestyle, software-engineering | Tags: mobility, opinion, rtos, seiko, tesla I wanted to repost the part about the mobility of an article I wrote in Turkish for [2024 Trends in the Software World](https://mhkoca.medium.com/yazılım-dünyasında-2024-trendleri-7ca5efe239eb) on my blog. The topic of mobility is still in my focus and I am still following the developments closely. * * * ... Now I will end my article with a topic I haven't mentioned before: **Electric vehicles**, or in general terms, automobiles. We have entered a strange period that will closely concern the software industry. It is like the Quartz revolution in watches (or the Quartz crisis if we look at it from the Swiss perspective). To put it simply, a Japanese wristwatch company called Seiko produced the first commercially mass-produced quartz wristwatch in the world, the **Astron** model. In appearance, there were still hour and minute hands on the dial, but instead of mechanical parts, it was powered by an electrical technology. These watches could show the time accurately for longer periods of time than mechanical watches, were lighter, and as production became easier and costs decreased, they took over the watch market. Mechanical watches currently have a certain user base, and there are very valuable companies that produce these watches. [![](/images/seiko-astron.png)](https://www.seiko-design.com/140th/en/topic/32.html) Now we see something similar in the automobile market. An American company called **Tesla** brought electric vehicles into our lives, then Chinese battery and electric vehicle companies sprang up like hotcakes, and European automobile manufacturers fell into the same situation as Swiss watch companies. These electric vehicles have very powerful computer hardware and operating systems, and I think this will be a new field of work for software developers. Cars with internal combustion engines will continue to exist, just like mechanical watches; however, the mobility experience that electric vehicles provide to the user makes us think that we need to look at those vehicles with a different perspective. I just imagine, there is a screen in the middle, being able to put it in camping mode and sleep in the car all night without getting cold, being able to play games, listen to music, have a living space where you can isolate yourself in a capsule, being able to connect to the internet and download applications, being able to do things in the car that you can do on your phone, being able to control the car from your phone or computer, being able to remotely monitor the vehicle's data, being able to access its cameras… I could list more, there are many possibilities and do you know who is needed to do these? Yes, you guessed it. ### Apple Passwords, Finally! > URL: https://gokmengorgen.net/2024/07/14/apple-passwords-finally/ | Published: 2024-07-14 00:00:00 +0000 UTC | Categories: lifestyle, remote-working | Tags: apple, application, opinion **Authy** was my bad decision to use it for two-factor authentication. I remember that I chose it because of its ability to work on both PC/Mac and mobile phone, so if I work on a PC, I don't need to use my phone to see the validation code. The GUI was very bad on all platforms, but it was working at least. Authy is [sunsetted](https://help.twilio.com/articles/22771146070299-User-guide-End-of-Life-EOL-for-Twilio-Authy-Desktop-app), the team explained on their website and stated that it will no longer be supported after March 19, 2024. On the other side, I was using KeePass for storing passwords, backup codes, and other secret texts. The reason for the choice of KeePass was the same: it works on multiple platforms and devices. But there were some problems: - I need to find a way to sync the passwords myself. All KeePass clients have their options, and keeping the files in iCloud is one of them. - Every client comes with a missing feature or a bug. The fact that the application was paid was not a problem for me, but it's not a good idea to make payment for each client. Some clients support multiple platforms, but they don't work as well on all platforms. - I was using KeePassXC on MacOS and KeePassium on iPhone. If I decide to go back to Windows, I will have to find a client for that too. I really don't have time to investigate it... In short, I was not happy with either of them and I started to search for an alternative app. My expectations are: - If it's possible, I want to use one app for two-factor authentication and password storage to reduce app requirements and subscriptions. - I want to choose the sync method myself. You know there were leaks in some applications like [LastPass](https://blog.lastpass.com/posts/2023/03/security-incident-update-recommended-actions) and [OnePassword](https://blog.1password.com/one-breach-one-leak/), and there's no a trustable way of syncing the passwords so each new syncing method means another system that must be secured. I want to continue to use my preferred cloud storage service for syncing the passwords. - And, of course, I still need to access my passwords from multiple devices. I would like to share with you what I prefer at the end of this article, but I really could not find a long-lasting solution to meet these needs. All I'm doing now is waiting, Apple [announced](https://mashable.com/article/apple-password-manager-wwdc-2024) that it is developing a new password manager called "Passwords". I hope it will solve my problems completely. ![](/images/apple-passwords.png) The existing password application in Apple is not a separate application; it's a part of **Settings**. However, you can use it for [two-factor authentication](https://support.apple.com/en-us/102606) and storing passwords. For all other secret texts like backup codes and the secret keys of your blockchain wallets, you can use the Notes app, but don't forget to lock the notes for added security. ### Less Configuration for More Freedom > URL: https://gokmengorgen.net/2024/05/16/less-configuration-for-more-freedom/ | Published: 2024-05-16 00:00:00 +0000 UTC | Categories: lifestyle, remote-working | Tags: emacs I'm very conservative to avoid changing my routines, habits about my preferred software and hardware. But on the other hand, I always follow the new tools and try them as much as possible. It's not easy to change habits, but if I think that the new alternative is better than my current one, and if I think that the new tool will increase my work quality, then I take a risk and replace it. Sometimes I've made the wrong decision, for example I was a [KeePass](https://keepass.info/) user and switched to the [Pass CLI](https://www.passwordstore.org) application because I thought I didn't need such features. But then I noticed that pass app doesn't have a good client for desktop and it's not easy to configure GPG, repository access for iOS. Then I decided to use Apple Passwords to get rid of installing extra password and two-factor authentication applications. Many developers have a repository that contains their public configuration files, and most of these are open to the public. I often look at these repositories, but unlike many people, I prefer to keep my config files as simple as possible, because it's like adding a dependency to your project, every new dependency comes with a maintenance cost. The other main reason is that I want to keep flexibility. I don't have specific requirements for any tools, but I always expect consistency between GUIs, keyboard shortcuts. And I also want to have all the features I need without adding a lot of plugins, or if that's not possible, I expect the plugins to at least be officially supported. So when I discover a new tool, or want to replace my existing tool with another, I follow these steps: 1. **First, check your budget if the tool is not free.** Some tools may come with a free subscription, but that does not mean the tool is always free. I don't have a hard and fast rule here, but I definitely expect the paid tools to be better than the free alternatives. 3. **Prefer the one that is ready to use quickly.** I could prepare a server to host my blog. I have to configure the virtual machine's swap area, prepare some cron jobs to back it up, use some plugins to cache and optimise WordPress. Or I can host my site directly on [WordPress.com](http://wordpress.com). I preferred the second option, but considering the first rule, I had a budget for it. 5. **Look at all the features, but compare the options based on the features you really need.** I used Evernote for a long time, then decided to investigate an alternative because of new expectations. Joplin was a good Evernote alternative, but I never used all of its features. So I even tried Apple Notes before making my final decision. 7. **Own fewer extensions, use all features efficiently.** If I'm not sure about the benefit of a tool or a feature of a tool, I temporarily stop using it and make a note of what I've lost. Tools are like a knight's sword and shield: the more effectively we use them, the better they help us do our job. 9. **Simplicity is fine to avoid distraction, but do not ignore helpful things.** I don't really need line numbers in my editor, but breadcrumbs are helpful to remember class name, module name, file path, etc. These rules also help with my hobbies and family time. The older you get, the more important it becomes to get things done on time. ### The Simplest Car Delivery Experience > URL: https://gokmengorgen.net/2024/04/23/the-simplest-car-delivery-experience/ | Published: 2024-04-23 00:00:00 +0000 UTC | Categories: family | Tags: automobile, tesla I really like Japanese cars. There are Japanese brands that are durable, safe and have very good parts and service support. Toyota and Lexus are my favourite brands. But on the other hand, I was looking for value for money and I knew that **Tesla** was unbeatable in that regard. My beloved wife and eldest daughter loved the Tesla, while I, as a gourmet car guy, preferred the Lexus. My wife suggested that I test drive both the Lexus and the Tesla. I tested the Lexus ES350h first and fell in love with the car. Everything was just as I wanted, I never had to change my old habits and because it was a hybrid, the fuel consumption was very low. Most importantly, it was not an SUV, which for me is a great opportunity that sedans are still being produced. Then we tried the Tesla Model Y. I felt I had to change all my habits. I had to get used to knowing when to charge it, where to charge it on the way, that I couldn't just park it anywhere because it was a bit big, that it didn't even have a physical key and a simple start button, and I had to get used to those innovations. On the other hand, I was convinced that it made more sense to buy an SUV for my little daughter's pram and lots of other stuff, and I respected my wife's choice. I'm not very good at communicating because I'm hearing impaired. However, the Tesla sales people were very understanding and I was able to complete most of the process virtually via the Tesla app and email. In fact, I can say that the most difficult part for me was registering the car and getting a licence plate. I was able to do that with a little bit of effort. After receiving the number plate, I contacted Tesla and was delighted when they told me I could pick it up now, even though the scheduled delivery date was the next day. They installed the number plate, gave me a briefing and helped me set up the phone. I was surprised to see that the battery was 79% full. None of the cars I've bought so far would have got that far, I could only go 3km at the most. So after a short test drive and making sure there were no problems, I wanted to leave them a tip, but they refused. I am still a fan of internal combustion vehicles, but I really congratulate Tesla on the sales experience. I have to say that I also think they have succeeded in terms of accessibility. I don't like to give out referral links, but if you're interested in a test drive, I can forward it to you privately. ### How did I Meet Pardus? > URL: https://gokmengorgen.net/2024/04/18/how-did-i-meet-pardus/ | Published: 2024-04-18 00:00:00 +0000 UTC | Categories: lifestyle | Tags: linux, pardus When someone asks me about the starting point of my career, I always tell them about my Linux/BSD adventure. These operating systems still exist and most people know them, but not everyone knows about Pardus, and even if they do, it is not the same Pardus I mean. ![](/images/pardus-linux-logo-thumbnail.png) I grew up in a house without internet and the only connection to the world was through technology and gaming magazines. I used to rewrite the articles in magazines that I liked and wanted to understand on my typewriter because I read too fast and didn't understand anything, so the typewriter was kind of slowdown for me. Sometimes codes were shared in magazines and they would also write what the output would be when we compile and run these codes. That's something a typewriter could never do. So I grew up dreaming of owning a personal computer until I started university. When I got my first computer, I remember that the operating system installed on it was FreeDOS. Honestly, I didn't even know how to connect to the internet, so I looked into installing another operating system instead. Windows was a very nice alternative, but it was expensive and I had to buy a license. Then I had heard a lot about Linux from magazines, but before that I want to try FreeBSD first, I don't know why but I thought that it may easier than Linux. There were many distributions of Linux and I couldn't decide which is better for me. But FreeBSD is already a ready-to-use operating system. I already had magazines with information on how to install FreeBSD and how to connect to the internet. I managed with that for a couple of months. Then I discovered some great Linux communities: forums, rooms on Freenode, events, new friendships, spontaneous meetings, and so on. The strongest of these communities, in my opinion, was [Pardus](https://en.wikipedia.org/wiki/Pardus_\(operating_system\)). It's a Linux distribution that is developed by [TÜBİTAK](https://tubitak.gov.tr/en), and I did my intern in this significant instituon. TÜBİTAK means "Scientific and Technological Research Council of Türkiye", is the leading agency for management, funding and conduct of research in Türkiye. When I started to use Pardus, most of the core tools of the operating system was developed in Python: PiSi, Kaptan, YALI, pyxemel, etc. Normally I was planning to learn Ruby but all my friends in Pardus community preferred to continue with Python. I don't regret it but since I couldn't use Ruby on Rails in any project, it remained a disappointment to me. But on the other hand, I got my first salary with Django and it wasn't bad either. Pardus is a Debian based distribution anymore. I don't know what the community is doing these days but I think those old days are over for me. ### Key Museum > URL: https://gokmengorgen.net/2024/04/14/key-museum/ | Published: 2024-04-14 00:00:00 +0000 UTC | Categories: hobbies | Tags: alfa-romeo, automobile, bmw, cars, classic-cars, porsche ![](/images/1d4726b1-5503-40a5-af09-726afedf1209_1_102_o-1.jpeg) ![](/images/2f01f8c4-0e68-43c6-ae3f-dd8e56c33c25_1_105_c.jpeg)![](/images/26e28d20-7289-44da-9968-6f285fe48556_1_105_c.jpeg) I discovered a beautiful car museum in Izmir. I flew to Izmir at the invitation of my former colleague and we met at Adnan Menderes airport. We rented a car to avoid wasting time on public transport and drove straight to Torbalı and the museum. The museum, which opened its doors in 2015, offers visitors a delightful journey through the evolution of automobile history. Upon entering, one is greeted by a fascinating array of iconic cars representing different eras, from the past to the present. The museum's collection not only showcases well-known classic cars, but also includes rare gems that spark the imagination and transport visitors to bygone times. Apart from the impressive car display, the museum features dedicated areas for motorcycles, accessories, and intricate car mockups, adding depth and variety to the overall experience. Describing every nook and cranny of the museum would spoil the element of surprise for future visitors, but rest assured, there is much more to explore and marvel at. For those with an interest in automotive history, or simply a curiosity to witness the evolution of transportation, this museum comes highly recommended. Whether you're a fervent car enthusiast or simply passing through the area, it's an experience not to be missed. Below are pictures of some of the cars I have chosen, along with a description and why they are special to me. ## Alfa Romeo Giulietta ![](/images/06a7a9be-498c-410b-983c-177147b405e0_1_105_c.jpeg) One-door convertible (cabriolet), red color, 1963 model. It has an owl-like design with a bird's beak grille and round headlights. The window edges, wipers, bumper, bonnet, and doors are all chrome-plated. There is a mirror on the left side and in the center above the dashboard for looking back, but not on the right side. Since the steering wheel is also on the left, you have to do the famous shoulder view check, which the Germans call "Schulterblick", looking back from the right shoulder to look at the right rear. Even though it has not been renewed for a few years, the Giulietta series still exists on the roads as a 5-door C segment vehicle. Alfa Romeo now belongs to the Stellantis group, I guess we will see new models with the engine of this group. But I don't know if the old Alfa Romeo spirit will remain. ## MG MGA MKII ![](/images/0a7c68eb-7551-44d6-8418-004d056b9248_1_105_c.jpeg) Blue in colour, the side mirrors on both sides are not at door level, but a little further forward, on the sides of the bonnet. Again, as with Alfa Romeo, there are round headlights, and again, chrome details are favored in many places. I think this was the fashion of the 1960s. Alfa Romeo was an Italian brand, MG a British one. But there is a strange similarity in the designs. Again a single door, again a convertible. I wonder what the rivalry was between them. I have never seen MG on Turkish roads, but I tried to understand what the Chinese company SAIC aims after buying MG. It is a bit like the Volvo - Geely relationship, or Lancia - Stellantis. Instead of creating a brand from scratch, they are trying to capture the old market by using the pre-existing image. So MG used to have some prestige. ## Porsche 356 A ![](/images/714640f2-473b-4d77-a967-960c2df006b3_1_105_c.jpeg) Another 1957 car, this time a Porsche. How similar the designs were back then. Again single doors, again chrome details, again convertible. But this time there's no radiator grille, and that's the most obvious difference. The engine is in the back, and it's rear-wheel drive. The grey colour suits it very well. I was playing a similar car in **Need For Speed: Porsche Unleashed**, I think it was a coupe model with a convertible top. This model no longer exists; but I think the 911 has a similar design. It is kind of a successor to the 911, and as far as I know, while all of Porsche's models are turning into electric vehicles, the 911 will still continue to have an internal combustion engine. I think it will fight until 2035 for an engine that runs on a fuel with low or near-zero emissions. ## Jaguar E-Type ![](/images/a3570973-fb0a-4f1c-8fb8-d5582038209b_1_105_c.jpeg) Yet another car that I didn't see in real life, but I know that this design is iconic and remember this car in some popular old and new movies. The most distinctive feature of this car is that the front bonnet is very long and there's a hump running down the center of the bonnet. The front bumper is there on the right and left side, not in the middle, because there is a radiator grille and there is not even a place to mount the number plate. There is also a wheel design similar to the wheels of old bicycles. It's a roadster; if I had a garage, it'd be a nice alternative to the Mazda MX-5. But it's so old, I don't know if they make them anymore. Jaguar is now more prominent with its SUV models. In fact, the autonomous driving technology company called [Waymo](https://waymo.com/) in the USA prefers these SUV models of Jaguar for their projects. ## BMW E30 M3 Coupe & GTS ![](/images/3573698a-2f69-4ebc-85a7-2edeb5bed1bf_1_105_c.jpeg) ![](/images/21ae62c8-beab-4efc-972b-21ba2125f933_1_105_c.jpeg) This is the design that comes to my mind when I think of BMW. A couple of round headlights on the left and right, grille with chrome ornaments in the centre, M3 logo, spoiler; light, small but powerful car. It already had a beauty that defies the years, I don't understand why they tried different things. The next orange car in the photo was M3 GTS, which was released in 2011. It may be the last one that I followed. Oh wait, M2 2023 may be an exception, it's still beautiful and doesn't seem like the other BMW models. There were quite a lot of BMW models in this museum, because I understand that the owners of the museum have a business partnership with BMW in Turkey. Therefore, if you like BMW, I recommend you to visit the museum. * * * I am not a classic car lover or someone who rejects modern technologies. However, in order to understand the identity of some automobile brands, to sympathize with and recognize some of them, it is necessary to know and learn the history of these brands. Automobile museums exist precisely for this purpose. It is not enough just to visit a museum. One of my short-term goals is to visit the Rahmi Koç museum (again), the Classic Remise museums in Berlin or Düsseldorf, the Mercedes museum in Stuttgart, the BMW museum in Munich and all other museums that can be visited and to have a culture about cars. ### Curiosity in Children > URL: https://gokmengorgen.net/2023/09/12/curiosity-in-children/ | Published: 2023-09-12 00:00:00 +0000 UTC | Categories: family This isn't advice, but I'd like to share what I did to get my daughter interested in coding. Like any parent, I showed her all sorts of things to learn coding at a young age, it was zero curiosity. After a while I couldn't understand why I had done this, I just put it on the shelf and let her do whatever she wanted, I just watched and expected her to ask for something. She said she wanted to write and draw on the walls of her room, I said yes, you can, on the other hand I was thinking about the price of repainting the walls. But anyway. Then, while I was playing a game on my Nintendo, the good questions came. "Are you playing this thing?", "Can it jump?", "Can you change its clothes?", "Does it have this function?"… That was a good point to start showing her something about coding. I started by showing her how to play **Minecraft** and **Animal Crossing**. She played the games in creative mode for a while. Even though what she can do in these games is very broad, she felt restricted in some places. For example, even though there was no cooking feature in Animal Crossing in the past, she thought she could put things in the fridge and cook with them. Then the expected question came. She said, "How are these features added to this game, can I add them too?" I explained that it is not so easy, but there are ways to do it. First of all, you have to learn how to code, design, use programmes… In the meantime, she had already digitised her drawing on her own, using applications thanks to her tablet and pen, drawing what she wanted to do in the game, adding simple animations, even video and voice-over. But again, she realised that something was missing. Her eyes were used to coding from my monitor since she was a baby. One day she came to me and said, "Dad, I want to code a game too. So I introduced her to [Swift Playgrounds](https://www.apple.com/swift/playgrounds/). We haven't finished it yet, but I think she'll be able to finish it when she has time from her homework. The funny thing is that this is the same app, Swift Playgrounds, that I showed her a couple of years ago to teach her how to code bu she was disinterested. The second thing I would say is that I think [code.org](https://code.org/), [Tinkercad](https://www.tinkercad.com/), [Scratch](https://scratch.mit.edu/), it doesn't matter. The first step should be to foster a sense of curiosity. Isn't that how we started? If there's no curiosity, I don't think it's a good idea to teach kids to code before they ask. Honestly, I didn't want my dad to teach me his business when I was a kid. ### Configuration Updates With Emacs 29 > URL: https://gokmengorgen.net/2023/05/07/configuration-updates-with-emacs-29/ | Published: 2023-05-07 00:00:00 +0000 UTC | Categories: software-engineering | Tags: emacs As I mentioned in my [last post](https://gokmengorgen.net/blog/2023/04/status-update-on-emacs/), I started using **VSCode** to see what I’m missing and I thought that it’s a good time to take all the risks and break my Emacs configuration. In the last changes, I tried to use the built-in alternatives of the packages like **eglot** instead of **lsp-mode**. Now I’ve made the decision to update Emacs to version 29. When I first switched to **Emacs 28**, all my performance problems were solved thanks to native compilation support. Most of these problems were caused by **LSP**[1](https://gokmengorgen.net/blog/2023/05/configuration-updates-with-emacs-29/#fn:1) and it was very annoying to wait even half a second to see syntax errors in the code. Now I don’t close Emacs on the server for months. This was the most significant change to Emacs 28 that I can’t forget. Now, if you ask what the equivalent important update is on **Emacs 29**, I guess I can claim that Emacs has become quite useful even if you don’t install any extensions. Many extensions I used are now included in the project, for example: - [Modus-Vivendi and Modus-Operandi](https://protesilaos.com/emacs/modus-themes), the themes I have been using for years and cannot give up, now come in. - The package configuration tool [use-package](https://jwiegley.github.io/use-package/) is now included. - The internal LSP service [eglot](https://github.com/joaotavora/eglot) is now available. I’ve previously used the [lsp-mode](https://emacs-lsp.github.io/lsp-mode/) extension. - For [tree-sitter](https://emacs-tree-sitter.github.io/) support, nothing needs to be installed any longer. Furthermore, **TRAMP**[2](https://gokmengorgen.net/blog/2023/05/configuration-updates-with-emacs-29/#fn:2), which functions similarly to VSCode’s remote development extensions, has started to support Docker and Kubernetes; however, I have not yet verified whether **LSP** can be used in a remote development environment. I prefer to use **MOSH**[3](https://gokmengorgen.net/blog/2023/05/configuration-updates-with-emacs-29/#fn:3) to connect to the server and execute Emacs remotely, unless this occurs. As many extensions were included, I also reviewed the other extensions I used. Although it is possible to use Emacs without any installed extensions, it is very difficult for me to give up some extensions. For instance, [magit](https://magit.vc/) is far superior to many competitors, both as an Emacs and a git client. Another extension that I can’t give up is [doom-modeline](https://seagle0128.github.io/doom-modeline/). The default mode-line view in Emacs is also quite ineffective. It wastes space, uses the right half of the line very inefficiently, and shows minor modes needlessly. I began utilizing **doom-modeline** to address all of these issues. You can see the screenshot to see how it looks: ![](/images/minibuffer-text-completion.jpg) With Emacs 29, I suppose the major modification I made was to cease using popups for text completion. I’m not sure if it’s a good idea yet, but I’ll keep trying. I use all of Emacs’ capabilities that make use of minibuffers considerably more effectively by using the following extensions: - [consult](https://github.com/minad/consult): an extension for minibuffer completion. - [vertico](https://github.com/minad/vertico): a minibuffer completion UI. It’s necessary for consult. - [orderless](https://github.com/oantolin/orderless): completion style with various algorithms to find more search results. - [marginalia](https://github.com/minad/marginalia): an extension to see more information about the search results. When I started using minibuffer instead of popup for completion, there was a lot of space left for a second text completion. so I thought why not use [copilot](https://github.com/zerolfx/copilot.el) or [codium](https://github.com/Exafunction/codeium.el). Look at the screenshot to see how it works: ![](/images/copilot-completion.jpg) I didn’t turn on a lot of UI components, like line numbers, tabs, fringe, and scroll bars, so it’s likely that my configuration isn’t optimal for a graphical user interface. And to be honest, I didn’t need it; perhaps I’ll keep the UI in zen mode and continue using Emacs in my preferred terminal program, WeztTerm. But for the time being, I intend to continue working with VSCode. You may find a new version of Emacs with my setup in my [emacs.d repository](https://github.com/gkmngrgn/emacs.d) if you want to try it out. * * * 1. LSP: Language Server Protocol [↩︎](https://gokmengorgen.net/blog/2023/05/configuration-updates-with-emacs-29/#fnref:1) 3. TRAMP: Transparent Remote Access, Multiple Protocol [↩︎](https://gokmengorgen.net/blog/2023/05/configuration-updates-with-emacs-29/#fnref:2) 5. MOSH: Mobile Shell [↩︎](https://gokmengorgen.net/blog/2023/05/configuration-updates-with-emacs-29/#fnref:3) ### Status Update on Emacs > URL: https://gokmengorgen.net/2023/04/10/status-update-on-emacs/ | Published: 2023-04-10 00:00:00 +0000 UTC | Categories: software-engineering | Tags: emacs, vscode I’ve used Emacs for years, and it’s not easy to get rid of this archaic (what?) editor. Although it helped me do my job better, my setup was not as stable as in the editor. When I started working as a web developer, I was installing all the project requirements on the local machine, even though I was not using virtual environments. Emacs was good enough to make development possible. Then, I started using tools like vagrant, docker, and virtual environments that made it easy to install the project but difficult to use Emacs because I needed to configure the editor to find the right Python interpreter, Node version, etc. Having the language server protocols (LSP) was a great help, but I still had to create a virtual environment for each project. Then I switched to remote development; I had a remote server to access the same development environment from all my devices. I was using a good terminal emulator like WezTerm, connecting to the server using MOSH or Eternal Terminal, and running Emacs on the server remotely. This has never been as comfortable as working locally. In each case where my setup has changed, I have updated Emacs and reconfigured it for the new environment. If you take a look at my Emacs configuration, you will see that I’m using vanilla Emacs with the minimum configuration, and I try to use built-in packages as much as possible. But now I’m at a new crossroads because I started using AI tools actively and am getting bored waiting for the tools to support my editor. I’m looking at the GitHub Copilot, and even they don’t have a plan to support Emacs officially. You can say that it’s a tactic to force them to use their own editors or that they don’t have time to support all the editors. Maybe it’s better to help the community take initiative for preparing the extension. But anyway, that’s not fair or helpful for maintaining the diversity of the editors. Probably it’s not easy to change my habits quickly, but I plan to use VSCode for a while and see what I’m missing. I know that VSCode has good remote development tools and official GitHub Copilot support. During this period, I will update Emacs to have the same features as VSCode and try to use it again. For now, I want to compare the two editors for the extensions I’m using in Emacs. These extensions are mostly not needed on VSCode because they are built-in features: - **company, company-prescient:** autocomplete extension. - **ctrlf:** better search and replace. - **deadgrep:** ripgrep integration for Emacs. I’m using the built-in search and find commands on VSCode. - **diff-hl:** shows git diff in the fringe. - **eglot:** LSP client. - **find-file-in-project:** Helpful for finding a file in a project. - **multiple-cursors:** Another extension for editing multiple lines at once. - **expand-region:** Not easy to do this on VSCode (CTRL+CMD+SHIFT+Left what the hell?) but yes it’s a built-in feature. - **magit:** Git app for Emacs. I don’t think that I can find an equivalent in any editor. Don’t suggest me GitLens, please. - **minions:** Hides minor modes on Emacs mode line. Not necessary on VSCode. - **modus-themes:** My favorite theme for Emacs. I’m using the GitHub theme on VSCode. - **puni:** Structured editing tool for Emacs. Not sure if I can find an equivalent on VSCode. - **vertico, vertico-prescient:** Similar to CTRL|CMD+SHIFT+P or CTRL|CMD+P on VSCode. - **tree-sitter, tree-sitter-langs:** Not sure if VSCode needs this extension, but it’s a great synax parsing library for Emacs. - **unfill:** For unfilling paragraphs with a shortcut. My Emacs configuration is available on [GitHub](https://github.com/gkmngrgn/emacs.d). ### Return Back to Blog > URL: https://gokmengorgen.net/2022/11/20/return-back-to-blog/ | Published: 2022-11-20 00:00:00 +0000 UTC | Categories: lifestyle | Tags: meep "__Hey, Twitter is not like in the good old days, I'm switching to Mastodon.__" No no, I’ll not say this. I already tried that, and I couldn’t succeed. Because I was alone and my friends continued to stay on Twitter. Now, after the latest news about Twitter layoffs, I see a similar migration again, but I don’t think it will be successful either. So the main thing I want is to be a platform-independent content creator; if someone wants to reach me, I want them to visit my website, or if someone has negative thoughts about me… Maybe they can write me an email, or I really don’t care. I had a plan in mind: ### 1\. Periodically delete unnecessary tweets on Twitter (98% of them are) I wrote a small application in Python because I didn’t want to allow any third-party software. Feel free to look at the project if needed; the name is [meep](https://github.com/gkmngrgn/meep). When I had time, I filtered and reviewed my tweets by year and keyword. Then, I deleted the unnecessary ones and searched for inspiration to write new blog posts. ### 2\. Create accounts on several alternative social media servers I will use my website as microblogging and share my posts on multiple social accounts like Mastodon, Cohost, etc. ### 3\. Automate the synchronization in one direction Using applications such as [IFTTT](https://ifttt.com/) and [Zapier](https://zapier.com/), I have automatically shared my new blog posts to social media via RSS. – After that, I don’t care anymore if Twitter shuts down or a Mastodon server crashes. I have the data, and it is always visible on my website. I advise. ### My Game List in Itchio Bundle > URL: https://gokmengorgen.net/2022/03/09/my-game-list-in-itchio-bundle/ | Published: 2022-03-09 00:00:00 +0000 UTC | Categories: entertainment | Tags: itchio The bundle is [here](https://itch.io/b/1316/bundle-for-ukraine); I will update the list when I finished a game. 1. [Crosscode](https://radicalfishgames.itch.io/crosscode) 3. [Gonner](https://rawfury.itch.io/gonner) 5. [Inmost](https://chucklefish.itch.io/inmost) 7. [Sundered](https://thunderlotus.itch.io/sundered) 9. [Baba Is You](https://hempuli.itch.io/baba) 11. [Moon Hunters](https://kitfoxgames.itch.io/moon-hunters) 13. [Celeste](https://mattmakesgames.itch.io/celeste) 15. [Towerfall Ascension](https://mattmakesgames.itch.io/towerfall) 17. [Towerfall Dark World](https://mattmakesgames.itch.io/towerfall-dark-world) 19. [Minit](https://devolverdigital.itch.io/minit) 21. [They Bleed Pixels](https://spookysquid.itch.io/they-bleed-pixels) 23. [Long Gone Days](https://laburatory.itch.io/lgd) 25. [Midnight Scenes](https://octavinavarro.itch.io/midnight-scenes-the-highway) 27. [Midnight Scenes Episode 2](https://octavinavarro.itch.io/midnight-scenes-the-goodbye-note) 29. [Hidden Folks](https://adriaan.itch.io/hidden-folks) 31. [Lenna’s Inception](https://tccoxon.itch.io/lennas-inception) 33. [Golf Peaks](https://afterburn.itch.io/golf-peaks) 35. [Detective Case And Clown Bot](https://nerdmonkeys.itch.io/detective-case-and-clown-bot-in-murder-in-the-hotel-lisbon) 37. [Pushamo](https://beanborg.itch.io/pushamo) 39. [Cruel World](https://droqen.itch.io/cruel-world) 41. [Gun Rounds](https://blabberf.itch.io/gunrounds) 43. [Sokobond](https://draknek.itch.io/sokobond) 45. [Haque](https://supertry.itch.io/haque) 47. [Schildmaid Mx](https://hitp-studio.itch.io/schildmaid-mx) 49. [Magnibox](https://josephgribbin.itch.io/magnibox) 51. [Ultra Hat Dimension](https://eniko.itch.io/uhd) 53. [Rebop Blasters](https://dean-sick.itch.io/rebop-blasters) 55. [Explorers](https://trasevol-dog.itch.io/explorers) 57. [Delver](https://priorityinterrupt.itch.io/delver) 59. [Speer](https://ohsat-andrej.itch.io/speer) 61. [Upsquid](https://01010111.itch.io/upsquid) 63. [Danger Crew](https://dangercrewgame.itch.io/dangercrew) 65. [Wand Wars](https://moonradish.itch.io/wand-wars) 67. [Paranoihell](https://lum-scum.itch.io/paranoihell) 69. [Dogs Throwing Words 2](https://lilyv.itch.io/dogsthrowingswords2) 71. [Vylan](https://mostlymadproductions.itch.io/vylan) 73. [Snack Scoffer](https://niall-chandler-games.itch.io/snack-scoffer) 75. [Micro Dash](https://inarisoft.itch.io/micro-dash) 77. [Crystal Anomaly](https://minotalen.itch.io/crystalanomaly) 79. [Bouncy Cars](https://assertchris.itch.io/bouncy-cars) 81. [Bugspeed Collider](https://ghostbrite.itch.io/bugspeed-collider) 83. [Hack Grid](https://daisy-games.itch.io/hackgrid) 85. [Death Drives A Bus](https://tallbeard.itch.io/death-drives-a-bus) 87. [The Machines Garden](https://toomuchtomato.itch.io/the-machines-garden) ### Remote Development Environment > URL: https://gokmengorgen.net/2022/03/06/remote-development-environment/ | Published: 2022-03-06 00:00:00 +0000 UTC | Categories: remote-working _When I started using Windows in 2014, I continued to keep my development environment on Linux. I first did this with Vagrant; then, I used WSL, Docker, WSL2. I had an idea forming in my head ever since. I’m already using two different systems on a computer simultaneously; is it possible to use one in a thin client and connect to the other remotely?_ ## PURPOSE Let me first start by explaining why I want to do this: - I need a powerful computer to be able to use two systems at the same time. But, on the other hand, I would like to use a lighter computer with better screen quality and longer battery life instead of a more powerful computer. - I already have a computer provided by the company I work for, and I don’t want to move two computers at once. And I don’t want to keep my files and hobby projects on the workstation. - Sometimes I want to connect to my development environment from another device such as a tablet and phone. To do this, I have to keep my computer turned on all the time. Now let’s look at where I can keep the development environment and investigate the other alternatives. ## PLAN Creating a virtual server using a VPS service like DigitalOcean or AWS Lightsail was my favourite option; however, when the need for RAM increased because of Docker, it’s possible to buy a Mac Mini every two years with the cost of VPS. So I eliminated this option. My first thought was to make a portable PC using Raspberry Pi 4. Since I don’t have enough experience in this subject, I thought I could do it; but as the system requirements increased, there were quite a few problems, and it moved away from the structure I imagined. For example, when I added an SSD, there was a heat problem; I had to add a heatsink to solve it. In addition, it needed an adapter to meet the power, and it wasn’t easy to find an excellent case to match it. ![](/images/remote-development-environment_1.png) Even though I looked for ready-made solutions later, I couldn’t find a product that I would like. So finally, when the performance achieved according to the cost did not satisfy me, I turned to other alternatives. There’s no advantage of having a laptop for the development environment, but I wanted the device to be portable because I occasionally travel. I also thought of keeping the server machine in the same place all the time, but I wanted to be able to physically access the device in case of an emergency such as a system error or power outage. I also looked at other alternatives such as Intel NUC and Beelink; I was disgusted with their brick-like adapters, so I preferred buying a Mac Mini because the case already includes the power supply. However, I still don’t understand why they can’t fix this adapter issue on PCs. ![](/images/remote-development-environment_2.png) ## CONNECTION After purchasing the machine that will provide my development environment and installing it at home, I made the first updates. First, I reviewed the power consumption settings to prevent the device from going into sleep mode. ![](/images/remote-development-environment_3.png) Then I determined the programs I would use to connect to the computer. I’ll explain later why I use multiple methods and tools to connect to a device: 1. **TAILSCALE:** The first thing I need to know to connect the server is a fixed address of my server. I’m using TailsScale, which uses WireGuard technology for that. For example, when I set the name of my server as **gerudo**, I can connect it by saying `ssh gerudo`. The device I use as a client must also be registered in my TailScale account to find the address where gerudo is registered. 3. **SSH & MOSH:** The most necessary applications I used in the terminal are SSH and Mosh. Mosh prepares a more stable connection than SSH, but you need to configure your terminal to support 24-bit colours. 5. **REALVNC:** There is no need to install a separate VNC application for macOS, but you can see the machine’s address when you log in with the RealVNC account. But if you are using TailScale, you can connect with any VNC client by saying `vnc://machine-name`. I only use it when necessary. 7. **DUET DISPLAY:** It helps me to use my iPad as a primary or secondary display. The server-side of the development environment is ok; now we can forget that part at home. Let’s come to the client part, which we will always have. You decide according to your situation, I will explain my preferences: 1. **WORKSTATION:** I can access my editor via **SSH** or **MOSH** from the computer provided by the company, and I can access the desktop with any VNC client. 3. **IPAD:** It’s better to use a tablet instead of carrying two laptops for me. I use the iPad to access my private files and use it as a second display for the workstation. Sometimes I don’t take my workstation, and I connect to my server using Blink from the iPad. 5. **IPHONE:** Although I prefer not this method, it’s cool to access the graphical interface and do small tasks on the server. I just use RealVNC. As I said before, I use TailScale on all devices. Maybe not needed on the phone because RealVNC already knows the machine’s address via the user account. Now let me explain why I use multiple connecting methods to the server. Don’t think that this whole structure is working smoothly; it’s not easy as it seems; there are at least a few critical problems I experienced once. ## PROBLEMS The first problem is that you need a display until you prepare your login account on Mac Mini for the first time. If I could use Raspberry Pi 4 as a server, it wouldn’t have this problem, but there is such a problem for Mac Mini, unfortunately. The other problem is making the first internet connection when you move the server to a different place. If you use iPhone, you don’t need to worry about that because it shares connection info between the devices. But what if you don’t have an iPhone or iPad? So yes, you need a display again. Another problem is with Duet Display. If the server restarts and you log out somehow, you need to log in again to use Duet. It is possible to solve this problem by automatic login; however, it’s creating security weaknesses, and it’s not a reasonable option. So instead, I connect with a VNC client and log in once. Then I continue with Duet Display. Let’s talk about work-related issues a bit. I’m neither not a frontend nor a mobile developer so I can work with just a terminal. Sometimes I’m interested in game development; I plan to use Duet Display for that. If I were a frontend user, I think I could use my workstation as a client and keep the code on my server; and I would prefer to debug the code from the browser on my workstation. On the other side, I think none of what I said would work in mobile development. If you have any suggestions on that, I would love to know. ## FINALLY Due to the frequency of power and internet cuts in Turkey, adding UPS (uninterruptible power supply) to this kind of remote development environment is necessary. Apart from that, you can get paranoid and consider making a mini-robot that you can control with wifi and press the computer’s power button. ### Pair Programming > URL: https://gokmengorgen.net/2021/10/20/pair-programming/ | Published: 2021-10-20 00:00:00 +0000 UTC | Categories: remote-working _Pair programming has been a known and applied method for a long time. I know that it has more than one purpose and practice, but I want to say some things about an expert and a novice working together._ ## Investigation For a long time, I went to the dental clinic for braces treatment, and after my treatment was over, I had surgeries two times (no worries, I’m fine). Sometimes there was more than one doctor at my appointments. One was relatively more experienced than the other and would generally instruct the less experienced to do what they would have done. The novice one was following the instructions without asking any questions because there was an actual patient, and they were trying to imitate the expert one as much as possible. After a while, the novice was now taking care of the appointments alone. Another thing I observed was that not every novice doctor always matched with the same expert. I think that is an essential detail because it explains that experts also go through similar processes. ## Pair Programming In the projects I’m working on, there are code reviews, we’re writing documentation, and we update it as new questions come in from novices. Also, I don’t miss to say to the novices that they can ask me any questions, then I tell them that I’ll answer when I’m available, but none of these solves the main problem. So I realized too late the importance of pair programming. To elaborate on the main problem, let’s think about the topic using the same metaphor: Consider there’s a novice doctor who cares for you for the appointment, and there’s no one else that helps them. They can’t make the patient wait for asking a question to an expert doctor and can’t record the operation during the treatment and ask for a talented doctor to review how they do the treatment later. So the patient comes to the appointment, they do what they should do, and the patient goes out when the doctor completes their work. To speed up the adaptation of a novice to the team and save time for other friends in the team, it may be a good idea to give them a critical job that will directly affect the quality of the production, directing them verbally or in writing. So the novice will implement the workflow a few times under the observation of an expert, and the expert will let them take a risk. Let’s move on to the second important issue, the case of experts and novices randomly matched every time. There are a few key benefits this provides: 1. The novice receives training from multiple experts instead of a single expert. If there is any inconsistency between the information received by the experts, the novice will object and warn the expert. 3. An expert will resolve this inconsistency by talking with other experts if necessary and will inform the final decision. 5. Both the novices will meet with multiple experts, and the experts will contact multiple novices. Thus, coworkers will establish relationships with each other one through their positions, not personally. I find the benefit mentioned in the last item very important. It is crucial that the projects are independent of the person and that the positions are fixed and maintained by different employees. If a developer can quit a project quickly, the project is independent of the persons. Therefore, we can consider it the success of the developers of the project. The case is also good for the developer because they will strike a snag-less when changing their team or project. ## The Cost of Making Busy the Expert In pair programming, the time spent by two people doing the same job will be multiplied by two. However, it can be misleading to calculate the person/time with such straightforward logic. This cost is bearable in the long run to reduce the time it takes for a novice to get used to the job and take on responsibility. The key here is to keep an expert busy for a maximum of one or two hours a week, ensure that each expert takes responsibility, and share tasks fairly. The second point to reduce the cost is that the job selected for pair programming has to be the expert’s job, not the novice’s. In other words, the expert will give one of their tasks to the novice, observing them if they completed the task as well. In this case, the only cost for the expert will be wasting some time by giving the job to a novice instead of quickly doing it independently. But, as I said before, this cost is bearable in the long run. ## Resources As I wondered and researched this subject, I realized that it was a little more complicated subject than I had anticipated. Therefore, without prolonging this article, I would like to inform the reader by sharing some resources. - [Awesome Pair Programming](https://github.com/kkemple/awesome-pair-programming): Awesome pages are famous; they even made a page of pair programming. I looked at this before Wikipedia. - [Pair Programming (Wikipedia)](https://en.wikipedia.org/wiki/Pair_programming): General information about pair programming here. The pair programming method I mentioned is an expert & novice. - [Pair Programming (Martin Fowler)](https://martinfowler.com/articles/on-pair-programming.html): If you’re wondering what Martin Fowler thinks about pair programming, yes, he has an article about it too. Pretty detailed post. - [Pair Programming (The Beauty and Joy of Computing)](https://bjc.edc.org/bjc-r/cur/programming/1-introduction/2-gossip-and-greet/1-pair-programming.html): A short article explaining how (not) to pair programming. - [Pair Programming (Laurie Williams - NC State University)](https://collaboration.csc.ncsu.edu/laurie/Papers/ESE%20WilliamsPairProgramming_V2.pdf): I haven’t read all of them, but those curious about the short history of pair programming can take a look. I especially recommend The Mythical Man-Month book. - [Pair Programming (Laurie Williams - PennState)](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.140.1522&rep=rep1&type=pdf): Yet another academic article with advice on pair programming. ### Three Questions to a CTO > URL: https://gokmengorgen.net/2021/09/17/three-questions-to-a-cto/ | Published: 2021-09-17 00:00:00 +0000 UTC | Categories: remote-working _I’m not a CTO of Radity anymore, but I trust that it will succeed more in the future. One of my old coworkers asked me some questions to understand what I was doing in this position. To remember it later, I wanted to share the questions and my answers here._ ### What are the most critical three needs and goals of a CTO? - To ensure that the IT organization does business uninterruptedly and efficiently. - To follow the news about IT and integrate the tools if there’s something new to facilitate its operation. - To save the company know-how in safe and up-to-date, and help the new coworkers to adapt to their teams quickly. ### In what topic did you have the most problems? I’m having a problem contacting the correct people. I always have to keep my network up-to-date for that. ### What kinds of tasks do you have? I have to work continuously to reach my goals what I told in the first question. On the other side, I’m always talking with my coworkers to discover their potentials and evaluate them in the correct projects or tasks. I love to share my ideas with them; I listen to their thoughts about my decisions and consider their ideas when I decide on something new that affects the culture and future of the company. ### How to Fix Default Fonts Problem on Firefox > URL: https://gokmengorgen.net/2020/05/14/how-to-fix-default-fonts-problem-on-firefox/ | Published: 2020-05-14 00:00:00 +0000 UTC | Categories: remote-working | Tags: linux, ubuntu Most of the websites are using Helvetica as an alternative font, and Ubuntu is trying to set Nimbus Sans as a similar font even you have Helvetica font. Also, the default font on Firefox is DejaVu Sans, but the default fonts are working just if the styles don’t specify a font family in a website. ![](/images/firefox-nimbus-sans-font.png) Nimbus Sans comes with **fonts-urw-base35** package, and it’s **ubuntu-desktop**’s dependency, direct or indirect. I need **ubuntu-desktop** to use GNOME, so the best solution here is to disable the font altogether and refresh the fonts cache. Let’s go step by step. First of all, if you don’t have it yet, start with installing **ttf-mscorefonts-installer** package, Arial is the best alternative font for Helvetica, and it comes with that package. Then, confirm if the system finds Nimbus Sans as an alternative font for Helvetica: ```bash $ fc-match "Helvetica" NimbusSans-Regular.otf: "Nimbus Sans" "Regular" ``` Ok, so we’re sure that we understood the problem correctly. We will try to reject that weird font and recheck the output until it finds Arial. To do that, we need to create a `fonts.conf` file and keep it on the correct path. On my Ubuntu (20.04), the path will be `~/.config/fontconfig/fonts.conf`, but if you’re using a different distribution, learn the correct path from Google. After you created the file, fill it with these lines: ```xml Nimbus Sans ``` Then, let’s clear the fonts cache and recheck the fc-match output: ```bash $ fc-cache -rv $ fc-match "Helvetica" n019003l.pfb: "Nimbus Sans L" "Regular" ``` Okay, yet another weird font. Let’s ignore this font too and try again: ```xml Nimbus Sans Nimbus Sans L ``` ``` $ fc-cache -rv $ fc-match "Helvetica" Arial.ttf: "Arial" "Regular" ``` Finally! Now we can restart the Firefox and check the fonts on the browser: ![](/images/firefox-arial-font.png) That’s all. ### Rust Essentials > URL: https://gokmengorgen.net/2020/02/02/rust-essentials/ | Published: 2020-02-02 00:00:00 +0000 UTC | Categories: software-engineering | Tags: book Mostly I do not prefer to read the books written for teaching a programming language. Because a good language community already places the importance on their websites to promote the programming language beautifully as in Python and Rust. In these websites, you can find documentation, tutorials, even a free ebook that allows you to read from the website directly, and they’re mostly up-to-date. As you know, Rust is not an easy-to-learn programming language. So I frequently look at the official documentation of Rust, and sometimes I choose a random topic and read them again and again. Before starting to read this book, I took a look at the pages and saw some details that I still missed on the Rust documentation. Then I read the entire book thoroughly. My ebook was the [first edition](https://www.packtpub.com/application-development/rust-essentials), and there were missing topics like async programming. The author published the second edition in 2017, and it seems he will need to prepare a new version to include the last changes in the language. That’s why I do not prefer to learn a programming language from a book. Rust is improving rapidly, so you need to follow the official documentation always. Another issue that I feel most lacking right now is macros. I know that they’re similar to Lisp macros, but I still couldn’t have a chance to try it in my pet projects yet. The book shows me an example of usage, but I don’t understand how and where to use it. I wish to see the samples from a specific project or all samples come from the same project. Finally, I share a table about the pointer types in Rust, when I started learning Rust, it was pretty intimidating. Now it seems a little more meaningful. | Type | Name | Description | | --- | --- | --- | | `&T` | Reference | One or more references to read **T** | | `&mut T` | Mutable reference | Single reference to read and write **T** | | `Box` | Box | Heap-allocated **T** with a single owner that may read and write **T** | | `Rc` | Rc pointer | Heap-allocated **T** with many readers | | `Arc` | Arc pointer | Like **Rc**, but enables safe mutable sharing accross threads | | `*const T` | Raw pointer | Unsafe read access to **T** | | `*mut T` | Mutable raw pointer | Unsafe read and write access to **T** | ![](/images/rust-essentials.jpg) ### Inmost > URL: https://gokmengorgen.net/2020/01/21/inmost/ | Published: 2020-01-21 00:00:00 +0000 UTC | Categories: entertainment | Tags: steam I have a gaming PC for two years but couldn’t have time to play a game. So I decided to change my priorities in my life and will try to play more games and read more books this year. My first plan was to play this game with my daughter, but I realized that it was not a suitable game for kids after I bought it, so I’ll pay attention to use the family filter from now on. Fortunately, I did not regret it. There are some characters you play in the game. And the painful past of them is creating the story of the game. Especially the imagination of the girl was very shocking for me. I’ll not give you a spoiler, but the story helps you to understand what depression is and how human relations are so crucial for the traumatized people. This game is first for me in many ways. It’s my first indie game, first story-driven atmospheric game, and the first game that I played with a game controller. If you want to spend a weekend playing a game, I recommend [Inmost](https://inmostgame.com/). ![](/images/inmost.jpg) ### Oceanhorn 2 > URL: https://gokmengorgen.net/2020/01/21/oceanhorn-2/ | Published: 2020-01-21 00:00:00 +0000 UTC | Categories: entertainment | Tags: apple-arcade I had trouble understanding the story of the game because I didn’t play the first one. You start to play the game in the middle of the adventure. You have a sword and shield, so you think that the story is in the past, but you also have a kind of motorcycle that has no wheels but can fly. Also, you have a brother in arms named Gen, and it’s a robot. The other friend Trin tells you the story during the game, help you to solve the puzzle. Warlock Mesmeroth is the primary foe in the game; he is coming back somehow. So the first goal is to convince the knights of the lost realm to be together against him. It’s beneficial to learn of the abilities of your character to solve the puzzles quickly. It can’t jump, can’t swim more than ten seconds, but it can burn somethings and throw them away, can sweep the grass to find heart, coin, or bullet. It can blow up the walls with a bomb. Also, you can give some directions to Trin or Gen to do something that you want. The maps of the sections are too large, so it may take a while to find a way to pass to the next section. It was the first time that I played a game in a PC quality on the iPad. But the game poorly finished; it is as if the development of the game has been left unfinished. I think the third version of [Oceanhorn](https://www.cornfox.com/oceanhorn-2) will come out. ![](/images/oceanhorn2.jpg) ### Being a Polyglot Developer > URL: https://gokmengorgen.net/2019/12/31/being-a-polyglot-developer/ | Published: 2019-12-31 00:00:00 +0000 UTC | Categories: software-engineering | Tags: polyglot My objective for the year 2019 was joining one more programming language community after Python and Lisp. I followed .NET Core in my first six months and did some projects using C# and F#. But then, I decided that learning Rust is a better idea. Some of the Python and Django developers I’ve followed have had a significant impact on my decision. Python is a programming language that easy to learn, it has a significant and active community, and I believe that it will keep its popularity for a longer time. Therefore, when choosing another programming language, I make sure that it has different features and priorities. I’m not sure, but I think that that’s why I couldn’t continue with .NET community. I already produce microservices, REST API, gRPC server, or even classifying things using machine learning libraries in Python. But I would not have preferred Python if I want to make a mobile application, that would not make sense. Or I would use Rust for embedded or blockchain projects; I would code data or text mining tools in Lisp, for example. In the past, being a full-stack developer was an extremely wanted job position. Now I don’t know how it is, but I suggest you stay away and become a polyglot developer instead. ### Data Types in Programming > URL: https://gokmengorgen.net/2019/08/25/data-types-in-programming/ | Published: 2019-08-25 00:00:00 +0000 UTC | Categories: lifestyle I started to take a look at C++ courses to understand Rust better because it helps me to see the advantages of Rust. The following images are from a Linkedin course, the instructor is [Bill Weinman](https://www.linkedin.com/learning/c-plus-plus-essential-training-2/), and his courses are perfect if you want to program with C++. If you have a photographic memory to remind something quickly, then you may like these images explaining data types in programming. ![](/images/cpp-iostream.jpg) ![](/images/cpp-list.jpg) ![](/images/cpp-map.jpg) ![](/images/cpp-queue.jpg) ![](/images/cpp-set.jpg) ![](/images/cpp-string.jpg) ### First Review on My iPad > URL: https://gokmengorgen.net/2019/08/03/first-review-on-my-ipad/ | Published: 2019-08-03 00:00:00 +0000 UTC | Categories: remote-working | Tags: rdp, vscode _I started using an iPad instead of a second laptop for more effective use. Although it is excellent for reading things, answering emails, checking tasks, it is still not possible to use as a laptop with these devices._ _So I tried to connect to my primary PC remotely. But this was not satisfactory for me either. I took some notes to compare when iOS 13 and some updates came._ ![](/images/ipad-remote-desktop.png) ## Pros - In tablet mode, all screens are full-sized automatically. - The density of UI components is more comfortable to manage cursor with touching. - Firefox has a tablet mode; it supports touch scrolling, easy to click bookmarks. - The virtual keyboard is great! I didn’t need to use the iPad’s native on-screen keyboard. - We can’t see the running apps in the taskbar in tablet mode, but it’s possible to use the gestures to show all running apps. ## Cons - You need a remote desktop or a server. It’s impossible to work offline. - If you decide to use a remote desktop and you are obsessed about fonts, there’s no way to fix screen quality. - I’m not sure that I can code with iPad for hours even I have a good physical keyboard. ## So.. - With the new updates in macOS and iOS 13, it will be possible to run iPad applications on macOS. So iPadOS may affect the quality and variety of applications. - I’m still waiting for a new version of Microsoft Surface or Surface Go that using ARM CPU, has Thunderbolt 3 and USB-C ports. - I still didn’t investigate how Google Pixelbook is but seems a good alternative. ### My First Wrong After The Vacation > URL: https://gokmengorgen.net/2019/06/20/my-first-wrong-after-the-vacation/ | Published: 2019-06-20 00:00:00 +0000 UTC | Categories: software-engineering | Tags: devops, django At the end of my three-week vacation, I was asked for a seemingly easy task. We were going to release the new version of the project we developed: - Is today is the last working of the week? **No**. - Is there any problem with the unit tests? **No**. - Are all changes confirmed by the product manager, in the staging server? **Yes**. I always note everything, and so I write this article to remind this experience. My other habit is to define [**dosh**](https://gokmengorgen.net/en/blog/how-do-i-publish-my-articles/) sub-commands to access frequently used commands in my whole projects. It doesn’t matter if the project is written in .NET Core or used Django; - I know that the project will start in my development environment with `dosh start`, - I know that the project will build with `dosh build`, - I know that `dosh deploy` command will be running if I push my commits to some specific git branches. All these things are common sub-commands in my projects. So what was not a standard? ![](/images/server-updates.png) I manage everything in a project except the server maintenance. Today the site was offline about an hour because of the communication failure. Sometimes there are small but critical upgrades on the servers, and one of them broke SSL module of the project’s **psycopg2** dependency. I had only these logs: ```bash DAMN ! worker 1 (pid: 28018) died :( trying respawn ... Respawned uWSGI worker 1 (new pid: 28021) !!! uWSGI process 27988 got Segmentation Fault !!! *** backtrace of 27988 *** /usr/bin/uwsgi-core(uwsgi_backtrace+0x2a) [0x55a0ad5c498a] /usr/bin/uwsgi-core(uwsgi_segfault+0x23) [0x55a0ad5c4d73] /lib/x86_64-linux-gnu/libc.so.6(+0x3ef20) [0x7f4811ecaf20] /project/venv/lib/python3.6/site-packages/psycopg2/.libs/./libssl-8bb9b3dd.so.1.0.2o(ssl3_cleanup_key_block+0xb) [0x7f480a747cbb] /project/venv/lib/python3.6/site-packages/psycopg2/.libs/./libssl-8bb9b3dd.so.1.0.2o(ssl3_clear+0x16) [0x7f480a7455b6] /project/venv/lib/python3.6/site-packages/psycopg2/.libs/./libssl-8bb9b3dd.so.1.0.2o(tls1_clear+0x9) [0x7f480a751229] /usr/lib/x86_64-linux-gnu/libssl.so.1.1(SSL_new+0x3f2) [0x7f4812b429d2] /project/venv/lib/python3.6/site-packages/psycopg2/.libs/libpq-239f9ac8.so.5.10(+0x23399) [0x7f480a9dc399] ``` You may know **Segmentation Fault** if you coded in C or if you worked with a package manager. Some included libraries that are coming with psycopg2 binary package are linked to the old version of libssl, so the last server update broke the dependencies[1](https://gokmengorgen.net/blog/2019/06/my-first-wrong-after-the-vacation/#fn:1). ```bash lib/python3.6/site-packages/psycopg2/.libs/libssl-8bb9b3dd.so.1.0.2o # from 1.0 lib/python3.6/site-packages/psycopg2/.libs/libssl-7a80b951.so.1.1.1b # to 1.1 ``` In some projects, it’s not possible to solve the problems as we wanted because of some regulations and source limits. I could find prevention for that case, but somehow, I forgot to check the updates in the source code and server packages and tried to make the deployment. And the worst thing, I didn’t realise the problem until someone warned me. So, I added one more rule for myself to make a deployment: - Is today the first day after the vacation? **Yes (so, don’t touch it.)**. * * * 1. “Don’t break the dependencies”, I missed contributing a Linux distro like Pardus. [↩︎](https://gokmengorgen.net/blog/2019/06/my-first-wrong-after-the-vacation/#fnref:1) ### Configure Windows for Development > URL: https://gokmengorgen.net/2019/03/16/configure-windows-for-development/ | Published: 2019-03-16 00:00:00 +0000 UTC | Categories: software-engineering | Tags: powershell, windows ## Environment Variables I still use some development tools that are used by most Linux users and these tools need some environment variables like **LC\_ALL**, **HOME**, etc. When I have a new PC with Windows 10, I start to use with defining these variables. Take a look at [this post](https://gokmengorgen.net/en/blog/important-windows-environment-variables/) for more detail. ## PowerShell Core It’s possible to use BASH on Windows indeed, but I think PowerShell Core is a good alternative. Git integration is working well, defining aliases and functions is easy: ```powershell # Extensions Import-Module posh-git Import-Module PSReadLine # DOSH settings $env:ENV = "DEV" Set-Alias dosh .\do.ps1 # Readline settings Set-PSReadLineOption -EditMode Emacs # Git prompt settings $GitPromptSettings.DefaultPromptPath.ForegroundColor = 0xFFA500 $GitPromptSettings.DefaultPromptWriteStatusFirst = $true $GitPromptSettings.DefaultPromptBeforeSuffix.Text = '`n$([DateTime]::now.ToString("MM-dd HH:mm:ss"))' $GitPromptSettings.DefaultPromptBeforeSuffix.ForegroundColor = 0x808080 $GitPromptSettings.DefaultPromptSuffix = ' $((Get-History -Count 1).id + 1)$(" >" * ($nestedPromptLevel + 1)) ' # Helper commands function which ($command) { Get-Command $command | Select-Object -ExpandProperty Definition } function touch ($filename) { $null > $filename } ``` **Readline** is a familiar extension for BASH users. If you want to use Emacs key bindings in PowerShell, I suggest you add Readline to the dependencies list. What if we want to use a Linux command-line app? Like Nano? Indeed, it’s possible to use it as a default git-commit editor but, let’s consider it’s a program that only available in Linux. I use WSL for that case. Just install Ubuntu or another Linux distro with WSL, open PowerShell and run this command: ```bash > wsl -e nano README.md ``` So you can reach all Ubuntu programs using this magic command. There’s only a little problem here, you have to keep your configuration files (like **.nanorc**) in your WSL instead of in your local. You can find my configuration repo [here](https://github.com/gkmngrgn/config/). ## Git-apply EOL Problem If you don’t ignore space changes in your patch command, you will get an error because the whitespaces in Linux environments. To solve this problem, use **git-apply** with these parameters: ```bash $ git apply --ignore-space-change --ignore-whitespace a.diff ``` ### Consumer > URL: https://gokmengorgen.net/2019/02/27/consumer/ | Published: 2019-02-27 00:00:00 +0000 UTC | Categories: lifestyle | Tags: opinion For good things in life, you need labour, patience, and time. - To draw a picture, - To play an instrument, - To program software, - Or to produce something, - Even to complete a book, - To translate a text, - To tell the troubles, - To write what you think, - To prepare a broadcast, - For everything. Just sharing something in social media and consuming it is easy. ### What age do we live? > URL: https://gokmengorgen.net/2019/02/16/what-age-do-we-live/ | Published: 2019-02-16 00:00:00 +0000 UTC | Categories: lifestyle | Tags: opinion ![](/images/train-station.jpg) > Our technology is not so advanced to be an eye or an ear for us. > Or we’re not in an age where we don’t need our body yet. ### String quotes in PEP8 > URL: https://gokmengorgen.net/2019/01/12/string-quotes-in-pep8/ | Published: 2019-01-12 00:00:00 +0000 UTC | Categories: software-engineering | Tags: python I use PEP8 in my Python projects except for [a few rules](https://www.python.org/dev/peps/pep-0008/#string-quotes). I think ‘single-quote’ and “double-quote” characters should **NOT** be the same. It could be better if these two characters had different counterparts in the Python language parser system. So we could use one of them for the template-strings (or f-strings). It doesn’t provide readability, causes inconsistency instead. Until now, I used string-quotes for the variable definitions and double-quotes for the visible texts. [But now](https://github.com/gkmngrgn/style-guide/blob/master/python.md), I plan to use always double-quote as in many other programming languages. ### Spreadsheet applications > URL: https://gokmengorgen.net/2019/01/02/spreadsheet-applications/ | Published: 2019-01-02 00:00:00 +0000 UTC | Categories: lifestyle | Tags: opinion Spreadsheet applications are the most functional applications I’ve used. Excel, Gnumeric, Google Sheet, OpenOffice Calc or whatever, it doesn’t matter. You can use it as task management like Trello, make daily - weekly - monthly plans, store and transfer data, and follow your financial situation. It’s like a Swiss army knife and not a new invention. I’ll update this article when I find a more functional application. ### How do I publish my articles? > URL: https://gokmengorgen.net/2018/12/30/how-do-i-publish-my-articles/ | Published: 2018-12-30 00:00:00 +0000 UTC | Categories: software-engineering | Tags: bash, devops, powershell With just a command: ```bash # terminal $ ENV=PROD ./do.sh deploy ``` I have many projects using my script named [DOSH](https://gist.github.com/gkmngrgn/48303742353b0b17ae0e5c2d1d24ec3e) and the parameters are mostly in common; `deploy`, `start`, `stop`, `runtests`, etc. It can be a .NET Core or a Django project, or just a website using any static site generator like [this one](https://gohugo.io/) but I run all the projects with the same command: `dosh start`. In Windows, the command may be a bit longer than in the other operating systems. So it’s a good idea to shorten the command using some aliases, the default environment is `DEV`: ```bash # ~/.bash_profile alias dosh="winpty bash do.sh" # or just type "./do.sh" in Linux or MacOS. ``` ```bash # terminal $ dosh start # in DEV $ ENV=PROD dosh deploy # in PROD, my deploy parameter works only in production. ``` Do you use PowerShell? No problem, I think it’s better to do the same thing in PowerShell, you can find the sample codes below, but let me show you how I use that, it’s a bit different than BASH: ```bash # powershell ~\Workspace\website [master ≡]> $env:ENV = "PROD" ~\Workspace\website [master ≡]> dosh deploy Environment: production Deploying updates to GitHub... Building sites … | EN | TR +------------------+----+----+ Pages | 13 | 67 Paginator pages | 0 | 0 Non-page files | 0 | 0 Static files | 63 | 63 Processed images | 0 | 0 Aliases | 1 | 12 Sitemaps | 2 | 1 Cleaned | 0 | 0 Total in 748 ms [master 1686121] rebuilding site 12/30/2018 15:02:32 1 file changed, 3 insertions(+), 3 deletions(-) Enumerating objects: 9, done. Counting objects: 100% (9/9), done. Delta compression using up to 12 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (5/5), 628 bytes | 628.00 KiB/s, done. Total 5 (delta 3), reused 0 (delta 0) remote: Resolving deltas: 100% (3/3), completed with 3 local objects. To github.com:gkmngrgn/gkmngrgn.github.io.git 733793b..1686121 master -> master DONE. ``` ## Code samples You can find many sample codes here to write a deployment script and I didn’t think of this idea **first** but still, I’m sharing my scripts to be an alternative: ### ./do.sh ```bash #!/usr/bin/env bash BLUE="\\033[1;34m" GREEN="\\033[1;32m" NORMAL="\\033[0;39m" RED="\\033[1;31m" print_help() { echo -e "${BLUE}Available environments${NORMAL}" echo " - DEV (default)" echo " - PROD" echo " - STAGING" echo "" echo -e "${BLUE}Available commands${NORMAL}" echo -e " > deploy [:message] Deploy the changes" echo -e " > start Run development server" } deploy() { case ${ENV} in "PROD") echo -e "${BLUE}Deploying updates to GitHub...${NORMAL}" ;; *) echo -e "${RED}This command only works in production.${NORMAL}" exit ;; esac if [ $# -eq 1 ] then msg="${1}" else msg="rebuilding site `date`" fi hugo cd public git add . git commit -m "${msg}" git push origin master cd .. echo -e "${GREEN}DONE.${NORMAL}" } start() { hugo server -D } if [ -z "$1" ] then print_help else case $ENV in "PROD") env_str="production" ;; "STAGING") env_str="staging" ;; *) env_str="development" ;; esac echo -e "${BLUE}Environment:${NORMAL} $env_str" "$@" fi ``` ### ./do.ps1 ```powershell <# Variables #> if ($env:ENV -eq "PROD") { $env_str = "production" } elseif ($env:ENV -eq "STAGING") { $env_str = "staging" } else { if ($env:ENV -ne "DEV") { $env:ENV = "DEV" } $env_str = "development" } <# Functions #> function Get-Help { Write-Host -ForegroundColor Cyan "Available Environments" Write-Output " - DEV (default)" Write-Output " - PROD" Write-Output " - STAGING" Write-Output "" Write-Host -ForegroundColor Cyan "Available commands" Write-Output " > deploy [:message] Deploy the changes" Write-Output " > start Run development server" } function Start-Deploy ([string] $subParams) { if ($env:ENV -eq "PROD") { Write-Host -ForegroundColor Blue "Deploying updates to GitHub..." } else { Write-Host -ForegroundColor Red "This command only works in production." exit } if ($subParams -eq "") { $msg = "rebuilding site $(Get-Date)" } else { $msg = $subParams } Invoke-Expression "hugo" Invoke-Expression "cd public" Invoke-Expression "git add ." Invoke-Expression "git commit -m '$msg'" Invoke-Expression "git push origin master" Invoke-Expression "cd .." Write-Host -ForegroundColor Green "DONE." } function Start-Server () { Invoke-Expression "hugo server -D" } <# Set default parameter as help. #> if ($args.Length -eq 0) { $param = "help" $subParams = "" } else { $param, $subParams = $args } if ($param -ne "help") { Write-Host -ForegroundColor Cyan -NoNewLine "Environment: " Write-Output $env_str } <# We use switch instead of alias because there are some constant variables like `start`. #> switch ($param) { "deploy" { Start-Deploy $subParams } "start" { Start-Server } Default { Get-Help } } ``` Don’t forget to set the alias in your config file, for example: ```bash # ~\Documents\PowerShell\profile.ps1 $env:ENV = "DEV" Set-Alias dosh .\do.ps1 ``` ### Important Windows Environment Variables > URL: https://gokmengorgen.net/2018/12/25/important-windows-environment-variables/ | Published: 2018-12-25 00:00:00 +0000 UTC | Categories: software-engineering | Tags: windows ![](/images/windows-env-variables.jpg) ## PowerShell and Git encoding problems To make `git log` command output properly display on Windows, we need to set a variable named `LC_ALL`: ```bash LC_ALL="C.UTF-8" ``` ![](/images/powershell-git-encoding-problem.jpg) ## Incorrect home folder in Emacs This problem is not only about Emacs. If you try to find a file from `HOME` variable, you may need to define the variable first: ```bash HOME="%USERPROFILE%" ``` ``` ;; place all backup files in one directory (setq backup-directory-alist `((".*" . ,temporary-file-directory))) (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) (setq default-directory (concat (getenv "HOME") "/Workspace")) ``` ## More.. Take a look at the [other posts](https://gokmengorgen.net/en/tags/windows/) about my Windows development environment.