<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rytis</title>
    <description>The latest articles on DEV Community by Rytis (@rytis).</description>
    <link>https://dev.to/rytis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F92448%2F31640b39-a38b-45ea-b95d-5f67eef3077f.png</url>
      <title>DEV Community: Rytis</title>
      <link>https://dev.to/rytis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rytis"/>
    <language>en</language>
    <item>
      <title>NFTs, Blockchains, and Standards Explained without BS</title>
      <dc:creator>Rytis</dc:creator>
      <pubDate>Fri, 28 Jul 2023 11:43:11 +0000</pubDate>
      <link>https://dev.to/rytis/nfts-blockchains-and-standards-explained-without-bs-3nm0</link>
      <guid>https://dev.to/rytis/nfts-blockchains-and-standards-explained-without-bs-3nm0</guid>
      <description>&lt;p&gt;This was originally written for my colleagues who were working on a same project. I am definitely not a cryptochad or a crypto promoter, but I find this technology quite interesting. If you want a no BS explanation without the hype or something being sold to you – then read on. This is the explanation I wish I had when I’ve started researching this technology. Please comment on any misconceptions / mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Token / NFT
&lt;/h2&gt;

&lt;p&gt;First we need to clarify some terminology. NFT stands for Non-Fungible Token, however people just use it as a catch-all term for everything crypto. What is the difference between fungible and non-fungible tokens?&lt;/p&gt;

&lt;p&gt;Think about a fungible token as just a simple 50 cent coin in your wallet. It is no different from any other 50 cent coin, and you probably don’t care whether you have that particular coin, or any other 50 cent coin. They are the same, they are interchangeable – they are fungible.&lt;/p&gt;

&lt;p&gt;Non-Fungible, however, means unique. Think of it as a commemorative coin with a stamped serial number. You might own the coin with the serial number 001, and your friend might own a coin with a serial number 050. They might look similar, but are unique because of their serial number. You wouldn’t exchange a 001 coin for a 050 coin, unless 050 had more sentimental value to you than 001.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Workings of Smart Contracts
&lt;/h2&gt;

&lt;p&gt;Another very important thing to understand is how smart contracts work and what they are. Smart contracts are just code that runs on Blockchain, that’s it. There’s no magic involved. It’s not much different from a Java class. Smart contracts are written in Solidity language, which is a &lt;a href="https://en.wikipedia.org/wiki/Turing_completeness" rel="noopener noreferrer"&gt;Turing Complete&lt;/a&gt; language, which means that pretty much any programming goal can be achieved with the language.&lt;/p&gt;

&lt;p&gt;However, there is a caveat – each operation on blockchain takes a very long time and can even cost money, so huge and complex functionality may not be feasible. Great care must be taken when developing smart contracts to reduce the complexity, operations, and thus the cost of execution. A cost of execution is referred to as &lt;strong&gt;Gas Fees&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Smart Contracts can also store data (for example token ownership information) on the blockchain. This costs even more Gas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Views vs Transactions
&lt;/h3&gt;

&lt;p&gt;An important distinction should be made between views and transactions. Retrieving data from blockchain (such as user’s crypto balance) does not warrant any gas fees from the user. As far as the end user is concerned, retrieving and showing data from blockchain is free. As long as no data is altered, the operations are free. To call a view function, user does not need to sign anything, the data will just be returned.&lt;/p&gt;

&lt;p&gt;Storing, manipulating, changing the data on Blockchain, however, is not free. Data manipulation on blockchain is called a &lt;strong&gt;transaction&lt;/strong&gt;. If any data is being changed (such as changing the owner of a crypto token), then all operations done within the same transaction will incur Gas Fees. Different operations have different gas cost – adding two numbers together is cheaper than making a call to an external smart contract. User will also need to sign the transaction, which basically means that before the transaction is executed, user will see a prompt from MetaMask and will have to confirm the transaction.&lt;/p&gt;

&lt;p&gt;All transactions are public. Everyone can see who made the transaction and what data has been changed and when it happened. Gas fees and any crypto transfers are also visible to the public.&lt;/p&gt;

&lt;p&gt;Transactions also come in two flavors – &lt;strong&gt;payable&lt;/strong&gt; and &lt;strong&gt;non-payable&lt;/strong&gt;. A payable transaction means that some amount of chain’s native currency (Ether on Ethereum, and Matic on Polygon) is attached together with the transaction. How the currency is distributed is in the sole discretion of the smart contract. A good analogy would be: you take an envelope and put in a note with the instructions and you also add a couple of dollars in that same envelope. The receiver of the envelope reads the instructions, and then gives a couple of dollars to their boss, takes a dollar to themselves, and then sends a dollar back to you. The postal fees you have paid to send that envelope are completely separate (analogy for gas fees). Money added to a transaction is referred to as &lt;strong&gt;transaction value&lt;/strong&gt;. Transaction value and gas fees are absolutely separate and unrelated. A non-payable transaction will incur gas fees anyway: again you’re paying for the postal office to send your letter, you’re just not adding any bills in the envelope.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart contracts in terms of crypto tokens
&lt;/h3&gt;

&lt;p&gt;A crypto token, be it some coin or an NFT – is a smart contract. Tokens have different standards, with different functionality and different goals, and those will be explained further down the line. Token contracts store their ownership information inside themselves, which means that from a technical perspective, saying that a token has been added to a wallet is incorrect. Technically nothing ever gets “added” to the wallet. The contract stores a wallet token balance inside itself, so the more accurate description would be: “Wallet gets assigned a balance in the contract”.&lt;/p&gt;

&lt;p&gt;This is extremely important to understand, because this part is where most miscommunication happens, with regards to crypto tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  A word on immutability
&lt;/h3&gt;

&lt;p&gt;Immutable means unchanging over time or unable to be changed. Smart contracts are immutable. This means that once the contract is deployed on blockchain, no one can change the functionality of it. Data stored by the contract can still be manipulated, granted that the functions to manipulate that data were developed, but you cannot add or remove those functions.&lt;/p&gt;

&lt;p&gt;This brings us to the biggest pitfall of smart contracts – they need to be developed correctly from the start. If a security vulnerability is later found in the contract, there’s nothing you can do about it. This is one of the reasons a lot of famous hacks have happened.&lt;/p&gt;

&lt;p&gt;So how can one upgrade the contract functionality? The answer is – deploy a completely new and separate smart contract with new functionality. This means that this new contract has new data completely unrelated with the previous contract. And that’s where we enter migration territory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contract migrations
&lt;/h3&gt;

&lt;p&gt;The moving of data from one smart contract to another is called a &lt;strong&gt;migration&lt;/strong&gt;. There’s no standard way to migrate the data, if it is possible at all. When smart contracts are developed, any future migrations should be had in mind upfront. If no functions were developed to read the data in the smart contract, the migration might not be possible at all.&lt;/p&gt;

&lt;p&gt;Technically a migration might happen as a communication between old contract and new contract:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;New Contract:&lt;/em&gt; Hey, old contract, how much of token 1 does wallet 0x123 have?&lt;br&gt;
&lt;em&gt;Old Contract:&lt;/em&gt; 42&lt;br&gt;
&lt;em&gt;New Contract:&lt;/em&gt; Ok, then I’ll note in my storage that wallet 0x123 has 42 counts of token 1. Hey, old contract, how much of token 2 does wallet 0x123 have?&lt;br&gt;
And so on…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This can get expensive pretty fast. Remember, each storage procedure costs gas. The more distributed your token gets, the more expensive it will be to migrate.&lt;/p&gt;

