<?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: Tobias Nickel</title>
    <description>The latest articles on DEV Community by Tobias Nickel (@bias).</description>
    <link>https://dev.to/bias</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%2F84818%2F4558dd5a-4d9d-47f7-acbd-875b8db16f9f.jpg</url>
      <title>DEV Community: Tobias Nickel</title>
      <link>https://dev.to/bias</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bias"/>
    <language>en</language>
    <item>
      <title>The Odyssey of an E-Commerce Order</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Wed, 29 Oct 2025 12:14:06 +0000</pubDate>
      <link>https://dev.to/bias/the-odyssey-of-an-e-commerce-order-o09</link>
      <guid>https://dev.to/bias/the-odyssey-of-an-e-commerce-order-o09</guid>
      <description>&lt;p&gt;Recently, after an exhausting 30-kilometer cycling sprint, I made a terrifying discovery: a chain link was suffering from a critical integrity breach! Thankfully, I'd managed to bootstrap my way home - the thought of pushing my bike for ten kilometers was a genuine nightmare scenario. So, I immediately logged in to provision a replacement part online. What followed was a masterclass in suboptimal data management.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Initial Data Handshake
&lt;/h2&gt;

&lt;p&gt;My journey began on the frontend of Vendor D's e-commerce platform. I initiated an order for a new bike chain. The first point of friction appeared during the checkout process: the selected chain cleaning solution was from a different microservice/vendor, triggering separate shipping APIs and demanding additional freight charges. I quickly decided to swap it for an alternative chain lubricant. For shipping, I stuck with the default parameter, which meant the package would be dispatched via the "Logistics Expert," Carrier H. Payment was swiftly processed via the Payment Gateway P, which directly transmitted my address data to Vendor D - this was accurately displayed to me in the final confirmation receipt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shipping Data Black Hole
&lt;/h2&gt;

&lt;p&gt;The following Monday, I received the shipping notification from Carrier H. Curiously, my street name was omitted from the payload, which I initially dismissed as a security feature (a common misconception!). Three days later, on Thursday, the major incident: an email informed me that my address had failed validation checks and I needed to establish contact with Carrier H within 10 days. The customer service portal was exclusively managed by a chatbot - a true test of patience, but at least I was promised that the package would be delivered within the next two days.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Back-End Disaster Recovery Failure
&lt;/h2&gt;

&lt;p&gt;As a Software Engineer, I was genuinely flummoxed. It took Carrier H three whole days to flag the address as invalid data! The package was stuck in a pointless holding state before even being loaded onto a truck, only for the driver to discover an address resolution error. This isn't just a poor User Experience (UX); it's an extremely expensive operational overhead for the company.&lt;/p&gt;

&lt;p&gt;My address was double validated transmitted correctly to the Online Vendor D. Granted, my street name is quite long. But here's the query: Shouldn't both Vendor D and Carrier H have implemented an address pre-validation routine? Both could have leveraged simple, publicly accessible external APIs such as OpenStreetMap or Google API for robust data verification.&lt;/p&gt;

&lt;p&gt;And even if Carrier H constantly struggles with long street names, shouldn't Vendor D - as a market leader - have already iterated on this feedback? Shouldn't they have a clear protocol for correctly interacting with Carrier H's service endpoints?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Focus on Data Architecture
&lt;/h2&gt;

&lt;p&gt;This narrative involves multiple enterprises that should be operating in a tightly integrated ecosystem. Each utilizes a myriad of systems that predominantly communicate through automated pipelines. As a Software Consultant and Developer, I see immense potential for optimization: processes could be made more lean, Total Cost of Ownership (TCO) reduced, and the Customer Service Level Agreement (SLA) significantly improved.&lt;/p&gt;

&lt;p&gt;My urgent recommendation to Vendor D and Carrier H: Prioritize and refactor your Data Management Architecture! Both companies have internal access to truly massive data lakes. This inherent potential must be harvested to elevate service quality while simultaneously de-risking and reducing costs. If an external observer can spot such glaring data integrity gaps and simple fixes, there are certainly far greater potentials that can be unlocked with solid Data Governance.&lt;/p&gt;

&lt;p&gt;Are you seeking support to optimize your data flows and streamline your processes? Then &lt;a href="https://www.codoflow.com/" rel="noopener noreferrer"&gt;Codoflow&lt;/a&gt; might give you the right starting point for you.&lt;br&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%2Febtmsh6royupgmfrmui9.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%2Febtmsh6royupgmfrmui9.png" alt=" " width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would you like me to highlight any specific IT terms in the translation or perhaps draft a social media post based on this article?&lt;/p&gt;