&lt;p&gt;A way to save gas fees in case of migration, would be to offload the costs to your users. This is more of a communication exercise, rather than a technical challenge. A functionality to copy the balance of the old token to the new token contract could be developed and your users could be told to call that functionality themselves, and pay the gas fees. This could however frustrate your users.&lt;/p&gt;

&lt;p&gt;Another thing to note is that after the migration, your old token contract, together with its ownership data will still be on the blockchain. This means that users that have migrated the tokens will still have their tokens in the old contract, as well as their tokens in the new contract, thus duplicating the information. Unless, of course, you develop a functionality that burns the tokens in the original contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  Differences between blockchains
&lt;/h3&gt;

&lt;p&gt;Nowadays there are a lot of different blockchains. Ethereum is the most popular blockchain, but there are others, such as Polygon. However, most of those chains are just a copy of Ethereum, which means that they use the same language and principles for smart contract development, which in turn means that smart contracts developed for Ethereum will work on Polygon or most other chains without any changes.&lt;/p&gt;

&lt;p&gt;Even if smart contract code is the same, contracts deployed on different blockchains will have nothing in common between them. If you launch your token on Ethereum and Polygon, they will not share ownership data, limits, metadata, or anything else. It’s like having two different Volkswagens – one on Earth and another in Mars. The blueprint is the same, but they don’t interact with each other.&lt;/p&gt;

&lt;p&gt;It is also important to mention that Bitcoin is a whole different beast on its own. It’s not based on Ethereum and cannot run the same smart contracts. Forget Bitcoin, it does not exists as far as we’re concerned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Token Standards
&lt;/h2&gt;

&lt;p&gt;So what are the options for token standards? A couple of standards are defined in the ERC (Ethereum Request for Comment). I encourage you to read the mentioned ERCs, so you can have the information from the horse’s mouth, but I’ll try to quickly run through the standards in my own words.&lt;/p&gt;

&lt;h3&gt;
  
  
  ERC-20
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-20" rel="noopener noreferrer"&gt;Read EIP&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your most common fungible token – a shitcoin, pardon the expression. All those Pepe Coins, Shib Coins, etc are ERC-20 tokens. It’s supposed to be like a currency, like your dollars and euros. You could also look at it as stocks – pieces of a company (you can cap the supply of the coin for artificial scarcity). No matter how you look at it, a piece of ERC-20 is the same as any other piece of that same ERC-20 token.&lt;/p&gt;

&lt;p&gt;The ownership data is stored as a map of &lt;code&gt;Wallet Address → number of coins owned&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wallet 0x123 owns 3 tokens,&lt;/li&gt;
&lt;li&gt;Wallet 0xABC owns 7 tokens,&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ERC-721
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-721" rel="noopener noreferrer"&gt;Read EIP&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most common non-fungible token, the original NFT. This is also sometimes referred to as collection. A collection has a name, such as “Bored Ape Yacht Club”, and it also has a ticker symbol, such as “BAYC”. BAYC, by the way, is a real token collection, where you can collect apes. Each ape is different from another (non-fungible).&lt;/p&gt;

&lt;p&gt;Each NFT in the contract is identified by a unique ID. This number does not change for the life of the contract. The ownership information is essentially stored as a map of &lt;code&gt;Token ID → Wallet Address&lt;/code&gt;: “Token ID 42 is owned by wallet 0x123”. No quantities are at play here. If a single wallet owns different tokens in the same contract, each record is stored separately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token ID 42 is owned by wallet 0x123&lt;/li&gt;
&lt;li&gt;Token ID 69 is owned by wallet 0x123&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ERC-777
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-777" rel="noopener noreferrer"&gt;Read EIP&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This standard defines a new way to interact with a token contract while remaining backward compatible with ERC-20.&lt;/p&gt;

&lt;p&gt;It defines advanced features to interact with tokens. Namely, &lt;em&gt;operators&lt;/em&gt; to send tokens on behalf of another address — contract or regular account — and send/receive &lt;em&gt;hooks&lt;/em&gt; to offer token holders more control over their tokens.&lt;/p&gt;

&lt;p&gt;So it’s basically a shitcoin on steroids. I have to admit, I don’t have much experience with this standard, but it does look interesting. Again, I encourage you to read the original EIP, it is quite well written and an interesting read.&lt;/p&gt;

&lt;h3&gt;
  
  
  ERC-1155
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-1155" rel="noopener noreferrer"&gt;Read EIP&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now this standard is the most advanced and it builds on the experience of the previous standards. While ERC-20 and ERC-721 requires deployment of separate contracts per token type, ERC-1155 is a Multi Token standard, that allows mixing fungible and non-fungible tokens in the same contract, with their own supplies, limits, and metadata.&lt;/p&gt;

&lt;p&gt;Tokens still have their own unique IDs as with ERC-721, however now the ownership information also includes the number of particular token owned. The ownership information is stored as a multi dimensional map of &lt;code&gt;Token ID → Wallet Address → Number owned&lt;/code&gt;. So ownership data is stored in such a manner:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token ID 42 is owned by:

&lt;ul&gt;
&lt;li&gt;Wallet 0x123 owns 2 tokens&lt;/li&gt;
&lt;li&gt;Wallet 0xABC owns 5 tokens&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Token ID 69 is owned by:

&lt;ul&gt;
&lt;li&gt;Wallet 0x123 owns 1 token&lt;/li&gt;
&lt;li&gt;Walled 0x999 owns 42 tokens&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;As you can see, this is a merge between ERC-20 and ERC-721 concepts as it includes non-fungibility (through unique token IDs) as well as fungibility through ownership quantities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operator Approvals
&lt;/h2&gt;

&lt;p&gt;An owner of a token may allow other addresses (wallets or contracts) to operate their tokens in that particular smart contract. In that case, the 3rd party is called an operator, and the act of allowing an operator is called an approval. This might be a bit different between the standards, but I want you to get the general gist of it.&lt;/p&gt;

&lt;p&gt;The operator has full reign over the tokens. This means that if you have approved an operator for your tokens, they are free to transfer all of your tokens from that smart contract to anyone. Usually when placing a token for sale on a marketplace, it asks you to grant approval to that market contract.&lt;/p&gt;

&lt;p&gt;This is basically the same as giving your house keys to your local Tesco manager, and trusting that they will only take one Gorilla figurine from your shelf. They might be trustworthy, but don’t be surprised if one day all your actions figures are gone. It might not even be the manager themselves, they might get robbed and your key gets stolen from them.&lt;/p&gt;

&lt;p&gt;Some more advanced contracts may implement their own more sophisticated approval systems, but those are out of scope of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenZeppelin
&lt;/h2&gt;

&lt;p&gt;A funny thing is that you don’t even need to develop any of this yourself. There’s a company that has developed the implementation of the standards described above. Want your own shitcoin? It’s as easy as opening their &lt;a href="https://www.openzeppelin.com/contracts" rel="noopener noreferrer"&gt;Contract Wizard&lt;/a&gt; and selecting the features that you want.&lt;/p&gt;