</description>
      <category>data</category>
      <category>architecture</category>
      <category>schema</category>
      <category>datatransfer</category>
    </item>
    <item>
      <title>Two Types of SmartContracts</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Tue, 16 Aug 2022 11:09:03 +0000</pubDate>
      <link>https://dev.to/bias/two-types-of-smartcontracts-5e1g</link>
      <guid>https://dev.to/bias/two-types-of-smartcontracts-5e1g</guid>
      <description>&lt;p&gt;For blockchain technologie and web3 it is today needed to use smartcontracts. today I want to discuss two greatly differences between smartcontracts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;single process contract&lt;/li&gt;
&lt;li&gt;business rule contract&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  single pricess contracts:
&lt;/h2&gt;

&lt;p&gt;On public blockchains such as eth one deployed smartcontract is meaned to represent one business process. they can be used to lock in some money(eth or a currency on that blockchain) and releqse it after some condition is met.&lt;/p&gt;

&lt;p&gt;Single process contracts can also be used to reflect ownership of some property. To do so they store a reference to the propery(art, house, car, certificate...) and a reference to the owner. depending on the usecase, the ownership can be transfered or not or only under defined conditions. &lt;/p&gt;

&lt;h2&gt;
  
  
  business rule contracts
&lt;/h2&gt;

&lt;p&gt;In private or consortium blockchains business rule contracts are used. Often these blockchain systems make a distinction of two data systems. First the blockchain itself, that is holding transactions in sequential order, that order can not be changed. And second a state database.&lt;/p&gt;

&lt;p&gt;In hyperledger fabric, the state db is defined as a key value store, and in most cases implemented using couchdb. In sawtooth the data store is a custom merkle tree that is also used like a key value store.&lt;/p&gt;

&lt;p&gt;The smartcontract in a business rule blockchain define the rules how a business is run. technically defining methods that will update the state database and apply rules for authentication and other validations.&lt;/p&gt;

&lt;h2&gt;
  
  
  implications
&lt;/h2&gt;

&lt;p&gt;When learning about etherium smartcontracts, I often asked: how do I store all my data. and the answer is: you don't. One smartcontract only reflects one business process and hopefully that process is finite(has an end, even if it is far in the future).  You might give the eth contract and its methods a meaningful name, but the true meaning comes from the application that is interacting witg that contract. &lt;/p&gt;

&lt;p&gt;Business rule contracts can represent business processes and rules much better and more clear. however instead of defining the rules for once incident of a process, they describe the rules for the long run. This is making it much more important to reach consensus of the business rules/smartcontract. This is making it particular hard to stablish this kind of contract, not technically but organisatorial.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>eth</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>RESTful verbs vs Real actions</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Tue, 05 Jul 2022 00:27:25 +0000</pubDate>
      <link>https://dev.to/bias/restful-verbs-vs-real-actions-51k</link>
      <guid>https://dev.to/bias/restful-verbs-vs-real-actions-51k</guid>
      <description>&lt;p&gt;In http rest APIs we are stuck with a very limited set of verbs. They are essentially:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;get: to load data&lt;/li&gt;
&lt;li&gt;post: to create new data&lt;/li&gt;
&lt;li&gt;put: to replace data&lt;/li&gt;
&lt;li&gt;patch: to update data&lt;/li&gt;
&lt;li&gt;delete: to remove data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the verbs of a typical CRUD operation. They are very effective. But let me tell you a story:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the afternoon you patch your location to your mothers house. After that you get her data and patch her status to happy. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a small situation, told as if you tell a story to a database. Here is the same story, but for the application layer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the afternoon you drive into the city to your mothers house. After you see her, you notice her pretty dress. You make her a nice compliment. That makes her very happy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What version of the story do you prefer?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>story</category>
      <category>api</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How often google crawls my websites sitemap.xml</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Mon, 25 Jan 2021 15:36:17 +0000</pubDate>
      <link>https://dev.to/bias/how-often-google-crawls-my-websites-sitemap-xml-1i5g</link>
      <guid>https://dev.to/bias/how-often-google-crawls-my-websites-sitemap-xml-1i5g</guid>
      <description>&lt;p&gt;My website has a sitemap.xml for years. It automatically get updated when I publish a new article. Or any new content.&lt;/p&gt;

&lt;p&gt;Since last November I use the google search console. There I can see how my website has performed in the google search. In the search console web app, you can add the url to your sitemap.xml. I did and I found google had already read it. The last time two days ago.&lt;/p&gt;

&lt;p&gt;I observed, when it was read again, it was three weeks later on December 17. In all this time I published 5 more articles already (not all of them here in dev). But ok, Google would know that there are 5 new pages at once.&lt;/p&gt;

&lt;p&gt;Then I published more stuff. Ohh in December I wrote a number of articles, that was a good month. And I keep observing when google pick up the sitemap.xml. It took an other week that it was crawled again.&lt;/p&gt;

&lt;p&gt;Now I decided, I will every time when google is coming have something new. I added a new section to my website a developer log, where I can write what I developed on a day in a less structured way, compared with nice worked out articles.&lt;/p&gt;

&lt;p&gt;Today, In the later half of January, I can see, that google read my websites sitemap.xml every day.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;When there is very irregular new content on your website, google will crawl the websites sitemap also less regular. When google find something new, it comes back more often. In that way, google is like a hungry wild cat.&lt;/p&gt;

&lt;p&gt;Now let us feet the cat and comment and share and make some good content.&lt;/p&gt;

</description>
      <category>web</category>
      <category>seo</category>
      <category>blogging</category>
    </item>
    <item>
      <title>TCP and UDP did you ever use them directly?</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Mon, 18 Jan 2021 09:09:16 +0000</pubDate>
      <link>https://dev.to/bias/tcp-and-udp-did-you-ever-use-them-directly-33c3</link>
      <guid>https://dev.to/bias/tcp-and-udp-did-you-ever-use-them-directly-33c3</guid>
      <description>&lt;p&gt;Did you ever had a project where you used lower level protocols directly?&lt;/p&gt;

&lt;p&gt;Usually we use &lt;code&gt;http(s)&lt;/code&gt;, a lib like &lt;code&gt;grpc&lt;/code&gt; or service &lt;code&gt;SDK&lt;/code&gt;s such as for databases.&lt;/p&gt;

&lt;p&gt;But did you ever build an app that use &lt;code&gt;tcp&lt;/code&gt; or &lt;code&gt;udp&lt;/code&gt; directly or define your own protocol on top of them?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
      <category>programming</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How I removed google analytics and still have good data to analyze</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Fri, 25 Dec 2020 05:19:48 +0000</pubDate>
      <link>https://dev.to/bias/how-i-removed-google-analytics-and-still-have-good-data-to-analyze-1c50</link>
      <guid>https://dev.to/bias/how-i-removed-google-analytics-and-still-have-good-data-to-analyze-1c50</guid>
      <description>&lt;p&gt;It was just recently, that I opened my google analytics account and added it to this website. I wanted to get some insights, about my website's visitors. But compared to the google search console, there was not much information interesting to me. &lt;/p&gt;

&lt;p&gt;And actually I worried a little. Is it legal to just add analytics? analytics was easy to add, just adding a script tag into my page. In EU it is needed to inform the user about non essential cookies. Before setting one, it is needed to ask the users consent. However, analytics got added using a static html tag and there is no way to control what cookies are set immediately.&lt;/p&gt;

&lt;p&gt;I was not sure if I should create that script tag dynamically after asking the user, using some client side javascript. and would analytics still work?&lt;/p&gt;

&lt;p&gt;On the internet when searching for analytics without cookies there are many websites advising to use &lt;code&gt;motomo&lt;/code&gt;. It is a very good solution made with php and mysql. But for my little blog setting up this server seem a little to much. Also because I would have to look that I keep it up do date and do some more security measures. For real production application, google analytics and &lt;code&gt;motomo&lt;/code&gt;, both will be a better choice recording lots of data you don't know now you want to have in the future.&lt;/p&gt;

&lt;h1&gt;
  
  
  My Solution to do Analytics without Analytics
&lt;/h1&gt;

&lt;p&gt;I added a little script into my website. Instead of cookies it uses local storage. local storage can not be used to track users across other websites. So I think this should comply with the law. Also in the storage there is nothing stored to identify the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// analytics&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastViewTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastViewTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;viewCount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastViewPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastViewedPage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastViewTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;viewCount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewCount&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastViewedPage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/pageViews&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;viewCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;lastViewTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lastViewTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastViewPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lastViewPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;userLanguage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;referrer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;referrer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dayTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dayTime&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;  
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pageViewResult:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the server I just dump this information into a jsonl file, meaning one json log entry each line. It can easily be converted to csv for analyses via &lt;code&gt;excel&lt;/code&gt;. Draw some charts or count per interval weekly and monthly interval.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageViewRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createWriteStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// 'a' means appending (old data will be preserved)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/pageViews&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;userLanguage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userLanguage&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;viewCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;viewCount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;lastViewTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastViewTime&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;lastViewPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastViewPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;referrer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;referrer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dayTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you see, that I do not check if the browser supports the &lt;code&gt;fetch&lt;/code&gt; API and modern arrow functions? I was thinking about it, and decided that I don't need to care about old browser compatibility for this optional feature.&lt;/p&gt;

&lt;p&gt;You see all the fields that are getting stored. These are what I came up with. That I think are interesting. To be honest, the API shown is not exactly the one running at tnickel.de, but the concept is this. On my running implementation I validate the received data, store urls and user agent string into a separate &lt;a href="http://tnickel.de/2020/11/20/2020-11-rapid-prototyping-with-json-file-database/"&gt;json file database&lt;/a&gt; and write the id into the log file. But with this example you can understand how you can implement the server side yourself.&lt;/p&gt;

&lt;h1&gt;
  
  
  How others do it
&lt;/h1&gt;