&lt;p&gt;A lot of the meme coins don’t even have their own code in them. This is a valid coin contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MemeCoin is ERC20 {
    constructor() ERC20("MemeCoin", "SHT") {
        _mint(msg.sender, 42000 * 10 ** decimals());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All it does is assigns a limited number of coins to the contract deployer address. Deployer can then build the hype around that coin and sell on a marketplace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blockchain Scanners
&lt;/h2&gt;

&lt;p&gt;For the sake of completeness I also need to mention blockchain scanners. As you already know, all transactions on blockchain are public and transparent. For that reason, most of the blockchains have public scanners, which are just websites that show transactions in a convenient way. Ethereum has &lt;a href="https://etherscan.io/" rel="noopener noreferrer"&gt;Etherscan&lt;/a&gt;, and Polygon has &lt;a href="https://polygonscan.com/" rel="noopener noreferrer"&gt;Polygonscan&lt;/a&gt;. Any transfers, purchases, method calls, and contract deployments you make will appear in those scanners for everyone to see and inspect. Whether this is good or bad, I’ll leave it to your own consideration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;Thank you for taking the time to read through this article.&lt;/p&gt;

&lt;p&gt;There are a lot of misconceptions about the blockchain, NFTs, and coins, and there’s no shortage of people willing to take advantage of the uninformed. I hope this article has given you at least some technical understanding on what the hype is all about.&lt;/p&gt;

&lt;p&gt;If you know someone who might benefit from this knowledge, please share this article with them, so that the working principle is demystified.&lt;/p&gt;

&lt;p&gt;If you’ve enjoyed the article, please like it, so that I know it was interesting / useful. Discuss any issues in the comments. And maybe consider following me here on DEV. I won’t be focusing on crypto topics, but I might put out an article about it once in a while.&lt;/p&gt;

&lt;p&gt;And with all that said – have a great rest of your day.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>solidity</category>
      <category>cryptocurrency</category>
      <category>learning</category>
    </item>
    <item>
      <title>Fixing Your Backend Git Strategy</title>
      <dc:creator>Rytis</dc:creator>
      <pubDate>Tue, 24 Jan 2023 15:16:27 +0000</pubDate>
      <link>https://dev.to/rytis/fixing-your-backend-git-strategy-ab</link>
      <guid>https://dev.to/rytis/fixing-your-backend-git-strategy-ab</guid>
      <description>&lt;p&gt;Have you found your company to be struggling with getting features to production quickly? Is there a big blocker somewhere in your process? It could be that one of the culprits is the way you’re using Git.&lt;/p&gt;

&lt;p&gt;This article started as an internal article within &lt;a href="https://metahi.world/" rel="noopener noreferrer"&gt;MetaHi&lt;/a&gt;, therefore it may contain references to problems specific to our company, so don't take it gospel. But in the grand scheme of things, I think that a lot of startups struggle with similar problems, so that’s why I decided to share this writeup, with minimal tweaks.&lt;/p&gt;

&lt;p&gt;If it makes you feel better, consider this another shill for a Continuous Integration/Delivery/Deployment process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we’re trying to achieve
&lt;/h2&gt;

&lt;p&gt;We want features to appear in production as soon as possible, with the least amount of bugs, and the most value to the user. A great way to achieve this is to practice &lt;strong&gt;Continuous Delivery&lt;/strong&gt;. Here’s some terminology that we should clear up first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Integration&lt;/strong&gt; — builds and tests software after every push. It does not deploy the build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Delivery&lt;/strong&gt; — deploys every change made to the code to a staging environment, and allows for a push to production on demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Deployment&lt;/strong&gt; — takes it even further, every code changes going through the pipeline will merge into production automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We should strive to achieve &lt;strong&gt;Continuous Delivery&lt;/strong&gt; at least. This means that the code you push should not break the builds, which means that you MUST run the tests and code locally before pushing, and should fix any failing tests immediately.&lt;/p&gt;

&lt;p&gt;Here’s a list of requirements. Print it and glue it in front of your eyes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Features should appear in Prod ASAP&lt;/li&gt;
&lt;li&gt;Tasks should not block the release of other tasks&lt;/li&gt;
&lt;li&gt;Code in &lt;code&gt;master&lt;/code&gt; MUST be production ready (building out of the box, and no failing tests)&lt;/li&gt;
&lt;li&gt;Commits in &lt;code&gt;master&lt;/code&gt; MUST have proper commit messages&lt;/li&gt;
&lt;li&gt;Any API release must be backwards compatible, unless otherwise agreed with Frontend devs&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to achieve it?
&lt;/h2&gt;

&lt;p&gt;Discipline and trunk based development. You need to have discipline to write proper tests for the features you are developing. You need to have discipline to test your code every time before pushing. You need to have discipline to not develop crap, even when you know you are developing throwaway code. &lt;/p&gt;

&lt;h3&gt;
  
  
  Trunk based development
&lt;/h3&gt;

&lt;p&gt;Trunk based development means that only a single branch is considered the main one. The less time your code spends detached from the main branch – the better. When you are striving to stay on the main branch you will be making smaller commits, thus ensuring that the changes you make are less risky and can be rolled back easily. It will also be easier to integrate with your colleagues, because there will be less merge conflicts. I’m not advocating against feature branches, those are still ok in some cases, but they should not be living for more than a couple of days.&lt;/p&gt;

&lt;p&gt;What about the QA step and dev? Nothing in the strategy above conflicts with Dev or QA. You are still free to independently tag your commits with &lt;code&gt;dev&lt;/code&gt; tag, so that it gets built into the dev environment. And QA can work either in dev environment, or directly in production. But how do we ensure that users don’t see untested features in production? And the answer to that is &lt;strong&gt;feature flags&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature flags
&lt;/h3&gt;

&lt;p&gt;Feature flags allow teams to modify system behavior without changing code. You can read an &lt;a href="https://martinfowler.com/articles/feature-toggles.html" rel="noopener noreferrer"&gt;in-depth article about feature flags on Martin Fowler’s website&lt;/a&gt;. In practice it means that for any feature or behavior change you want to hide from the user, you should make a config variable. And then taking that config variable into account is as easy as writing an &lt;code&gt;if&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;However, not every new feature warrants a feature flag. If you are developing some new endpoints that are not going to have frontend attached for a while, there’s no need to make a feature flag, because end users will not be able to reach it by normal means anyway.&lt;/p&gt;

&lt;p&gt;A real example of where you would use a feature toggle in the config: let’s say there’s existing code for filtering a list, but it’s not good code. You want to develop something more robust, while the crappy code still remains working. The first commit you would make to master, would be config param something along the lines of &lt;code&gt;use-new-filtering&lt;/code&gt;. Nothing has changed and this should be safe to deploy to production. You can then make an &lt;code&gt;if&lt;/code&gt; statement in your controller to take this configuration param into account and call an appropriate service (either &lt;code&gt;OldFilteringService&lt;/code&gt; or &lt;code&gt;NewFilteringService&lt;/code&gt;). And then you are free to actually continue developing your new filtering functionality, continually deploy to prod, and all while still keeping the old code working. Dev environment can have &lt;code&gt;use-new-filtering=true&lt;/code&gt;, and QA can keep testing it while you are working, and production environment can have &lt;code&gt;use-new-filtering=false&lt;/code&gt; in order to use the old and approved code. Once the code is ready and tested, it’s just a matter of flipping the flag in production to make use of the new code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Versioned endpoints
&lt;/h3&gt;

&lt;p&gt;Talking about endpoints – they can actually act as a method of feature flagging themselves. If you have an endpoint that has been running on production for a while and you want to fundamentally change it (ie introduce breaking changes), one way to handle that is to create versioned endpoints. Frontend can still use the old &lt;code&gt;/do/something&lt;/code&gt; endpoint for the time being, and you can actively be developing &lt;code&gt;/v2/do/something&lt;/code&gt; without breaking the first one. When the endpoint is ready, frontend will just switch the URL, and it should be good to go. When old endpoint is no longer actively in use and everyone has confirmed that the new endpoint works correctly, you should take some to remove the older endpoint so that it doesn’t clutter the codebase and confuse other devs.&lt;/p&gt;

&lt;p&gt;Versioned endpoints supports our goal of having our code backwards compatible, so that existing features and frontend doesn’t break.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branching
&lt;/h3&gt;

&lt;p&gt;Let’s get back to trunk based development a bit. As mentioned previously, trunk based development does not forbid you from actually using branches. I would even encourage using them, for more isolation of your changes, and nicer looking diffs when merging. However your branches should live for as short time as possible. We’re talking hours here, or couple of days at maximum.&lt;/p&gt;

&lt;p&gt;In practice – all your feature branches should be branched off of &lt;code&gt;master&lt;/code&gt; branch. Since there’s a rule that &lt;code&gt;master&lt;/code&gt; must always be production ready and work out of the box, it is the safest place to base your code off of.&lt;/p&gt;

&lt;p&gt;When the feature is done, it should be merged back to &lt;code&gt;master&lt;/code&gt;. Doing it through a PR, or a simple merge is entirely up to you, just make sure it ends up back in &lt;code&gt;master&lt;/code&gt; when it’s ready and not breaking.&lt;/p&gt;

&lt;h4&gt;
  
  
  Branch naming
&lt;/h4&gt;

&lt;p&gt;And let’s for a moment talk about branch naming. Branch names should be as short as necessary, while still communicating their intention as precisely as possible. Prefixes, such as &lt;code&gt;feat/&lt;/code&gt;, &lt;code&gt;bugfix/&lt;/code&gt;, &lt;code&gt;chore/&lt;/code&gt;, and similar are just noise, and let me tell you why.&lt;/p&gt;

&lt;p&gt;I would argue that any bug fix should be merged as soon as possible. This means that the branch will live for a couple of hours tops. Since you are writing tests (you are writing tests, yes?), you will write a test to specifically test for the buggy condition. Your test will fail at first, and you will develop a fix in a couple of hours. When your test passes, you know that you have fixed the bug, you are free to merge. But wait, this is most likely a single commit, therefore it doesn’t need its own branch and can be done directly on master. You don’t need to wait for QA to test this, because you have already verified that you’ve fixed the bug by running the tests.&lt;/p&gt;

&lt;p&gt;Now let’s talk about chores. What is a chore? Cleaning your room is chore. Taking out the trash is a chore. One would argue that refactoring code is also a chore. But why the hell are you refactoring code just for the sake of it, as a separate task? Code refactoring should be done as a preparation of developing a particular feature that brings value. Refactoring is a part of a feature or a bugfix, and not a separate task on its own. Therefore in reality you won’t see or create branches prefixed with &lt;code&gt;chore/&lt;/code&gt;. If anything, your refactoring commits will go inside your feature branch.&lt;/p&gt;

&lt;p&gt;This leaves us with &lt;code&gt;feat/&lt;/code&gt; or &lt;code&gt;feature/&lt;/code&gt;. Since we have already established, that bugfix branches will either live for a couple of hours or be done on master directly, and there’s no such thing as a standalone chore, then every branch will be some sort of a feature branch. If every branch is a feature branch, why prefix it at all?&lt;/p&gt;

&lt;p&gt;Finally we’re left with ticket number prefixes, such as &lt;code&gt;PRJ-123&lt;/code&gt;. I don’t have a strong opinion on those, as I can see their value for quick reference. But that’s only valid for a case where there will be multiple people checking the branch (like in PR for example). But you could also just add the ticket number to a PR title, and that would work just as good, if not even better.&lt;/p&gt;

&lt;p&gt;One thing that I have a big problem with is &lt;code&gt;NO-JIRA&lt;/code&gt; prefixes. What value does this prefix bring? If there’s no ticket for a task, it’s either a quick fix and will either be done on master directly OR the task is too big, and a ticket needs to be created anyway.&lt;/p&gt;

&lt;h4&gt;
  
  
  Shared dev
&lt;/h4&gt;

&lt;p&gt;In rare instances, it could happen that multiple features can’t be merged to master, but still need to be tested on dev environment. For example you are working on task A and your colleague is working on task B at the same time. You are both working on your own feature branches, but yet you still want both features on dev at the same time.&lt;/p&gt;

&lt;p&gt;Enter the &lt;code&gt;shared-dev&lt;/code&gt; branch. This of course requires clear communication between the team members, but what doesn’t? How you name the branch doesn’t matter at all, as long as people are aware of what’s going on. This &lt;code&gt;shared-dev&lt;/code&gt; branch should be branched off of master, and then your branches should be merged into it. After the branches are merged, the &lt;code&gt;shared-dev&lt;/code&gt; branch is tagged with &lt;code&gt;dev&lt;/code&gt; tag, so that it builds and deploys into dev environment. When changes are made on a feature branch, feature branch again gets merged into &lt;code&gt;shared-dev&lt;/code&gt; and tagged with &lt;code&gt;dev&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;As soon any feature branch appears in &lt;code&gt;master&lt;/code&gt; (read - is ready for release), the &lt;code&gt;shared-dev&lt;/code&gt; MUST be deleted to avoid confusion.&lt;/p&gt;

&lt;h4&gt;
  
  
  Deleting branches
&lt;/h4&gt;

&lt;p&gt;Talking about deletion. For the love of whoever is your god – delete those old branches. If your feature is merged and deployed, there’s no need to keep that old branch and watch as it falls behind hundreds of commits. You can always create a new branch if you need to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commits
&lt;/h3&gt;

&lt;p&gt;You should strive to separate your commits into standalone units of valuable code. Think of it this way – if you need to include &lt;code&gt;and&lt;/code&gt; word into your commit message, maybe you’re actually committing too much (ex. &lt;code&gt;Add this AND change that&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Commit messages should be human readable, and have the most important information upfront. Since we’re not using any automation tools (if we start using them, we will reevaluate this), we shouldn’t prefer cryptic tags &lt;code&gt;fix()&lt;/code&gt;, &lt;code&gt;feat()&lt;/code&gt;  and similar (comes from &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt;, including link just for curiosity) at the start of the message. The ticket reference (&lt;code&gt;PRJ-123&lt;/code&gt;) should go at the end of the message, because it does not communicate immediate information, without having to reference a 3rd party system.&lt;/p&gt;

&lt;p&gt;You should definitely read &lt;a href="https://chiamakaikeanyi.dev/how-to-write-good-git-commit-messages/" rel="noopener noreferrer"&gt;this in depth article about good Git commit messages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Imagine that after doing a commit, you would go on Slack and describe the changes to your colleagues in a message. A great place for that message is actually the commit message body. Add a blank line below your commit message and explain why you made the change, and possibly how to use it.&lt;/p&gt;

&lt;p&gt;A good commit message should look something like this (completely fictional):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add metadata to asset details. PRJ-123

Asset metadata was missing from asset detail page. Metadata is 
needed for OpenSea and similar 3rd party systems in order to
display the asset correctly. Metadata should now be included in
the asset details endpoint.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pull Requests
&lt;/h3&gt;

&lt;p&gt;Pull requests are inefficient, change my mind. First, they stop code from appearing in &lt;code&gt;master&lt;/code&gt; which we have already established is a bad practice in itself. Second, in order to properly conduct a code review (and I mean properly, not only check the indentation), you probably need to spend just as much time as writing the original code. Therefore a better practice is pair programming – in the end just as much time is spent by a couple of people as with PRs, but the added benefit is that the feedback is instant and can instantly be addressed.&lt;/p&gt;

&lt;p&gt;I’m not advocating against pull requests, if you want someone to quickly go over your code just to double check for those low hanging fruits, but I’m also saying you don’t need to ask someone’s permission to do your job.&lt;/p&gt;

&lt;p&gt;On a side note, a senior developer’s approval on a PR does not mean that suddenly you’re off the hook and anything bad that happens with your code is now the responsibility of the approver. It is your responsibility as a professional to make sure that the code meets business requirements and is factored to the best of your abilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  What doesn’t work
&lt;/h2&gt;

&lt;p&gt;Throughout many years, me personally, and the industry as a whole has learned new things. We’ve also learned what doesn’t work, or doesn’t work in our context at least.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitFlow
&lt;/h3&gt;

&lt;p&gt;One of such things is GitFlow. GitFlow is a branching model created by Vincent Driessen more than a decade ago. The author himself, has stated that this is an outdated model, and should not be used in continuous delivery environment. &lt;a href="https://nvie.com/posts/a-successful-git-branching-model/" rel="noopener noreferrer"&gt;Original article here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standalone &lt;code&gt;dev&lt;/code&gt; branch
&lt;/h3&gt;

&lt;p&gt;Some of you may remember times when &lt;code&gt;dev&lt;/code&gt; was a separate branch. A big problem with that is the same as with any other long lived branch – it tends to quickly diverge from &lt;code&gt;master&lt;/code&gt;. Especially if you have many features that are tested on dev, but never end up in production. There comes a point where the whole &lt;code&gt;dev&lt;/code&gt; branch needs to be deleted and then branched off of master again. And that comes with its own sets of pain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;So this was my heavily opinionated article about how Git should be used. If you disagree, please voice your discontent in the comments to boost the engagement. But in all seriousness, let's discuss the process that you find works in your context – I love learning how to improve the efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://continuousdelivery.com/evidence-case-studies/#the-hp-futuresmart-case-study" rel="noopener noreferrer"&gt;HP Case Study on CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/articles/feature-toggles.html" rel="noopener noreferrer"&gt;Feature Flags&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chiamakaikeanyi.dev/how-to-write-good-git-commit-messages/" rel="noopener noreferrer"&gt;How to write good Git Commit messages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How to Bring Back Old IntelliJ Look (somewhat)</title>
      <dc:creator>Rytis</dc:creator>
      <pubDate>Thu, 05 Jan 2023 13:13:51 +0000</pubDate>
      <link>https://dev.to/rytis/bring-back-old-intellij-theme-somewhat-5d6g</link>
      <guid>https://dev.to/rytis/bring-back-old-intellij-theme-somewhat-5d6g</guid>
      <description>&lt;p&gt;There's also a video version of this same article&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lktBPySMDxM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro Rant
&lt;/h2&gt;

&lt;p&gt;Feel free to skip this and go straight to the practical tips.&lt;/p&gt;

&lt;p&gt;All good things come to an end, and it looks like the time has also come for IntelliJ’s old design. While it makes me sad to see JetBrains fall for the VSCodification&lt;sup id="fnref1"&gt;1&lt;/sup&gt; trend, I do realize that it is inevitable, and there will come a moment when this abomination is forced upon us, and there’s not much that I can do about it. So I decided to bite the bullet and switch to the new design to make the transition more gradual - new year, new look, amirite?&lt;/p&gt;

&lt;p&gt;After switching, I am immediately greeted by trendy excessive padding around every element - something that is more suited for a touch interface rather than a productive work tool, and a contrasty color theme that looks like a direct knockoff of VSCode. I even whipped out a color meter to check - colors are not the same, but pretty damn close (VSCode background is 30,30,30 and new IntelliJ’s is 30,31,34, in case you were wondering).&lt;/p&gt;

&lt;p&gt;Anyway, I decided to give it a shot for a day despite my bitterness, and I very quickly realized that I can barely even fit two classes side by side due to that gosh darn padding. And the color contrast was starting to strain my eyes. So I decided to check what settings I can change to actually make it look more like good old days.&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Back To Dracula
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fod03gzzmdyslpf3hmayl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fod03gzzmdyslpf3hmayl.jpeg" alt="Change theme back to Dracula" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing that has the most impact is the actual IntelliJ theme that you are running. And I didn’t know this, but it seems that a lot of padding is actually baked into the theme itself, so changing back to good old Dracula theme already brings back a lot of information density:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdgsdq4kr3tal3btp49hj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdgsdq4kr3tal3btp49hj.jpeg" alt="Filetree density" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While you’re at it, you can also change back to &lt;code&gt;.AppleSystemUIFont&lt;/code&gt; instead of their new &lt;code&gt;Inter&lt;/code&gt; font. I haven’t dove deep into why the new font is better (it very well might be), but I really hate when UIs use non-default fonts, it just falls out of context from the whole OS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disable Auto Opening of Files
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmid56flt8aq286qjxk55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmid56flt8aq286qjxk55.png" alt="Disable Preview Tab" width="712" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another thing that I’ve noticed with the new design is that they’ve enabled file opening by default when you click on the file tree. If I want to open a file, I double click on it. Opening on a single click is annoying, distracting, and might introduce lag depending on the system.&lt;/p&gt;

&lt;p&gt;Apparently this is called “Preview Tab” and to disable it, you have to click on the kebab menu (three vertical dots) and uncheck &lt;code&gt;Enable Preview Tab&lt;/code&gt;. You will now be able to navigate the file tree like the good old days.&lt;/p&gt;

&lt;p&gt;Also, depending on your taste, you might want to check &lt;code&gt;Show tree indent guides&lt;/code&gt; and/or &lt;code&gt;Use smaller indents in trees&lt;/code&gt; in Appearance preferences. I personally don’t like small indents (two spaces as indent must die altogether, but that’s another topic), but indent guides are definitely nice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3f15xgtmu6ced7pojmwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3f15xgtmu6ced7pojmwo.png" alt="Show tree indent guides" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Breakpoints
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1vutb2k265dkfxbg9fd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1vutb2k265dkfxbg9fd.png" alt="Breakpoints over line numbers" width="611" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another change they’ve made is that breakpoints now go over line numbers. This might save a bit of space depending on where you place a breakpoint, but that can also be annoying. You can disable this behavior by right clicking on the gutter and unchecking &lt;code&gt;Breakpoints over line numbers&lt;/code&gt;. I don’t yet have a strong opinion about this one, but I’m experimenting with both.&lt;/p&gt;

&lt;p&gt;A bit annoying addition is the breakpoint preview on mouse over. As far as I know that can’t be disabled unfortunately.&lt;/p&gt;

&lt;p&gt;Talking about right click, I use it a lot on the gutter to enable Git Blame, and oh god did they messed that up. Depending on where you right click it will bring a different context menu. And most annoyingly, if you right click the arrow, it will toggle the fold instead of showing the context menu. This has got me so many times already. Hopefully they will fix this soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navbar / breadcrumbs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9lcayt9avh85katix45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9lcayt9avh85katix45.png" alt="Navbar position" width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They have also changed the location of the Navbar to be in the status bar. If you want to change it back to where you’re used to, you can go to &lt;code&gt;View&lt;/code&gt; &amp;gt; &lt;code&gt;Appearance&lt;/code&gt; &amp;gt; &lt;code&gt;Navigation Bar&lt;/code&gt; &amp;gt; &lt;code&gt;Top&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I personally think it looks weird at the top with the current design, so I will make myself get used to it at the bottom.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Branch View
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6toks148rjs6h5t8koo2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6toks148rjs6h5t8koo2.png" alt="Git Branch view" width="733" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Git Branch view has been removed from the bottom right status bar and everything Git related has been moved to the top left. You can however still enable the old location of Git Branch by going to &lt;code&gt;View&lt;/code&gt; &amp;gt; &lt;code&gt;Appearance&lt;/code&gt; &amp;gt; &lt;code&gt;Status Bar Widgets&lt;/code&gt; &amp;gt; &lt;code&gt;Git Branch&lt;/code&gt;. Now you will be able to control Git from both corners of the screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fat Side Icons
&lt;/h2&gt;

&lt;p&gt;Unfortunately, I haven’t found a way to bring back good old slim text instead of the fat side icons. Those icons do take a lot of useful space, without actually providing more information compared to text. Again, it’s not a touch interface, we don’t need fat buttons, mouse is a precision device, and I don’t think people had trouble clicking it before. But trends are trends, the pendulum will swing to the other side in about 10 years or so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run Widget
&lt;/h2&gt;

&lt;p&gt;I haven’t found a way to customize that either. It seems that you can right click choose Customize Toolbar, but nothing you do there makes a difference. I did read that they will tone down the distracting color of the run widget in the next version. With that said, I’m not a fan of the new run widget either, especially stop button disappearing when nothing is running. But I’ll get used to it eventually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;With these steps I was able to somewhat bring back the old look of IntelliJ and get rid of the annoying padding around everything. When a colleague initially showed me the new theme, I was sad and frustrated that I will soon have to face VSCode looking IntelliJ every day, but after doing a bit tweaking, I can see that the future is not as bleak as initially thought. This brings a bit of peace to my mind, and if you’re anything like me, hopefully this will also bring a little bit of peace to you too.&lt;/p&gt;

&lt;p&gt;Please share your frustrations in the comments, so that we can be frustrated together 🙂. And if you find any tips on making the new design a bit better, then definitely share that in the comments. I will update this post with more tips when they're found. But with that said, thank you for reading my salty rant with a bit of practical information sprinkled in.&lt;/p&gt;

&lt;p&gt;For a list of changes, you can check the &lt;a href="https://youtrack.jetbrains.com/articles/IDEA-A-156/Main-changes-and-known-issues" rel="noopener noreferrer"&gt;Official Post from JetBrains&lt;/a&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;VSCodification trend is when every IDE wants to be like VSCode. Well at least IntelliJ is not an Electron app… yet ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>cloud</category>
      <category>python</category>
      <category>infrastructureascode</category>
    </item>
    <item>
      <title>Should routing go before security?</title>
      <dc:creator>Rytis</dc:creator>
      <pubDate>Tue, 12 Jan 2021 10:12:10 +0000</pubDate>
      <link>https://dev.to/rytis/should-routing-go-before-security-4no8</link>
      <guid>https://dev.to/rytis/should-routing-go-before-security-4no8</guid>
      <description>&lt;p&gt;Recently I've got into an argument with a colleague in regards to what HTTP status to return.&lt;/p&gt;

&lt;p&gt;The way our API works right now: you need to be authenticated to call any route except the ones which are explicitly configured as public. This means that if you call any endpoint (doesn't matter if it exists or not) without a token, you will get a 401 response. If you call a non-existing endpoint with a valid token, only then it returns 404.&lt;/p&gt;

&lt;p&gt;My colleague says that it should be the other way around and we should first check if the route exists and only then validate the token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's your opinion on this issue?&lt;/strong&gt; I've seen it done both ways and I don't have a problem with either approach, but I am leaning more towards returning 401 before 404, because unauthenticated calls shouldn't reveal whether endpoint exists or not.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>security</category>
      <category>help</category>
    </item>
    <item>
      <title>How I Fixed IntelliJ Build Problems After MacOS Update</title>
      <dc:creator>Rytis</dc:creator>
      <pubDate>Wed, 27 Nov 2019 10:25:48 +0000</pubDate>
      <link>https://dev.to/rytis/how-i-fixed-intellij-build-problems-after-macos-update-1kg</link>
      <guid>https://dev.to/rytis/how-i-fixed-intellij-build-problems-after-macos-update-1kg</guid>
      <description>&lt;h1&gt;
  
  
  Backstory
&lt;/h1&gt;

&lt;p&gt;Feel free to skip this section if you don't care for a short story. There's a tl;dr; at the bottom.&lt;/p&gt;

&lt;p&gt;I came back to work after my vacation, fired up IntelliJ, punched in a few lines of code, compiled my Spring project, and... nothing changed. No errors, everything compiled and ran perfectly.&lt;/p&gt;

&lt;p&gt;At first I thought that this was cache related, even though I was doing http requests through Postman. So I entered a few logging lines on startup and tried again just to find that they too were not shown.&lt;/p&gt;

&lt;p&gt;I then tried to do a &lt;code&gt;Build &amp;gt; Rebuild Project&lt;/code&gt; and got an error saying something along the lines of &lt;code&gt;Could not get UNIX mode on /ProjectDir/build/File.class. File does not exist&lt;/code&gt;. It was then that I realized that there was something wrong with build folder access.&lt;/p&gt;

&lt;h1&gt;
  
  
  How I Solved It
&lt;/h1&gt;

&lt;p&gt;Since build folder is generated automatically I simply deleted it for the offending submodule. When I tried to rebuild the project, another submodule that previously compiled now showed different errors.&lt;/p&gt;

&lt;p&gt;I remembered that during my vacation I upgraded MacOS to the newest version and the update probably messed with the user or permissions or something along those lines.&lt;/p&gt;

&lt;p&gt;So I just deleted &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;out&lt;/code&gt; folders for all the submodules, rebuilt the project successfully and voila - all was good and I started seeing the changes I've made.&lt;/p&gt;

&lt;p&gt;Moral of the story - delete generated folders after OS upgrade, just in case.&lt;/p&gt;

&lt;h1&gt;
  
  
  TL;DR;
&lt;/h1&gt;

&lt;p&gt;After upgrading to the latest MacOS, new changes to my Java code didn't  make it into compiled version. I fixed it by deleting generated &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;out&lt;/code&gt; folders for every submodule.&lt;/p&gt;

</description>
      <category>java</category>
      <category>todayilearned</category>
      <category>macos</category>
    </item>
    <item>
      <title>Setting up Intellij to close previously running build</title>
      <dc:creator>Rytis</dc:creator>
      <pubDate>Thu, 07 Nov 2019 16:28:30 +0000</pubDate>
      <link>https://dev.to/rytis/setting-up-intellij-to-close-previously-running-build-1m90</link>
      <guid>https://dev.to/rytis/setting-up-intellij-to-close-previously-running-build-1m90</guid>
      <description>&lt;p&gt;Hello there, I've been struggling with this problem for 2 days now and I am completely lost.&lt;/p&gt;

&lt;p&gt;So I've upgraded to most recent IntelliJ Idea and it turns out that they've changed the default "Build and Run" option to be Gradle (under &lt;code&gt;Preferences &amp;gt; Build, Execution, Deployment &amp;gt; Build Tools &amp;gt; Gradle&lt;/code&gt;. Which is totally fine by me, if not that annoying feature where it now starts up as many instances of the program as you click run.&lt;/p&gt;

&lt;p&gt;It used to be like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I punch in a few lines of code&lt;/li&gt;
&lt;li&gt;Ctrl + R to build and run (under Mac, Windows has another shortcut)&lt;/li&gt;
&lt;li&gt;Old instance of my program terminates&lt;/li&gt;
&lt;li&gt;New instance of my program launches&lt;/li&gt;
&lt;li&gt;Go to step 1 and repeat ad infinitum&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And now it's like this&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ctrl + R to build and run&lt;/li&gt;
&lt;li&gt;Gradle builds the program&lt;/li&gt;
&lt;li&gt;Program starts up, but the build keeps spinning&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Build only stops when I close the program manually. If I press Ctrl + R again, a new build launches with a new instance of the program and I find myself running 15 instances of slightly different programs more times than not.&lt;/p&gt;

&lt;p&gt;So ideally I would like the build to be marked as complete when the actual build finishes and not when I close program. Also I would like to run only one instance of the program at a time and if I build a new one, I want old one to close down.&lt;/p&gt;

&lt;p&gt;By the way, Parallel run is not checked under run configurations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Another Problem
&lt;/h2&gt;

&lt;p&gt;Now I could just change "Build and Run" option to be IntelliJ and be happy with the old functionality that I liked before. The problem is - when I do this it suddenly can't find any of my resources. The resource folder is marked as resource root. I can also find my resources moved to &lt;code&gt;build/resources/main/&lt;/code&gt;. But &lt;code&gt;getClass().getResource("/asd.fxml")&lt;/code&gt; always returns null.&lt;/p&gt;

&lt;p&gt;I also cannot change anything in &lt;code&gt;File &amp;gt; Project Structure&lt;/code&gt; as applying any changes starts throwing all kinds of errors, and the structure is managed through Gradle anyway.&lt;/p&gt;

&lt;p&gt;I'll buy a pizza for anyone who helps me with either of the problems.&lt;/p&gt;

</description>
      <category>help</category>
      <category>java</category>
    </item>
    <item>
      <title>Hiring the Right People</title>
      <dc:creator>Rytis</dc:creator>
      <pubDate>Mon, 19 Aug 2019 20:33:18 +0000</pubDate>
      <link>https://dev.to/rytis/hiring-the-right-people-3i0g</link>
      <guid>https://dev.to/rytis/hiring-the-right-people-3i0g</guid>
      <description>&lt;p&gt;Hey, community! Recently I've been invited to give a talk at a local conference about the early stages of a startup and I chose to speak about my take on hiring the right people. I thought that it would be beneficial to share my speech with y'all.&lt;/p&gt;

&lt;p&gt;It may not be directly development related, but I'm speaking mostly from the perspective of a CTO and long time team lead to a crowd of people interested in starting their own companies.&lt;/p&gt;

&lt;p&gt;Please share your thoughts and insights in the comments!&lt;/p&gt;




&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;So, you have a killer idea that has been circling around in your head for quite some time? You finally decide to take that leap of faith and start up a company. A startup! Maybe you’ve been working on an idea alone and now you’re looking to expand? The only problem is – what kind of people do you need? Can’t you just get a bunch of programming students to work their magic and then a bunch of marketing students to push your product on the cheap? Well let’s find out, shall we?&lt;/p&gt;

&lt;h1&gt;
  
  
  The Most Important Person in Your Company is You!
&lt;/h1&gt;

&lt;p&gt;Now that sounds a bit egocentric, doesn’t it? Well hear me out on this one. When a company is young, the first people you hire are going to be the most important ones. They will shape the culture and work ethic. And while you’re alone, you are the one shaping those things.&lt;/p&gt;

&lt;p&gt;You must also take good hard look at yourself and figure out your strengths, but most importantly your weaknesses, which brings us to the next point.&lt;/p&gt;

&lt;h1&gt;
  
  
  Find a Co-founder Who Complements Your Own Skill Set
&lt;/h1&gt;

&lt;p&gt;A great co-founder is a must if you want to keep your sanity. A co-founder should fill in the gaps in the skills that you lack. Maybe you’re a good programmer, but not such a good salesman? Then the co-founder should fill in that gap and be a great salesman. In the ideal world, co-founder skills should hardly overlap yours. It’s a great way to let everyone do what they do best and avoid conflicts when someone has a different approach to the same problem.&lt;/p&gt;

&lt;p&gt;At my current company we have a great dynamic, where my colleague knows a lot about the Danish tax system, but nothing about programming, and I am just the opposite – I know programming and system architecture, but nothing about the Danish tax. Working like this, we just need to sync up once a week and continue doing what we do best!&lt;/p&gt;

&lt;p&gt;With that said, there will come a time when you need to bring in more talent to the team.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hire for a Team Fit, not for Skills
&lt;/h1&gt;

&lt;p&gt;Time and time again, I have seen startups hire a candidate that looked great on paper, but once they joined, they started struggling to fit in. And when people are struggling to fit in, their productivity suffers. They will want to spend less time around other people in the office. They will struggle with communication. They won’t be sincere with their feedback.&lt;/p&gt;

&lt;p&gt;A great example is the experience of a company I used to work for. The team dynamic in the company was great! Everyone considered their colleagues a family, organized events together, spent time outside work as friends, and so on. And then we hired a new developer. As his skill set was all right, and he had considerable experience, we didn’t dig much deeper and after a few interviews we invited him to join. After a few weeks, the mismatch was starting to become apparent – he didn’t like any of the same things as anyone else. Although he was extroverted, it didn’t interest him to attend any of the team-building events. And even though everyone in the team was trying hard to find some common ground with the fellow, he just didn’t seem to click. The worst of it all was he was working on a module alone and left immediately after he got offered a bit more money at another company. &lt;/p&gt;

&lt;p&gt;The damage was 4 months of above average salary for the developer, plus 3 months to find a new developer, plus rewriting the module he was working on from scratch since it didn’t do anything it was supposed to do. And since the budget runway was 12 months, it was a pretty significant cost for that startup.&lt;/p&gt;

&lt;p&gt;Remember, skills can almost always be learned, team fit cannot. So, hire slow, hire carefully. Allow a trial period for potential candidates, take them out for a beer, go to a concert with them. A good colleague is the one you don’t hate seeing outside work! But…&lt;/p&gt;

&lt;h1&gt;
  
  
  Don’t Hire Your Friends
&lt;/h1&gt;

&lt;p&gt;You may think that it’s a good idea, you know your friends, they’re great people. But once you add salary into the mix and change the rules from being their friend to becoming their boss, it tends to get messy. Friends and money don’t mix. They may start slacking off, just because they know you as a friend. Then you might want to push them, but it comes off as harsh and they feel attacked. And in the end, everyone’s mad and you just lost a co-worker AND a friend.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, some people can indeed separate their work life and social life, but it’s best not to take that risk.&lt;br&gt;
I say – let them become your colleagues first, and your friends afterwards. This way you won’t mess up the chain of command.&lt;/p&gt;

&lt;h1&gt;
  
  
  Early Team Culture is Super Important
&lt;/h1&gt;

&lt;p&gt;Now let’s take a step back and discuss your team culture. The first people you hire are the most important ones. As I’ve mentioned at the beginning – they will shape the work ethic, the way people interact, the way they communicate. It is highly unlikely that you will be hiring a lot of new people at the same time, so the new people are going to be a minority. They will have to adapt to the existing culture and are most likely to start mimicking the way everyone else is behaving. It’s a primal instinct. So once the tone is set, it may be very difficult to change afterwards. And changing it may even result in your key people leaving, because you just changed the way they had been doing things since the beginning.&lt;/p&gt;

&lt;h1&gt;
  
  
  Don’t Waste Time or Money on Subpar Talent
&lt;/h1&gt;

&lt;p&gt;You have to hire great people if you want to have a great product. But great people don’t come cheap. It may be tempting to bring in a student because, hey, they’re cheap and they still get the job done. But those savings are going to quickly bite you in the butt in the form of a technical debt. The structure may be all messed up and the project will reach an unscalable state where adding a new feature takes so long that it’s best not to start at all. And let me tell you – rewriting the project costs at least 3 times more than you ever anticipated. So, it is best to just get one really smart person for a price of two mediocre ones, everyone will thank you later.&lt;/p&gt;

&lt;p&gt;Here’s another example from a company I used work for. The company used to sell a SaaS product and hired only student interns as salespeople. Since most of the students were on Erasmus, they would leave in half a year. This was fine for cold calling when the product was just a single small module. But once it got bigger, it took a lot time to train those students about that product. And by the time they knew everything about the product they were selling; it was time for them to leave. Fortunately, this was noticed by the board and 15 sales interns were replaced by a few skilled full-time salespeople.&lt;/p&gt;

&lt;h1&gt;
  
  
  It Doesn’t Always Have to Be About the Money
&lt;/h1&gt;

&lt;p&gt;When you’re running a startup, money is always very limited. You may not have enough money for the talent that you want. But it doesn’t always have to be about the money. Top-tier people can always get a well-paid position, so money is mostly not a priority for them anymore. They are usually looking for an interesting project with highly motivated people with whom they can collaborate. So, think what your startup can offer your employees beside money. And no, a foosball table is not that thing. In my career as a lead developer I have deduced that freedom is what works. I tend to allow people as much freedom as possible – want to work from home? That’s fine as long as the communication is good, and the job gets done. Don’t feel like working today? Take a day off – it’s much more efficient to rest for a while than to force yourself to squeeze that last drop of energy.&lt;/p&gt;

&lt;p&gt;Another thing you can offer, and I know I have mentioned it a lot before, is a great team. I would always choose a great team versus more money in a bad team.&lt;/p&gt;

&lt;h1&gt;
  
  
  It’s Cheaper to Retain Your Current Staff
&lt;/h1&gt;

&lt;p&gt;Since money at startups is in short supply, employee turnover can be deadly. An employee leaving does not only mean compensating them for their unused vacation days, paying a recruiter to find a new candidate, and training them. You should also factor in the cost of lost knowhow. Maybe that girl who just left had been working on something alone and now someone else has to dedicate their time to understand her work. Moreover, a leaving team member can cause a domino effect and other members may follow in their footsteps, which I’ve seen time and time again. And if you’re hiring in a market with a very scarce supply of talent, such as programmers, it means there won’t be any freely available employees. Which then, in turn, means that you will have to headhunt people from other companies, which will again hike up your costs.&lt;/p&gt;

&lt;p&gt;Therefore, it is much cheaper to retain people that are already working for you. Ask for their honest opinion on the current state of the company monthly. And if they don’t feel like they’re valued enough, it will always be cheaper and more beneficial in the long run to give them a small pay bump rather than going through the leave-recruit-train process over and over again.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Most Suitable Person May Already Be in Your Team
&lt;/h1&gt;

&lt;p&gt;It is always the easiest not to hire new people at all. This again boils down to communication and knowing your colleagues very well. Talk with your existing employees about what excites and interests them. You may find that this one extroverted HR rep is actually a pretty good salesman. Or this introverted developer is actually very good with social media. And introducing changes into someone’s day to day work may provide them with that very well needed break from the rut. You may be surprised at what hidden talents you may find.&lt;/p&gt;

&lt;h1&gt;
  
  
  Fire Early, Fire Fast
&lt;/h1&gt;

&lt;p&gt;However, there will come a time when someone you hire will just not work out. It may be that they’re just not bonding with the rest of the team. Or it may be that you find out that their skills are lacking after all. In that case, it is much more beneficial to just let them go. Do it fast, because the longer they spend working on something that will have to be transferred to another employee, the more it will cost YOU.&lt;/p&gt;

&lt;h1&gt;
  
  
  Outsource Everything Else
&lt;/h1&gt;

&lt;p&gt;With all that said, maybe you don’t even need a full-time person to do some of the work. I have found that outsourcing some tedious or one-off jobs may seem to cost more upfront, but it may actually lead to better results if you’re hiring a really professional agency or person. Always try to evaluate whether the task at hand must be handled by you or your team or is it something an outsider could easily do. Outsourcing can alleviate the stress from yourself and your colleagues. Try it, you may not regret it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lead by Example
&lt;/h1&gt;

&lt;p&gt;Finally, I’d like to give a few important examples on being a bad founder after you’ve already assembled a team. A company that I was advising had a great and motivated team that liked getting things done. They also had a CEO who was so overworked that he was always late for meetings and sometimes even forgot them outright. Over time, I saw that team transform from punctual go getters to just not caring at all. Their argument was: if the CEO doesn’t care much about their time, neither should they care about the company’s time. By the time I stopped advising the company, their meetings got delayed on average by about 30 minutes, just because they were waiting for people who didn’t care to show up.&lt;br&gt;
And same with deadlines. The CEO would promise to deliver the specification on a certain day, and then he would just forget about it, so the team also started skipping deadlines because they saw that it was just not important for the company’s brass.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Good Founder is a Good Router
&lt;/h1&gt;

&lt;p&gt;Talking about that same company. Their CEO used to want to do everything himself – bookkeeping, taxes, sales, product ownership, wireframes, he even suggested how the database should be structured. No wonder he was overworked, late and skipping meetings. Therein lies the problem – don’t try to do everything yourself. When people bring up a problem, redirect them to someone who can handle that problem. Empower people to make their own decisions and hold them accountable for them. &lt;/p&gt;

&lt;p&gt;Make yourself available and don’t do the work that someone else can do. For example, you don’t have to do your own taxes – hire a tax advisor once a year or so. Your employees will thank you for having you available when they need your input.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Here I have told you about my take on hiring the right people. Please note that this is tailored for small startup teams and may not work at a larger scale (but you don’t want it to). Always use strategies that fit your current state of the company and never try to apply a 100 people strategy to a 5-person team. Don’t follow everything by the book, chances are your situation is different.&lt;/p&gt;

&lt;p&gt;To sum up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The most important person in your company is YOU&lt;/li&gt;
&lt;li&gt;Find a co-founder who compliments your own skill set&lt;/li&gt;
&lt;li&gt;Hire for a team fit, not for skills&lt;/li&gt;
&lt;li&gt;Don’t hire your friends&lt;/li&gt;
&lt;li&gt;Early team culture is super important&lt;/li&gt;
&lt;li&gt;Don’t waste time or money on subpar talent&lt;/li&gt;
&lt;li&gt;It doesn’t always have to be about the money&lt;/li&gt;
&lt;li&gt;It’s cheaper to retain your current staff&lt;/li&gt;
&lt;li&gt;The most suitable person may already be in your team&lt;/li&gt;
&lt;li&gt;Fire early, fire fast&lt;/li&gt;
&lt;li&gt;Outsource everything else &lt;/li&gt;
&lt;li&gt;Lead by example&lt;/li&gt;
&lt;li&gt;A good founder is a good router&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thank you for taking your time to read this long text.&lt;/p&gt;

</description>
      <category>hiring</category>
      <category>startup</category>
      <category>founders</category>
    </item>
  </channel>
</rss>