&lt;p&gt;As by chance: The dev.to community, was just asked about analytics tools. And I described my little solution. The &lt;a href="https://dev.to/madza/what-web-analytics-tools-do-you-use-458o"&gt;comment&lt;/a&gt; received a reply by &lt;a href="https://charanj.it/"&gt;Charanjit Chana&lt;/a&gt;, saying he is using a similar solution, here is what I found on his websites source code (it was minified, so I formatted it a little):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;allowedToTrack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doNotTrack&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doNotTrack&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;msDoNotTrack&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;external&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msTrackingProtectionEnabled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;external&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doNotTrack&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doNotTrack&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doNotTrack&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;msDoNotTrack&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;external&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;msTrackingProtectionEnabled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;allowedToTrack&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8999999&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="c1"&gt;// this request then set the cookie. &lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://123.charanj.it/xyz/api/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/false/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%c👋 Hey!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-size: 16px; font-weight: 600&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%cIf you can see this I would love to hear from you.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-size: 16px;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%cYou can find me at https://twitter.com/cchana.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-size: 16px;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%cUse the hashtag #cchanaconsole&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-size: 16px;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%c🤙 🖖&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-size: 16px;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems as head of development he is interested in finding new developer talents for his team. I like the &lt;code&gt;allowToTrack&lt;/code&gt; function used before the analytics request is made. This request then set a cookie, so multiple page views can be related to the same user and session. I don't know about the rules in England after it left the EU, but I believe in Germany, an additional popup banner would be needed. Other than me, Charanjit is interested in the users screen resolution to know what to optimize the page for.&lt;/p&gt;

&lt;h1&gt;
  
  
  How do you analytics on your website?
&lt;/h1&gt;

&lt;p&gt;You now have seen two valid approaches to building the client side for collecting analytics information. With this article, I hope you find how how this website does analytics, without tracing the users all over the internet and even into their darkest dreams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update January
&lt;/h2&gt;

&lt;p&gt;In a number of comments people point out, that storing identification data in local storage is under the law similar to storing it directly as a cookie.&lt;/p&gt;

&lt;p&gt;I was thinking this would be OK, because it would mean, that you can not be tracked with it over other websites. But anyway, I did not store personal identifiers. Or did I?&lt;/p&gt;

&lt;p&gt;I think at this point you have to really believe the website operator try to trick you. And if they really wanted, it would be easier to simply show a cookie banner and get consent.&lt;/p&gt;

&lt;p&gt;But lets us pretend I wanted to track you personal journey on my(your) website. With the recorded information, there is the viewCount and ViewTime the current and last URL. Just like that these information can plot a journey, but are not connected to a person. However when I or any other web provider with such solution plan to connect journeys with user information that could be possible by: provide a feature or content on the page that require authentication. At the moment of authentication it would be possible to connect that user with his already journey. And that is not good.&lt;/p&gt;

&lt;p&gt;Here is some idea, that can make it more difficult for you to connect a journey to a user, but still maintain good insights to users in general.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Round the timestamps to a full minute or several minutes.&lt;/li&gt;
&lt;li&gt;Same with the viewCount. I came up with the following function. The function still allow you to know if there are regular users or just random spontanious visitors.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;normalizeViewCound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sqrt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sqrt&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here is the version that I currently use for my website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastViewTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastViewTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;viewCount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastViewPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastViewedPage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;visitTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// normalize the time&lt;/span&gt;

&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastViewTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;visitTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;viewCount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastViewedPage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;normalizeViewCound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sqrt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sqrt&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/pageViews&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;viewCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;normalizeViewCound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;viewCount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;visitTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastViewTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lastViewTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastViewPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lastViewPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;userLanguage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;referrer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;referrer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dayTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visitTime&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pageViewResult:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these changes, the privacy of my and your users is greatly improved. However, I can't really give legal advice here and know for certain if the measures are enough. Maybe it is just easier to just show the users a cookie information and shameless track them into their most private dreams.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>analytics</category>
      <category>blog</category>
    </item>
    <item>
      <title>How big or small should microservices be?</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Thu, 17 Dec 2020 10:07:40 +0000</pubDate>
      <link>https://dev.to/bias/how-big-or-small-should-microservices-be-1c13</link>
      <guid>https://dev.to/bias/how-big-or-small-should-microservices-be-1c13</guid>
      <description>&lt;p&gt;How big are microservices? They are small. How do you even messure it? lines of code? needed memory? amount of data processed? complexity(of any kind)?&lt;/p&gt;

&lt;p&gt;Does running an app in docker makes it a micro service architecture? and how big would you say is a cloud function in comparison?&lt;/p&gt;

&lt;p&gt;and I would also like to see some wrong and fun answers. &lt;/p&gt;

</description>
      <category>discuss</category>
      <category>architecture</category>
      <category>docker</category>
      <category>microservices</category>
    </item>
    <item>
      <title>The Best approach to use RxJS for clean code</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Tue, 08 Dec 2020 00:58:18 +0000</pubDate>
      <link>https://dev.to/bias/the-best-approach-to-use-rxjs-for-clean-code-9dl</link>
      <guid>https://dev.to/bias/the-best-approach-to-use-rxjs-for-clean-code-9dl</guid>
      <description>&lt;p&gt;When building angular apps, you will sooner or later get in contact with &lt;a href="https://rxjs.dev/"&gt;RxJS&lt;/a&gt; library. On angular's official &lt;a href="https://angular.io/guide/rx-library"&gt;documentation&lt;/a&gt;, the library get praised with many examples how to use rx. In angular templates, the result of a subscription can be used directly. Many of angular's core modules expose RxJS Observables through the API. For example the http module, that most angular developers use for loading additional data from the server.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is RxJs used for?
&lt;/h1&gt;

&lt;p&gt;With RxJS, you can write the same code, for an event stream as for a plain array. RxJS promote the use of functional programming. For that it provides very abstract primitives, that fit into almost any situation. &lt;/p&gt;

&lt;p&gt;A already mentioned request response request to an API but also processing data, implementing user interactions or working with data streams, all can follow the same programming paradigm.&lt;/p&gt;

&lt;p&gt;Due to the functional programming model, it should be easy to reason about the logic and to be easy to locate and repair bugs.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is an observable and how do they work?
&lt;/h1&gt;

&lt;p&gt;The main concept or class, to use the Library, is the &lt;code&gt;Observable&lt;/code&gt;. Every &lt;code&gt;event stream&lt;/code&gt;, data or process can be wrapped into an Observable.&lt;/p&gt;

&lt;p&gt;An Observable is providing the most general API to work in your programs. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.subscribe&lt;/code&gt; method works similar to the &lt;code&gt;.then&lt;/code&gt; function on a Javascript &lt;code&gt;Promise&lt;/code&gt;. With the difference, that the event can happen many times, not just once. When Processing data, Errors can happen, So the `.subscribe method also accepts an error handler as second argument. &lt;/p&gt;

&lt;h1&gt;
  
  
  What are operators?
&lt;/h1&gt;

&lt;p&gt;Operators are the second important concept when working with &lt;code&gt;RxJS Observables&lt;/code&gt;. Operators are there to process data. The Rx library provides many helper functions, to do &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;, &lt;code&gt;retry&lt;/code&gt;, &lt;code&gt;scan&lt;/code&gt; (a different kind of reduce function) and more. These are basically higher order functions. and get passed into the observables &lt;code&gt;.pipe&lt;/code&gt; method.&lt;/p&gt;

&lt;h1&gt;
  
  
  Is it worth learning RxJS?
&lt;/h1&gt;

&lt;p&gt;To answer the question short, and you might already know: no, it is not worth it. I think the best about the RxJS library, is  its documentation. It teaches about good programming concepts. However, then it seems in the docs, that the engineers of the RxJS library invent all the good concepts and they only work, when the developer uses Rx. &lt;/p&gt;

&lt;p&gt;In my opinion it is making things difficult, mapping simple programming paradigms into the most complex form: an 'async list operation'. I believe when requesting data from the server, it is guarantied, that there is one result, not many. Using observables does not allow in these situations to use JavaScripts &lt;code&gt;async/await&lt;/code&gt; syntax.&lt;/p&gt;

&lt;p&gt;In one of the first examples of the documentation, a &lt;code&gt;click&lt;/code&gt; event listener get registered to button. That event get throttled. In Pure js with some extra variables and a timeout. In rx with a single pipe through a &lt;code&gt;throttle&lt;/code&gt; helper function. However, when using the &lt;a href="http://underscorejs.org/#throttle"&gt;throttle&lt;/a&gt;  helper utility from &lt;code&gt;underscore&lt;/code&gt; js, I believe the pure js code is much simpler and also more easy to reason about.&lt;/p&gt;

&lt;p&gt;It is a strong contradiction, to promote functional programming, but the most basic thing in RxJS is a class. The problem with this class, is its live time. In every project I work on that is using the library, I see the same kind of bugs. Some events are happening multiple times. I see that there is subscribed often to the same &lt;code&gt;Observable&lt;/code&gt; and forgotten to &lt;code&gt;unsubscribe&lt;/code&gt;. Some dialogs open twice on a single click, some API update calls get executed multiple times. &lt;/p&gt;

&lt;p&gt;For a long time, I thought this is a problem with the angular framework, but found when working clean with angular components and services, making apps with angular feels much better, is easier to test and reason about.&lt;/p&gt;

&lt;p&gt;I ask you, try it out, make an angular app without using RxJS. One Method of the observable, that will help you to make the transition is &lt;code&gt;Observable.toPromise()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I don't want to make ads here, but I learned a good way to work on angular apps from a &lt;a href="https://www.pluralsight.com/paths/angular"&gt;pluralsight&lt;/a&gt; video course, shows very clear, how to use use services to share information between components.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>rxjs</category>
      <category>opinion</category>
      <category>bestpractice</category>
    </item>
    <item>
      <title>rapid prototyping with json file database</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Fri, 20 Nov 2020 00:59:24 +0000</pubDate>
      <link>https://dev.to/bias/rapid-prototyping-with-json-file-database-5821</link>
      <guid>https://dev.to/bias/rapid-prototyping-with-json-file-database-5821</guid>
      <description>&lt;p&gt;What do you think? How many good ideas never got started? Rapid Prototyping, is the art of getting up an initial version of an app. A version good enough for showing an idea, proving that an idea is feasible. &lt;/p&gt;

&lt;p&gt;That often is a frontend. How fast can you run &lt;code&gt;create react app&lt;/code&gt;, add a material UI, maybe with the help of &lt;code&gt;material&lt;/code&gt; or &lt;code&gt;ant design&lt;/code&gt; let users login, insert and present data.&lt;/p&gt;

&lt;p&gt;For me as a backend engineer it is often more about the nodejs app. How quick can I create an &lt;code&gt;express&lt;/code&gt; app with session middleware and some endpoints to insert and query data. Can it be faster setup using &lt;code&gt;lookback&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Personally I never used loopback, sails or such productive, they both have an &lt;code&gt;inMemory datastore&lt;/code&gt;. I mostly use less opinionated libraries. &lt;/p&gt;

&lt;p&gt;The part that stopped most of my projects from actually getting started is setting up the DB. Docker is not stable on my mac nor on my Windows PC. That is why I sometimes look into file datastores.&lt;/p&gt;

&lt;p&gt;For frontend developers there is the fantastic &lt;code&gt;json-server&lt;/code&gt;. It provides rest API to a json file very quickly in a single command. As a backend developer we can use SQLite, nedb (outdated/not maintained), low-db that is inside json-server.&lt;/p&gt;

&lt;p&gt;But the problem I found is, that the code written with these solutions is much different from actual production applications made with a sophisticated database. &lt;/p&gt;

&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;That is why I created the node module &lt;a href="https://npmjs.com/package/trdb"&gt;trdb&lt;/a&gt;. A json file database that feels like a real db with asynchronous API and the data inside the db are isolated objects, that will not unexpectedly mutate. &lt;/p&gt;

&lt;p&gt;While &lt;code&gt;json-server&lt;/code&gt; let you build the frontend before the API is ready, With &lt;code&gt;trdb&lt;/code&gt; you can implement the API before the db is ready.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// create a db&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;newFileDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./db.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// create a collection&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// insert a user (see without id!)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Tobias Nickel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;technical lead&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// update and save the user&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;favoriteHobby&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;programming&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertMany&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sebastian Sanchez&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Firat Evander&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Silpa Janz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// When inserting or saving, internally a new copy of the object is created&lt;/span&gt;
&lt;span class="c1"&gt;// next the reloaded user represents the same user in DB, but is a separate object.&lt;/span&gt;
&lt;span class="c1"&gt;// this is the same behavior you get from a real databases or API.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userReloaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;userReloaded&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="c1"&gt;// pass in the properties all the resulting items should have.&lt;/span&gt;
&lt;span class="c1"&gt;// also allow to pass arrays for then the objects value need to be included.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchedUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Firat Evander&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Tobias Nickel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchedUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// removing items just works just like search, if first search then removes.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Tobias Nickel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Feel free to create multiple dbs to put collections in separate files.&lt;/span&gt;
&lt;span class="c1"&gt;// This example also shows the options for custom idName and&lt;/span&gt;
&lt;span class="c1"&gt;// newId. This the newId defaults to uuid v4, and provides a method for&lt;/span&gt;
&lt;span class="c1"&gt;// generating autoIncrementIds. You can implement your own ID functions,&lt;/span&gt;
&lt;span class="c1"&gt;// returning and primitive like numbers and strings. &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postsDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;newFileDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;idName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;newId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAutoIncrementId&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The db also watches the file. during development and testing you can always see what is inside the db file. When you edit that file, it is instandly loaded into the server process.&lt;/p&gt;

&lt;h1&gt;
  
  
  Result
&lt;/h1&gt;

&lt;p&gt;I was about to study oauth2 and open connectId. To play with that, you need three services. The authentication/authorization service, an API service and the app service. Each want to have its own db. With &lt;a href="https://npmjs.com/package/trdb"&gt;trdb&lt;/a&gt; setting up these services was quick and I can concentrate on the logic, rather than setup.&lt;/p&gt;

&lt;p&gt;What do you think of my solution? How do you build quick prototypes.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>prototyping</category>
      <category>json</category>
      <category>database</category>
    </item>
    <item>
      <title>Peter Drucker's quotes for software developers</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Fri, 13 Nov 2020 01:41:39 +0000</pubDate>
      <link>https://dev.to/bias/peter-drucker-s-quotes-for-software-developers-20ko</link>
      <guid>https://dev.to/bias/peter-drucker-s-quotes-for-software-developers-20ko</guid>
      <description>&lt;p&gt;As expert for business, economy, management leadership and such, Peter Drucker also shared some interesting thought about the computer. And &lt;a href="http://tnickel.de/"&gt;I&lt;/a&gt; believe, these quotes can serve you as a developer well. &lt;/p&gt;

&lt;p&gt;With these quote, you might get the right words, that will help you next time, to make and win the argument about a new feature in your software giving great value to you and your organization.&lt;/p&gt;

&lt;p&gt;You can be sure, your manager has read some of his books, or at least have read and heard about Peter Drucker's work.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Quote
&lt;/h2&gt;

&lt;p&gt;Beginning somewhat provocative:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The computer being a mechanical 
moron, can handle only quantifiable 
data. These it can handle with 
speed, accuracy, and precision. 
It will, therefore, grind out 
hitherto unobtainable quantified
information in large volume.
One can, however, by large 
quantify only what goes on 
inside an organization.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you feel it? when the software does not do what it should? This quote is about quantifiable information. Stuff that can be counted and measured. But while we can also also count anything we find outside, we will never have the complete picture, because we can never count everything. And when investing the Effort, money and time to analyse the outside, at the time we get the result, it might just be irrelevant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Second Quote
&lt;/h2&gt;

&lt;p&gt;Going in a similar direction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Relevant outside events are rarely 
available in quantifiable form, 
until much to late to do anything 
about them. This is not because 
out information-gathering capability
in respect to outside events lags 
behind the technical abilities 
of the computer. 

The problem is rather that the 
important and relevant outside 
events are often qualitative and 
not capable of quantification.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow, &lt;code&gt;relevant information is qualitative&lt;/code&gt;. Informations that we need to develop a sence for, where we need a good intuition. We need experience to make good decisions based on qualitative information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Third Quote
&lt;/h2&gt;

&lt;p&gt;Very quick, check the next quote&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The danger is that executives will 
become contemptuous of information 
and stimulus that cannot be reduced 
to computer logic 
and computer language.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you know that when getting lost in more and more information. When buying a new PC or other gedget,  study lots of options, probably way to many, and actually getting distracted from what I actually wanted. While for personal, this can be very joyful, in business however there are usually bigger amounts of data and lots valuable resources at risk. We have to figure out what is the relevant information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fourth Quote
&lt;/h2&gt;

&lt;p&gt;Is about your team.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;One should only have on a team the 
knowledge and skills, that are
needed day in and day out for 
the bulk of the work.

Specialists that may be needed 
once in a while, or that have to be 
consulted on this or on that, should
always remain outside.

It is indefinitely cheaper to go
to them and consult them against
a fee than to have them 
in the group.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is so huge, I see so many decisions made by inexperienced people, including me. We all always strive for the best solution. Sometimes we wish, there is someone with even more experience. This quote tells you, not to do everything on your own. Ask for help, and while it can cost, it will certainly pay off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fived Quote
&lt;/h2&gt;

&lt;p&gt;Next is about attitude to your colleagues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The man of knowledge has always
been expected to take
responsibility for being 
understood.

It is barbarian arrogance to assume
that the layman can or should make
the effort to understand him,
and that it is enough 
if the man of knowledge talks to 
a handful of fellow experts
who are his peers.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I said this counts for your direct communication with others as well as making sure your code can be understood by the next engineer. And that one is not necessarily on your team jet, he does not everything about your app jet and probably not even about your problem space and work domain. As, it is not necessary that your grandmother understand your code, a less experienced engineer should.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sixed Quote
&lt;/h2&gt;

&lt;p&gt;This is the quote, that made me start writing this article:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The greatest impact of the computer
lies in its limitations,
which will force us increasingly 
to make decisions, 
and above all,
forces middle managers to change 
from operators 
into executives and decision makers.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is so powerful. When managing people, it is enough to say "get it done"(probably more friendly and constructive) and later check how it goes. When developing an application however we have to define every little behavior for any possible circumstances. And that means, we have to make the decision upfront, hopefully before the user encounter that case.&lt;/p&gt;

&lt;p&gt;I often have this quote in the back of my head, when asking my boss for the next nitpicking detail, that will be encountered by only 0.1% of users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comments
&lt;/h2&gt;

&lt;p&gt;What are your thoughts? are these thoughts outdated? which one quote is new to you? &lt;/p&gt;

&lt;p&gt;These quotes are from the book 'The Effective Executive`.&lt;/p&gt;

&lt;p&gt;The title picture for this article is from &lt;a href="https://cowomen.com/?utm_medium=referral&amp;amp;utm_source=unsplash"&gt;coWoman&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>development</category>
      <category>leadership</category>
      <category>project</category>
      <category>management</category>
    </item>
    <item>
      <title>What to do with abandoned projects? BrowserSync</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Fri, 06 Nov 2020 06:56:40 +0000</pubDate>
      <link>https://dev.to/bias/what-to-do-with-abandoned-projects-browsersync-ido</link>
      <guid>https://dev.to/bias/what-to-do-with-abandoned-projects-browsersync-ido</guid>
      <description>&lt;p&gt;Browser sync let you view your app in multiple sizes and even multiple devices at once. Navigsting in one of the windows, All other windows will perform the same action.&lt;/p&gt;

&lt;p&gt;BrowserSync is an openSource project of the company &lt;a href="https://wearejh.com/"&gt;jh&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;When I tried eleventy for the first time, it serve the ssg site via browser-sync. I found an issue about a broken link, that leads to a potentially dangerouse fraudulent website.&lt;/p&gt;

&lt;p&gt;I created an issue, as asked on browsersyncs website.&lt;/p&gt;

&lt;p&gt;Now some time went by, and it seems more and more issues pile up. not answered.&lt;/p&gt;

&lt;p&gt;What do you think can we do? The tool is very cool, but it should also be safe and secure to use.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
    </item>
    <item>
      <title>web accessibility with the axe-core module</title>
      <dc:creator>Tobias Nickel</dc:creator>
      <pubDate>Mon, 02 Nov 2020 00:51:42 +0000</pubDate>
      <link>https://dev.to/bias/web-accessibility-with-the-axe-core-module-5han</link>
      <guid>https://dev.to/bias/web-accessibility-with-the-axe-core-module-5han</guid>
      <description>&lt;p&gt;Accessibility accessibility, as here at dev, we also want want that the apps we develop, can be used by everyone. &lt;/p&gt;

&lt;p&gt;Wether people with a hook as their had, a wooden lag, shoot laser out of the eyes, or have not caught Jerry yet. They all want to access your awesome new app, that you build with all the great skills you learn at dev.to. &lt;/p&gt;

&lt;p&gt;Today I want to introduce a module, that I recently came across, to help you, that all people can use your site and feel included. If they stand upside down or read minds.&lt;/p&gt;

&lt;p&gt;The tool I am very excited now, is axe-core. It is absolutely straight forward to use and provides direct feedback, on what you can do, to show that everyone is welcome on your platform.&lt;/p&gt;

&lt;p&gt;My blog, is looking pretty good, strong contrasts in the colors and big fonts. Articles are wrapped in the  tag. But I had to learn different. There are several issues. And I will work, to make my page easier accessible by everyone. Even if he let the minions read my page to him.&lt;/p&gt;

&lt;p&gt;When analyzing your site with axe-core,  you will get a valuable list of issues, that can hold back the one or the other visitor to enjoy your content.&lt;/p&gt;

&lt;p&gt;Axe-core not only helping you to find all the little inconveniences that can hold nice people away, itself has a very clean API and command line tool, that themselves are very accessible for every programmer.&lt;br&gt;
You can run it inside your site on client site and get the results on the browser's JavaScript console. The module works well with various frameworks and provides for example integrations for react.&lt;/p&gt;

&lt;p&gt;These integrations into our javascript tooling, allow us to have in the complete product development cycle an eye on accessibility and avoid to improve the accessibility as an afterthought.&lt;/p&gt;

&lt;p&gt;My blog is a static site, so I simple tested it using the cli tool. First install it with &lt;code&gt;npm install -g axe-cli&lt;/code&gt; and then test your site like this: &lt;code&gt;axe http://tnickel.de/&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The tool is not only good for us engineers, it is also good for management. Because, as we know, management loves numbers. With &lt;code&gt;axe&lt;/code&gt; we get a single number for accessibility issues, and we can work to bring the number down and with that, the accessibility up.&lt;/p&gt;

&lt;p&gt;I would say, now there is no excuse, not to improve the accessibility to your precious content. &lt;/p&gt;
&lt;h1&gt;
  
  
  API
&lt;/h1&gt;

&lt;p&gt;What? you still need to see an example how to use it with your project? What about using it by adding some scripts-tags to your html?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"node_modules/axe-core/axe.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;lastViolations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;axe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;violations&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;violationData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;violationData&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;lastViolation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;lastViolation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;violationData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some issue with axe:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And yes, this code don't need to be efficient. It only runs on your site during development, not on the users device. and you can probably integrate axe better into your framework, after your redux store dispatch an update after your component updated. &lt;/p&gt;

&lt;p&gt;just add it somewhere where it constantly run during your development. Then you will always see tips, how to improve your site. and knows, even presidents who can not read could understand your articles.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>web</category>
      <category>a11y</category>
    </item>
  </channel>
</rss>
