<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.3">Jekyll</generator><link href="https://brototyp.de/feed.xml" rel="self" type="application/atom+xml" /><link href="https://brototyp.de/" rel="alternate" type="text/html" /><updated>2020-05-10T17:20:37+02:00</updated><id>https://brototyp.de/</id><title type="html">Cornelius Horstmann | iOS Developer &amp;amp; Blogger</title><subtitle>Hi, my name is Cornelius Horstmann, iOS Developer and Tech Lead from Berlin. I am writing about iOS Development and technical projectmanagement.</subtitle><entry><title type="html">A Checklist to create the best Pull Request</title><link href="https://brototyp.de/blog/pull-request-checklist/" rel="alternate" type="text/html" title="A Checklist to create the best Pull Request" /><published>2018-07-18T08:00:00+02:00</published><updated>2018-07-18T09:33:13+02:00</updated><id>https://brototyp.de/blog/pull-request-checklist</id><content type="html" xml:base="https://brototyp.de/blog/pull-request-checklist/">&lt;p&gt;Pull requests, sometimes called merge requests, are an essential part of a teams workflow. It helps to catch bugs early and is a great way to learn and grow. There are a few things to consider in order to have an effective pull request.&lt;/p&gt;

&lt;h2 id=&quot;purpose&quot;&gt;Purpose&lt;/h2&gt;

&lt;p&gt;A pull request should have a single purpose. Don’t stuff random changes into your pull request and don’t solve two issues at the same time. If there are multiple issues, it’s harder to understand which issue a certain line is contributing to and to grasp the overall logic. Also, make sure to constrain the pull request to a maximum complexity and length. 500 changed LOC is a good upper bound.&lt;/p&gt;

&lt;h2 id=&quot;explanation&quot;&gt;Explanation&lt;/h2&gt;

&lt;p&gt;A pull request should have a meaningful title (naming the purpose) and a proper description. It should describe &lt;strong&gt;what&lt;/strong&gt; you are doing and why you are doing it in this way. If your pull request is based on a proper ticket/issue (which it should) it is fine to just link the ticket to describe the &lt;strong&gt;what&lt;/strong&gt;. Keep the reviewer in mind and help her to get started. The better you help her understand the context and your thoughts, the easier the review will be and the faster the pull request is merged.&lt;/p&gt;

&lt;h2 id=&quot;self-review&quot;&gt;Self Review&lt;/h2&gt;

&lt;p&gt;Review your own pull request before assigning the pull request to someone. You want to value the time of your reviewer and want to prevent unnecessary review cycles. So just after you created the pull request have a short read over your code. Are there any things that shouldn’t be there? Remove them. Did you find any bugs right away? Fix them. Try to get into the mindset of a reviewer. Are there any pieces that might take a second to understand? Just add a comment in the pull request yourself and try to help your reviewer out.&lt;/p&gt;

&lt;h2 id=&quot;assignment&quot;&gt;Assignment&lt;/h2&gt;

&lt;p&gt;Don’t let a pull request hang around just like this. Your task isn’t finished just by creating the pull request. It’s your code. You want it to be merged. Find yourself a reviewer. Get in contact and make sure there is one who wants to review it. Make sure your pull request is assigned to someone.&lt;/p&gt;

&lt;h2 id=&quot;communication&quot;&gt;Communication&lt;/h2&gt;

&lt;p&gt;Most importantly: communicate! If you feel your reviewer is stuck get in touch. If you have any time constraints and need the pull request to get merged try to support and talk about it. Don’t be afraid to ask questions and try to be constructive (which obviously counts for both).&lt;/p&gt;</content><author><name>Cornelius Horstmann</name></author><summary type="html">Pull requests, sometimes called merge requests, are an essential part of a teams workflow. It helps to catch bugs early and is a great way to learn and grow. There are a few things to consider in order to have an effective pull request.</summary></entry><entry><title type="html">Jekyll Speed Improvements</title><link href="https://brototyp.de/blog/jekyll-speed-improvements/" rel="alternate" type="text/html" title="Jekyll Speed Improvements" /><published>2018-04-03T16:00:00+02:00</published><updated>2018-04-30T13:50:33+02:00</updated><id>https://brototyp.de/blog/jekyll-speed-improvements</id><content type="html" xml:base="https://brototyp.de/blog/jekyll-speed-improvements/">&lt;p&gt;This blog is based on &lt;a href=&quot;https://jekyllrb.com&quot;&gt;jekyll&lt;/a&gt; a static site generator that takes my markdown files and generates static html, css, JavaScript and all the other magic that makes this beautiful blog. I love this setup mainly for two reasons. Firstly, I write in markdown so my content is independent from the platform. Secondly, I like static sites. It is so much harder to create an inflated and slow page where the visitor has to wait for seconds until the page is loaded after each click. If you put in the extra effort it is possible to have sites served at lightning speed.&lt;/p&gt;

&lt;h2 id=&quot;browser-caching&quot;&gt;Browser caching&lt;/h2&gt;

&lt;p&gt;One of the most important things is to save the browser some work and let it reuse some resources. How often do you change your css or your JavaScript? Propably quite rarely. So let the browser reuse it’s files and let it know when to reload. One way is to set the cache header to “indefinitely” and add a cachebuster whenever you change the file.&lt;/p&gt;

&lt;p&gt;I added this lines to the apache configuration …&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;FilesMatch&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; &quot;\.(jpeg|jpg|png|js|css)$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;set&lt;/span&gt; Cache-Control &quot;max-age=31536000, public, s-maxage=31536000&quot;
    &lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;set&lt;/span&gt; Pragma &quot;cache&quot;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;FilesMatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… and added a small Cachebuster tag to jekyll.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'digest/sha1'&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Jekyll&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CacheBuster&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Liquid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Tag&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;rendering_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;site&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;time&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Digest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SHA1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hexdigest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rendering_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Liquid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cachebuster'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CacheBuster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way I can easily create a seemingly random string based on the current time. It basically just takes the &lt;a href=&quot;https://jekyllrb.com/docs/variables/#site-variables&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;site.time&lt;/code&gt;&lt;/a&gt; (for example &lt;em&gt;2020-05-10 17:20:37 +0200&lt;/em&gt;) and calculates the sha1 from it (for example &lt;em&gt;e7ac651a89cedb959848aebc45f56604d91a22e7&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;We can then append this cachebuster to the css url for example.&lt;/p&gt;

&lt;div class=&quot;language-liquid highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/assets/main.css&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;relative_url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;?version=&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;cachebuster&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But it is possible to get even better than this. Don’t load external js and css files at all.&lt;/p&gt;

&lt;h2 id=&quot;inline-css-and-javascript&quot;&gt;Inline CSS and JavaScript&lt;/h2&gt;

&lt;p&gt;Wait, I thought inlining CSS and JavaScript is a bad thing&lt;sup id=&quot;fnref:dzone&quot;&gt;&lt;a href=&quot;#fn:dzone&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;?! Generally speaking that is true. In my case the CSS and JavaScript is so small that the overhead of a seperate request is not woth it. Currently my &lt;a href=&quot;/assets/main.css&quot;&gt;CSS file&lt;/a&gt; is about 200 bytes and the overhead of a HTTP request is about 500 bytes to 1KB&lt;sup id=&quot;fnref:mathiasbynens&quot;&gt;&lt;a href=&quot;#fn:mathiasbynens&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and my js is barely even there. Inlining is not always the best solution but it might be.&lt;/p&gt;

&lt;p&gt;I decided to inline my .css and .js file. In order be able to write in scss and have my scss in seperate files I let jekyll do the heavy lifting.&lt;/p&gt;

&lt;p&gt;I created a new &lt;code class=&quot;highlighter-rouge&quot;&gt;_includes/inline.scss&lt;/code&gt; …&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;../_sass/main_sass_file&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… and replaced my old link to the stylesheet …&lt;/p&gt;

&lt;div class=&quot;language-liquid highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/assets/main.css&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;relative_url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;?version=&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;cachebuster&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… with this code to inline the css.&lt;/p&gt;
&lt;div class=&quot;language-liquid highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;style type=&quot;text/css&quot;&amp;gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;capture&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;include_to_scssify&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;scss&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;endcapture&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;include_to_scssify&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;scssify&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;minify-your-css-and-javascript&quot;&gt;Minify your CSS and JavaScript&lt;/h2&gt;

&lt;p&gt;Speaking of scss. If you use scss or sass compressing your css is as easy as configuring it in the &lt;code class=&quot;highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;compressed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Minifying HTML is not as easy. I use &lt;a href=&quot;http://jch.penibelst.de/&quot;&gt;this&lt;/a&gt; script by &lt;a href=&quot;http://anatol.penibelst.de/&quot;&gt;Anatol Broder&lt;/a&gt; with the folowing configuration. But be aware. For my blog it increased generation time from about 1.8 seconds to about 3.2 seconds.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;compress_html&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;blanklines&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;!--&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reducing-image-filesize&quot;&gt;Reducing image filesize&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/valerijaspasojevic/jekyll-compress-images&quot;&gt;jekyll-compress-images&lt;/a&gt; is a great tool to losslessly reduce your image filesizes. I am using it with the following configuration.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;imageoptim&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;skip_missing_workers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;nice&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;5&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;threads&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;4&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;svgo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additionaly, make sure you don’t use oversize images.&lt;/p&gt;

&lt;h2 id=&quot;the-outcome&quot;&gt;The Outcome&lt;/h2&gt;

&lt;p&gt;Using all these methods (and some more) I was able to get a close to perfect &lt;a href=&quot;https://developers.google.com/web/tools/lighthouse/&quot;&gt;lighthouse&lt;/a&gt; and &lt;a href=&quot;https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fbrototyp.de%2Fblog%2Fone-day-project-bookmarks%2F&amp;amp;tab=mobile&quot;&gt;PageSpeed Insights&lt;/a&gt; rating. Though you should use your common sense when checking these tools for issues on your site, they provide some great indicators. And it is always configming to see the green circles.
&lt;span class=&quot;center&quot;&gt;
&lt;img src=&quot;/assets/2018-04-03/insights.png&quot; alt=&quot;PageSpeed Insights result&quot; /&gt;
&lt;img src=&quot;/assets/2018-04-03/lighthouse.png&quot; alt=&quot;Lighthouse Results&quot; /&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:dzone&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://dzone.com/articles/why-inline-css-and-javascript-&quot;&gt;Why Inline CSS And JavaScript Code Is Such A Bad Thing&lt;/a&gt; &lt;a href=&quot;#fnref:dzone&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:mathiasbynens&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://mathiasbynens.be/notes/inline-vs-separate-file&quot;&gt;Inline &amp;#x3C;script&amp;#x3E; and &amp;#x3C;style&amp;#x3E; vs. external .js and .css — what’s the size threshold?&lt;/a&gt; &lt;a href=&quot;#fnref:mathiasbynens&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name>Cornelius Horstmann</name></author><summary type="html">This blog is based on jekyll a static site generator that takes my markdown files and generates static html, css, JavaScript and all the other magic that makes this beautiful blog. I love this setup mainly for two reasons. Firstly, I write in markdown so my content is independent from the platform. Secondly, I like static sites. It is so much harder to create an inflated and slow page where the visitor has to wait for seconds until the page is loaded after each click. If you put in the extra effort it is possible to have sites served at lightning speed.</summary></entry><entry><title type="html">One day project: Bookmarks</title><link href="https://brototyp.de/blog/one-day-project-bookmarks/" rel="alternate" type="text/html" title="One day project: Bookmarks" /><published>2018-01-02T17:11:00+01:00</published><updated>2018-04-03T15:48:19+02:00</updated><id>https://brototyp.de/blog/one-day-project-bookmarks</id><content type="html" xml:base="https://brototyp.de/blog/one-day-project-bookmarks/">&lt;p&gt;&lt;a href=&quot;https://github.com/brototyp/Bookmarks&quot;&gt;Bookmarks&lt;/a&gt; is a very simple iOS application to save bookmarks. The basic idea is to archive the websites and make them searchable. It should be able to answer questions such as “what was the website, where I read something about XYZ”.&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;float:left; width: 20%; margin: 0 1em 1em 0&quot;&gt;&lt;img src=&quot;/assets/2018-01-02/icon-138x138.jpg&quot; alt=&quot;Bookmarks app icon&quot; /&gt;&lt;/span&gt;
&lt;em&gt;Bookmarks&lt;/em&gt; is a one-day-project and thus in a very crude state. The &lt;a href=&quot;https://github.com/brototyp/Bookmarks#todos&quot;&gt;list of todos&lt;/a&gt; is very long and the search isn’t even available yet. During development I noticed it would have benefitted from using &lt;a href=&quot;https://github.com/ReactiveX/RxSwift&quot;&gt;RxSwift&lt;/a&gt;.&lt;/p&gt;</content><author><name>Cornelius Horstmann</name></author><summary type="html">Bookmarks is a very simple iOS application to save bookmarks. The basic idea is to archive the websites and make them searchable. It should be able to answer questions such as “what was the website, where I read something about XYZ”.</summary></entry><entry><title type="html">Five years</title><link href="https://brototyp.de/blog/five-years/" rel="alternate" type="text/html" title="Five years" /><published>2017-12-19T14:53:00+01:00</published><updated>2018-08-27T16:17:22+02:00</updated><id>https://brototyp.de/blog/five-years</id><content type="html" xml:base="https://brototyp.de/blog/five-years/">&lt;p&gt;August 2013, I was still a student, &lt;a href=&quot;http://tbointeractive.com&quot;&gt;TBO INTERACTIVE&lt;/a&gt; was located in the Auguststraße and the team was only six bright minds. Today it’s the Torstraße and 16 minds. Friday was my last day at work and I want to say thanks for five terrific years.&lt;/p&gt;

&lt;p&gt;I want to thank all of TBO’s clients, with whom I was able to work on all of these projects. There is &lt;em&gt;Daily Ratings&lt;/em&gt; and &lt;em&gt;Research Lab&lt;/em&gt; for Prosieben Sat.1, the AOK &lt;em&gt;vigo&lt;/em&gt; and &lt;em&gt;Bleibgesund magazine&lt;/em&gt;, the &lt;a href=&quot;http://aboutvalues.net&quot;&gt;ValuES&lt;/a&gt; website for the &lt;a href=&quot;https://www.giz.de&quot;&gt;GIZ&lt;/a&gt;, the &lt;em&gt;Alcomedia&lt;/em&gt; iPad app for the &lt;a href=&quot;http://lssh.de&quot;&gt;Landesstelle für Suchtfragen Schleswig-Holstein e.V.&lt;/a&gt;, the &lt;a href=&quot;https://land-der-ideen.de/projekt/artomat-app-fuer-gegenwartskunst-459&quot;&gt;awarded&lt;/a&gt; &lt;em&gt;Artomat&lt;/em&gt; app for the &lt;a href=&quot;https://www.skd.museum&quot;&gt;SKD&lt;/a&gt;, the &lt;a href=&quot;http://www.wetter.com&quot;&gt;wetter.com&lt;/a&gt; &lt;a href=&quot;https://itunes.apple.com/de/app/wetter-com/id1020581825?mt=8&quot;&gt;iOS Universal app&lt;/a&gt;, the &lt;a href=&quot;https://itunes.apple.com/de/app/handelsblatt10-ein-tag-zehn-themen/id1082671761?l=en&amp;amp;mt=8&quot;&gt;Handelsblatt 10 iPhone app&lt;/a&gt; and lastly the &lt;a href=&quot;https://itunes.apple.com/de/app/antenne-bayern/id293170410?mt=8&quot;&gt;Antenne Bayern&lt;/a&gt; app. Every project was a challenge and I learned quite a bit.&lt;/p&gt;

&lt;p&gt;I want to give thanks to Daniel, Ruslan, and Steve, with whom I got to work with for five years, and who got me on board four years ago and since then have met me with such trust. Four people, completely different, united by common values and driven by a shared goal.&lt;/p&gt;

&lt;p&gt;Most of all I want to give thanks to the sublime team. I enjoyed the professional challenges. Not only the skilled discussions and the energy but the drollery during lunch and our common achievements. It makes me proud to think, that I built this team.&lt;/p&gt;</content><author><name>Cornelius Horstmann</name></author><summary type="html">August 2013, I was still a student, TBO INTERACTIVE was located in the Auguststraße and the team was only six bright minds. Today it’s the Torstraße and 16 minds. Friday was my last day at work and I want to say thanks for five terrific years.</summary></entry><entry><title type="html">Continuous Integration with Jenkins</title><link href="https://brototyp.de/blog/continuous-integration-with-jenkins/" rel="alternate" type="text/html" title="Continuous Integration with Jenkins" /><published>2017-10-20T17:40:00+02:00</published><updated>2018-02-10T10:10:15+01:00</updated><id>https://brototyp.de/blog/continuous-integration-with-jenkins</id><content type="html" xml:base="https://brototyp.de/blog/continuous-integration-with-jenkins/">&lt;p&gt;In september 2016 a &lt;a href=&quot;https://jenkins.io/blog/2016/09/19/blueocean-beta-declarative-pipeline-pipeline-editor/&quot;&gt;blogpost on jenkins.io&lt;/a&gt; announced &lt;a href=&quot;https://jenkins.io/projects/blueocean/&quot;&gt;Blue Ocean&lt;/a&gt; and with it declarative pipelines and with that the build and deployment process can be managed from within the repository. In the meantim the plugins are well hung and additional plugins have been developed.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://travis-ci.org&quot;&gt;Travis&lt;/a&gt; uses &lt;code class=&quot;highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt;, &lt;a href=&quot;https://gitlab.com&quot;&gt;GitLab&lt;/a&gt; uses &lt;code class=&quot;highlighter-rouge&quot;&gt;.gitlab-ci.yml&lt;/code&gt;, &lt;a href=&quot;https://www.bitrise.io&quot;&gt;BITRISE&lt;/a&gt; uses &lt;code class=&quot;highlighter-rouge&quot;&gt;bitrise.yml&lt;/code&gt; and &lt;a href=&quot;https://github.com/drone/drone&quot;&gt;Drone&lt;/a&gt; uses &lt;code class=&quot;highlighter-rouge&quot;&gt;.drone.yml&lt;/code&gt;. Finally jenkins followed using the &lt;code class=&quot;highlighter-rouge&quot;&gt;Jenkinsfile&lt;/code&gt;. Not only is it possible to manage the process in the CVS, it also allows fast and easy copying among projects.&lt;/p&gt;

&lt;h2 id=&quot;team-projects&quot;&gt;Team Projects&lt;/h2&gt;

&lt;p&gt;Once Jenkins is setup the first question is what kind of project one should choose. For iOS development the &lt;em&gt;freestyle&lt;/em&gt; project was the way to go. With the update two new plugins came along. The &lt;a href=&quot;https://wiki.jenkins.io/display/JENKINS/Bitbucket+Branch+Source+Plugin&quot;&gt;Bitbucket Branch Source Plugin&lt;/a&gt; and the &lt;a href=&quot;https://wiki.jenkins-ci.org/display/JENKINS/GitHub+Branch+Source+Plugin&quot;&gt;GitHub Branch Source Plugin&lt;/a&gt; which allow adding team folders.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2017-10-20/bitbucket-team-project.jpg&quot; alt=&quot;Bitbucket Team/Project&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once configured, the jenkins server regularly scans all the teams repositories for branches with a Jenkinsfile and configures projects for the repositories and jobs for the branches. New projects don’t have to be configured within Jenkins. It’s sufficient to add a Jenkinsfile in the base folder of the project. Jenkins also configures a job for every pull request and runs every commit both in the context of the pull request and in the context of the branch. To avoid that you can use the options &lt;code class=&quot;highlighter-rouge&quot;&gt;Discover branches&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;Automatic branch project triggering&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2017-10-20/discover-branches.jpg&quot; alt=&quot;Discover branches&quot; /&gt;
&lt;img src=&quot;/assets/2017-10-20/branch-triggering.jpg&quot; alt=&quot;Automatic branch project triggering&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;blue-ocean&quot;&gt;Blue Ocean&lt;/h2&gt;

&lt;p&gt;Blue Ocean is the new Jenkins interface, that runs in addition to the classic Jenkins interface. Day to day tasks can be done in the new interface but specific configuring tasks are only possible in the old one.&lt;/p&gt;

&lt;p&gt;All jobs for a specific branch are shown together with their status.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2017-10-20/jobs.jpg&quot; alt=&quot;List of all Jobs in Blue Ocean&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;jenkinsfile&quot;&gt;Jenkinsfile&lt;/h2&gt;

&lt;p&gt;The Build Pipeline is configured in a &lt;code class=&quot;highlighter-rouge&quot;&gt;Jenkinsfile&lt;/code&gt; in the root folder of the project. To quickly find a build error, it is helpfull to define different stages, which cover different scopes. For example &lt;code class=&quot;highlighter-rouge&quot;&gt;checkout&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;prepare&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;tests&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;codestyle&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;deployment&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;archive&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All tasks (aside of configurations) have to be executed on a node. A node can be the Jenkins server itself but to be able to scale it is helpfull to add additional nodes. Every node can be assigned different tags that describe satisfied requirements. You can either chose &lt;code class=&quot;highlighter-rouge&quot;&gt;macos&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;linux&lt;/code&gt; or be more specific using &lt;code class=&quot;highlighter-rouge&quot;&gt;xcode9&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;nodejs&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;ruby2.1.6&lt;/code&gt; and so on.&lt;/p&gt;

&lt;p&gt;An example Jenkinsfile could look like this:&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groovy&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Defines the number of builds and artifacts to store.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buildDiscarder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logRotator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;artifactDaysToKeepStr:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'30'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;artifactNumToKeepStr:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'50'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;daysToKeepStr:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'30'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;numToKeepStr:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'50'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))])&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// These stages require a node with the taks xcode8 and fastlane&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'xcode8 &amp;amp;&amp;amp; fastlane'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Activates the Ansi Color Plugin for the enclosed stages&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'AnsiColorBuildWrapper'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'colorMapName'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'XTerm'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'defaultFg'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'defaultBg'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Checkout'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;checkout&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Bundle install'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'bundle update'&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'bundle install'&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Tests'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;killall Simulator || true&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SNAPSHOT_FORCE_DELETE=yes snapshot reset_simulators&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'fastlane test sdk:&quot;9.3&quot; device:&quot;iPhone 5s&quot;'&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'fastlane test sdk:&quot;10.2&quot; device:&quot;iPhone 5s&quot;'&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;publishHTML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;allowMissing:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;alwaysLinkToLastBuild:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;keepAll:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;reportDir:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'build/reports/'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;reportFiles:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'report.html'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;reportName:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'HTML Test Report'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;junit&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;allowEmptyResults:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;testResults:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'build/reports/report.junit'&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;archiveArtifacts&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;allowEmptyArchive:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;artifacts:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'build/reports/*'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;onlyIfSuccessful:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href=&quot;http://wiki.jenkins-ci.org/display/JENKINS/AnsiColor+Plugin&quot;&gt;Ansi Color Plugin&lt;/a&gt; provides support for ANSI Escape Characters and optimizes the representation of console output.&lt;/p&gt;

&lt;p&gt;Every build can be inspected and lists all stages. It will show test results, archived artifacts and provides ways to restart a build if necessary.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2017-10-20/job.png&quot; alt=&quot;View of a single build in Blue Ocean&quot; /&gt;&lt;/p&gt;</content><author><name>Cornelius Horstmann</name></author><summary type="html">In september 2016 a blogpost on jenkins.io announced Blue Ocean and with it declarative pipelines and with that the build and deployment process can be managed from within the repository. In the meantim the plugins are well hung and additional plugins have been developed.</summary></entry><entry><title type="html">Swift Struct vs. Class Performance</title><link href="https://brototyp.de/blog/swift-struct-vs-class-performance/" rel="alternate" type="text/html" title="Swift Struct vs. Class Performance" /><published>2016-07-14T19:29:07+02:00</published><updated>2018-02-10T10:10:15+01:00</updated><id>https://brototyp.de/blog/swift-struct-vs-class-performance</id><content type="html" xml:base="https://brototyp.de/blog/swift-struct-vs-class-performance/">&lt;p&gt;In the game that &lt;a href=&quot;http://twitter.com/seilinho&quot;&gt;Michael&lt;/a&gt; and I are developing for our project &lt;a href=&quot;http://derbe.cool&quot;&gt;derbe.cool&lt;/a&gt; we frequently use immutable structs that are copied and mutated multiple times for every user activity. That’s when I started to wonder what the performance difference is between copying a struct vs. a class.&lt;/p&gt;

&lt;p&gt;A comparison of simple structs and classes using only value types or only referency types shows a huge difference.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/assets/2016-07-14/StructsVsClasses.playground.zip&quot;&gt;Playground zum Download&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Foundation&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;iterations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// simple&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleStruct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt16&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleStruct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleClass&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt16&lt;/span&gt;
    
    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anotherValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anotherValue&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleClass&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;structStartDate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;aStruct&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;aStruct&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aStruct&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;structDuration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timeIntervalSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;structStartDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;simple struct &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;structDuration&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;classesStartDate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;aClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;SimpleClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;anotherValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;aClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;classDuration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timeIntervalSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;structStartDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;simple class &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classDuration&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;





&lt;span class=&quot;c1&quot;&gt;// moreComplex&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ComplexStruct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setFirstValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ComplexStruct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;newValues&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;newValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ComplexStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ComplexClass&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    
    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setFirstValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ComplexClass&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;newValues&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;newValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ComplexClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;complexStructStartDate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;complexStruct&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ComplexStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;complexStruct&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complexStruct&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setFirstValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;complexStructDuration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timeIntervalSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;complexStructStartDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;complex struct &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;structDuration&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;complexClassesStartDate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;complexClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ComplexClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterations&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;complexClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complexClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setFirstValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;complexClassDuration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timeIntervalSince&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;complexClassesStartDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;complex class &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classDuration&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

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

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;simple struct 0.0083010196685791
simple class 0.0205469131469727
complex struct 0.0083010196685791
complex class 0.0205469131469727
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Cornelius Horstmann</name></author><summary type="html">In the game that Michael and I are developing for our project derbe.cool we frequently use immutable structs that are copied and mutated multiple times for every user activity. That’s when I started to wonder what the performance difference is between copying a struct vs. a class.</summary></entry><entry xml:lang="de"><title type="html">TBODeveloperOverlay - Dinge, die jeder braucht</title><link href="https://brototyp.de/blog/TBODeveloperOverlay/" rel="alternate" type="text/html" title="TBODeveloperOverlay - Dinge, die jeder braucht" /><published>2016-06-19T20:02:37+02:00</published><updated>2018-01-31T10:44:17+01:00</updated><id>https://brototyp.de/blog/TBODeveloperOverlay</id><content type="html" xml:base="https://brototyp.de/blog/TBODeveloperOverlay/">&lt;p&gt;Mit wachsender Komplexität eines jeden Softwareprojektes wächst auch die Komplexität beim Debuggen von Fehlern und Verstehen von Supportanfragen. Dabei gibt es einige Aspekte, die es einfacher machen die Situation zu verstehen. Ein gut gepflegtes Log kann sehr hilfreich sein. Genauso ist es wichtig zu verstehen auf welcher Version und mit welchen Parametern das Problem auftritt.&lt;/p&gt;

&lt;p&gt;Mit dem &lt;a href=&quot;https://cocoapods.org/pods/TBODeveloperOverlay&quot;&gt;TBODeveloperOverlay&lt;/a&gt; hat das Entwicklerteam von &lt;a href=&quot;http://tbointeractive.com&quot;&gt;TBO Interactive&lt;/a&gt; heute eine Suite von Tools veröffentlicht, die zum Debuggen vielen dieser Situationen einer &lt;strong&gt;iOS Applikation&lt;/strong&gt; hilft und durch eine Pluginarchitektur flexibel erweiterbar ist.&lt;/p&gt;

&lt;h2 id=&quot;catch-em-all&quot;&gt;Catch em all&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2016-06-19/tbodeveloperoverlay-pluginlist.jpg&quot; alt=&quot;TBODeveloperOverlay Plugin List&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Im Kern steht beim &lt;code class=&quot;highlighter-rouge&quot;&gt;DeveloperOverlay&lt;/code&gt; dabei eine einfache Liste aller konfigurierten Plugins. Diese kann beliebig eingebunden werden. Sei es ein einfacher versteckter Knopf, oder eine undokumentierte Geste. Die Anforderungen an ein Plugin sind dabei marginal. So lange es ein &lt;code class=&quot;highlighter-rouge&quot;&gt;UIViewController&lt;/code&gt; ist, lässt es sich einbinden. Zum aktuellen Zeitpunkt sind vier verschiedene Plugins veröffentlicht.&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;NSArray&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plugins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;@[];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Die Menge aller konfigurierten Plugins&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayPluginListViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;containedViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayPluginListViewController&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithPlugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    
&lt;span class=&quot;n&quot;&gt;TBOModalNavigationController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;developerOverlay&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBOModalNavigationController&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithRootViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;containedViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;presentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;developerOverlay&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;YES&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;keyvaluedebugger---its-all-about-the-state&quot;&gt;KeyValueDebugger - It’s all about the state&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2016-06-19/tbodeveloperoverlay-kvdebugger.jpg&quot; alt=&quot;TBODeveloperOverlay Key Value Debugger&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es gibt viele Parameter, die auf die Funktion einer Applikation Einfluss haben. Die Version der Applikation, das Backend mit dem kommuniziert wird, das Gerät um das es sich handelt oder bestimmte Variablen die Funktionen (de-)aktivieren oder verändern. Außerdem gibt es interne Variablen, die viel über den Zustand aussagen. Ist der Nutzer angemeldet? Wann wurde das letzte mal synchronisiert? Gibt es einen aktiven in-app-purchase? All das sind Fragen, die oft sehr einfach zu beantworten wären, hätte man Einblick auf ein paar dieser Variablen. Mit dem KeyValueDebugger gibt es ein Plugin, dass beliebige Variablen strukturieren und anzeigen kann. Dabei gehen wir davon aus, dass die Entwickler der Applikation am besten entscheiden können welche Informationen wichtig sind. Zum Definieren dieser Werte reicht eine Datasource, die das &lt;a href=&quot;http://cocoadocs.org/docsets/TBODeveloperOverlay/1.3.0/Protocols/TBODeveloperOverlayKVDebuggerDatasourceProtocol.html&quot;&gt;TBODeveloperOverlayKVDebuggerDatasourceProtocol&lt;/a&gt; implementiert. Alternativ kann die &lt;a href=&quot;http://cocoadocs.org/docsets/TBODeveloperOverlay/1.3.0/Classes/TBODeveloperOverlayNSUserDefaultsDatasource.html&quot;&gt;TBODeveloperOverlayNSUserDefaultsDatasource&lt;/a&gt; genutzt werden um einen Einblick in die NSUserDefaults zu erhalten.&lt;/p&gt;

&lt;p&gt;Zusätzlich können über die &lt;code class=&quot;highlighter-rouge&quot;&gt;–isEditableForIndexPath:&lt;/code&gt;und &lt;code class=&quot;highlighter-rouge&quot;&gt;–didChangeValue:atIndexPath:&lt;/code&gt; Methoden auch Variablen definiert werden, die in dem KeyValueDebugger verändert werden können. Möglich sind dabei aktuell &lt;code class=&quot;highlighter-rouge&quot;&gt;Bool&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;NSNumber&lt;/code&gt; und &lt;code class=&quot;highlighter-rouge&quot;&gt;NSString&lt;/code&gt; Datentypen.&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;CustomKeyValueDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CustomKeyValueDatasource&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayKVDebugger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvDebuggerViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayKVDebugger&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;loggeroverlay---time-to-look-back&quot;&gt;LoggerOverlay - time to look back&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2016-06-19/tbodeveloperoverlay-logger.jpg&quot; alt=&quot;TBODeveloperOverlay Logger&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wenn ein Blick auf den Zustand nicht reicht muss man in die Vergangenheit schauen. Wie ist es zu dieser Situation gekommen? Mit dem &lt;a href=&quot;http://cocoadocs.org/docsets/TBODeveloperOverlay/1.3.0/Classes/TBODeveloperOverlayLogger.html&quot;&gt;TBODeveloperOverlayLogger&lt;/a&gt; gibt es ein Tool für eine Zeitreise. Dabei können beliebige Filter und eine Suchmaske genutzt werden um die Menge an logs einzuengen. Der Logger unterstützt auch hier wieder beliebige Quellen und bring eine &lt;code class=&quot;highlighter-rouge&quot;&gt;TBODeveloperOverlayLoggerCocoaLumberjackDatasource&lt;/code&gt; mit, die mit wenig Konfiguration ein Forschen in den CocoaLubjerack Logdateien ermöglicht.&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayLoggerCocoaLumberjackDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loggerDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayLoggerCocoaLumberjackDatasource&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayLogger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayLogger&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loggerDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;alltogether---yeah&quot;&gt;Alltogether - Yeah&lt;/h2&gt;

&lt;p&gt;Zusammen mit dem &lt;a href=&quot;http://cocoadocs.org/docsets/TBODeveloperOverlay/1.3.0/Classes/TBODeveloperOverlayFileInspectorViewController.html&quot;&gt;TBODeveloperOverlayFileInspectorViewController&lt;/a&gt; gibt somit drei hilfreiche Tools, die mit nur wenigen Zeilen Code die Arbeit enorm vereifachen.&lt;/p&gt;

&lt;div class=&quot;language-objc highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c1&quot;&gt;// initialize key-value-debugger&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;CustomKeyValueDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CustomKeyValueDatasource&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayKVDebugger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvDebuggerViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayKVDebugger&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    
&lt;span class=&quot;c1&quot;&gt;// initialize NSUserDefaults inspector&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayNSUserDefaultsDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userDefaultsDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayNSUserDefaultsDatasource&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayKVDebugger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userDefaultsInspector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayKVDebugger&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userDefaultsDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;userDefaultsInspector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&quot;UserDefaults Inspector&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
&lt;span class=&quot;c1&quot;&gt;// initialize logger overlay&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayLoggerCocoaLumberjackDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loggerDatasource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayLoggerCocoaLumberjackDatasource&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayLogger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayLogger&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loggerDatasource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    
&lt;span class=&quot;c1&quot;&gt;// initialize file inspector&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;NSUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileInspectorBaseUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSURL&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fileURLWithPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSSearchPathForDirectoriesInDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NSLibraryDirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NSUserDomainMask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;YES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;firstObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;URLByDeletingLastPathComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayFileInspectorViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileInspector&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayFileInspectorViewController&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithBaseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileInspectorBaseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fileInspector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&quot;File Inspector&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// create core overlay&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;NSArray&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plugins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;@[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvDebuggerViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userDefaultsInspector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileInspector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;UIViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;presentedDebuggingViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// with just one plugin we don't need to display a list of plugins&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// we will directly show the first one&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;presentedDebuggingViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;presentedDebuggingViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBODeveloperOverlayPluginListViewController&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithPlugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// present the developer overlay modally    &lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;TBOModalNavigationController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;developerOverlay&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TBOModalNavigationController&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initWithRootViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;presentedDebuggingViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;presentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;developerOverlay&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;YES&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><summary type="html">Mit wachsender Komplexität eines jeden Softwareprojektes wächst auch die Komplexität beim Debuggen von Fehlern und Verstehen von Supportanfragen. Dabei gibt es einige Aspekte, die es einfacher machen die Situation zu verstehen. Ein gut gepflegtes Log kann sehr hilfreich sein. Genauso ist es wichtig zu verstehen auf welcher Version und mit welchen Parametern das Problem auftritt.</summary></entry><entry><title type="html">Swift Bitmasks - Things nobody needs</title><link href="https://brototyp.de/blog/swift-bitmasks/" rel="alternate" type="text/html" title="Swift Bitmasks - Things nobody needs" /><published>2016-06-07T21:52:11+02:00</published><updated>2018-02-10T10:10:15+01:00</updated><id>https://brototyp.de/blog/swift-bitmasks</id><content type="html" xml:base="https://brototyp.de/blog/swift-bitmasks/">&lt;p&gt;Whoever wrote an iOS App in Objective-C knows bitmasks very well. Even just configuring a simple &lt;code class=&quot;highlighter-rouge&quot;&gt;UIButton&lt;/code&gt; one is confronted with a &lt;code class=&quot;highlighter-rouge&quot;&gt;UIControlState&lt;/code&gt; and things like &lt;code class=&quot;highlighter-rouge&quot;&gt;UIControlStateHighlighted|UIControlStateDisabled&lt;/code&gt;. Before autolayout one had to fight with &lt;code class=&quot;highlighter-rouge&quot;&gt;UIViewAutoresizing&lt;/code&gt;.
But bitmasks aren’t a common concept in Swift and creating them isn’t trivial.&lt;/p&gt;

&lt;p&gt;To get a better understanding of bitmasks, generics and bitshifting in swift I wrote an &lt;code class=&quot;highlighter-rouge&quot;&gt;extension&lt;/code&gt; fo &lt;code class=&quot;highlighter-rouge&quot;&gt;UInt8&lt;/code&gt; which is an eight bit bitmask. Bigger bitmasks aren’t difficult either.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bitmask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;BitName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bitmask&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setBit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RawRepresentable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;newValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bitmask&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;RawValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;BitName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rawValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawValue&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;currentState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getBit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rawValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getBit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RawRepresentable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;RawValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;BitName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rawValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawValue&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rawValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With a simple usage.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RoomBitNames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;BitName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Livingroom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Kitchen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bedroom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// there can be 5 more bits&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bitmask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setBit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RoomBitNames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Livingroom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;newValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setBit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RoomBitNames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Kitchen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;newValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;hasLivingroom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getBit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RoomBitNames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Livingroom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;hasKitchen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getBit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RoomBitNames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Kitchen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;hasBedroom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getBit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RoomBitNames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bedroom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><summary type="html">Whoever wrote an iOS App in Objective-C knows bitmasks very well. Even just configuring a simple UIButton one is confronted with a UIControlState and things like UIControlStateHighlighted|UIControlStateDisabled. Before autolayout one had to fight with UIViewAutoresizing. But bitmasks aren’t a common concept in Swift and creating them isn’t trivial.</summary></entry><entry xml:lang="de"><title type="html">Plan B - Was ich für mein Backup nutze</title><link href="https://brototyp.de/blog/plan-b/" rel="alternate" type="text/html" title="Plan B - Was ich für mein Backup nutze" /><published>2016-06-02T21:23:11+02:00</published><updated>2018-01-31T10:44:17+01:00</updated><id>https://brototyp.de/blog/plan-b</id><content type="html" xml:base="https://brototyp.de/blog/plan-b/">&lt;p&gt;Geht eine Nerdin zum Prophylaxe. Nach dem üblichen säbel, feil und putz kommt die unausweichliche Frage: &lt;em&gt;Nutzen sie regelmäßig Zahnseide?&lt;/em&gt; Je nach Grad der persönlichen Zahnpflege ist das &lt;em&gt;Eigentlich schon!&lt;/em&gt; mehr oder weniger ehrlich. Bei der Zahnseide verhält es sich wie beim Backup. Jeder weiß, dass es wichtig ist. Jeder nimmt sich vor es regelmäßig zu machen. Aber irgendwie macht man es dann doch nicht, oder nicht so oft wie es gut wäre. Als gute Zahnärztin wird natürlich nach jedem Essen Sortimennt der verschiedenen Zahnseiden herausgeholt und die passende gründlich ausgesucht. Genauso ist der Backup-Plan einer guten Nerdin selbstverständlich vielschichtig.&lt;/p&gt;

&lt;p&gt;Nachdem die Verbreitung von &lt;a href=&quot;https://de.wikipedia.org/wiki/Ransomware&quot;&gt;Ransomware&lt;/a&gt; zugenommen hat und mittlerweile auch das &lt;a href=&quot;http://www.heise.de/mac-and-i/meldung/Erpressungs-Trojaner-Time-Machine-Backups-anfaellig-3131762.html&quot;&gt;TimeMachine Backup mit verschlüsselt wird&lt;/a&gt; habe ich mich entschieden meine Backupstrategie auszuweiten. Viele meiner Dokumente liegen mittlerweile auf der Dropbox oder einer &lt;a href=&quot;https://www.seafile.com/en/home/&quot;&gt;Seafile&lt;/a&gt; Instanz. Aber beidest ist kein (ausreichender) Schutz. Neben TimeMachine habe ich auch &lt;a href=&quot;https://www.crashplan.com/&quot;&gt;Crashplan&lt;/a&gt; und &lt;a href=&quot;https://www.backblaze.com&quot;&gt;Backblaze&lt;/a&gt; ausprobiert. Crashplan empfinde ich als unbenutzbar. Java Software halt. Backblaze hat einen anständigen Eindruck gemacht und ich habe bisher aus verschiedenen Richtungen viel Gutes gehört. Die voreingestellten Ausnahmen die man oftmals entfernen kann und die fest definierte Ausnahme des &lt;em&gt;/Applications&lt;/em&gt;-Folder haben mich jedoch abgeschreckt. Ich möchte ein System, das genau das macht, was ich von ihm erwarte. Ich möchte keine versteckten Ausnahmen. Und ich möchte auch nicht, dass sich eine Backup Software um das &lt;a href=&quot;https://www.backblaze.com/lost_computer.html&quot;&gt;finden von verlorenen oder gestohlenen Rechnern kümmert&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Da ist mir &lt;a href=&quot;https://www.arqbackup.com&quot;&gt;Arq&lt;/a&gt; eingefallen. Eine Software die einen ganz anderen Weg wählt. Arq ist nur eine Software. Arq verschlüsselt die Daten lokal auf dem Rechner und speichert diese dann wohin man will&lt;sup id=&quot;fnref:storage_destination&quot;&gt;&lt;a href=&quot;#fn:storage_destination&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Arq ist ein &lt;em&gt;Bring your own Storage&lt;/em&gt; Modell.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You can back up to your own Amazon Cloud Drive, Amazon Web Services, Google Cloud Storage, Google Drive, Dropbox, or OneDrive accounts, or your SFTP server or NAS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Da &lt;a href=&quot;https://twitter.com/arqbackup/status/583382315772059648&quot;&gt;OneDrive for Busines (noch) nicht unterstützt wird&lt;/a&gt; habe ich mich für Amazon S3 entschieden. Aktuell liegen dort 20GB von vor meinem &lt;a href=&quot;/blog/brew-bundler/&quot;&gt;reinstall&lt;/a&gt; und 4GB von meiner aktuellen Installation. Meine letzte Rechnung war knappe 1€ leicht. Damit ich mich auch beim nächsten reinstall an die Wichtigen Punkte erinnere habe ich &lt;a href=&quot;https://github.com/brototyp/dotfiles/blob/master/docs/arc.md&quot;&gt;hier&lt;/a&gt; angefangen zu notieren welche Dateien und Ordner in das Backup sollten und welche meiner Meinung dort nicht hin gehören.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:storage_destination&quot;&gt;
      &lt;p&gt;Nicht überall hin, aber es werden viele &lt;a href=&quot;https://www.arqbackup.com/features/&quot;&gt;Anbieter unterstützt&lt;/a&gt;. &lt;a href=&quot;#fnref:storage_destination&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name></name></author><summary type="html">Geht eine Nerdin zum Prophylaxe. Nach dem üblichen säbel, feil und putz kommt die unausweichliche Frage: Nutzen sie regelmäßig Zahnseide? Je nach Grad der persönlichen Zahnpflege ist das Eigentlich schon! mehr oder weniger ehrlich. Bei der Zahnseide verhält es sich wie beim Backup. Jeder weiß, dass es wichtig ist. Jeder nimmt sich vor es regelmäßig zu machen. Aber irgendwie macht man es dann doch nicht, oder nicht so oft wie es gut wäre. Als gute Zahnärztin wird natürlich nach jedem Essen Sortimennt der verschiedenen Zahnseiden herausgeholt und die passende gründlich ausgesucht. Genauso ist der Backup-Plan einer guten Nerdin selbstverständlich vielschichtig.</summary></entry><entry xml:lang="de"><title type="html">Brew Bundler - Das Gemfile für dein Homebrew Cask</title><link href="https://brototyp.de/blog/brew-bundler/" rel="alternate" type="text/html" title="Brew Bundler - Das Gemfile für dein Homebrew Cask" /><published>2016-06-01T20:49:40+02:00</published><updated>2018-01-31T10:44:17+01:00</updated><id>https://brototyp.de/blog/brew-bundler</id><content type="html" xml:base="https://brototyp.de/blog/brew-bundler/">&lt;p&gt;Reboot tut gut. So zumindest der alte Spruch der Windows Benutzer. Auf dem Mac wird jeder passionierte Steve Jünger behaupten ist das anders, aber ein Clean install ist nach ein paar Jahren doch ganz erholsam. Man muss nicht mühsam ausmisten, sondern installiert sich nach und nach die Software die man braucht und kümmert sich mit akribischer Sorgfalt um die Konfiguration und das Setup.&lt;/p&gt;

&lt;p&gt;Aber die Reinkarnation kommt mit hohen Kosten. Bis man sich in der täglichen Arbeitsumgebung wieder heimisch fühlt und alle notwenige Software wieder installiert hat vergehen Tage bis hin zu Wochen.&lt;/p&gt;

&lt;p&gt;Da ich gerade dabei bin meinen mobilen Rechner mit neuem glanz zu versehen nutze ich die Gelegenheit diesen Prozess ein wenig zu dokumentieren und zu verschlanken. Manche Dinge sind automatisierbar, manches ist synchronisierbar und manches wird einfacher in dem man sich einfach nur notiert: &lt;em&gt;Wie kann man verdammt noch mal einstellen, dass man durch die Elemente in einem Fenster per Tab durchwelchseln kann?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Vor einem Jahr in etwa bin ich über &lt;a href=&quot;https://caskroom.github.io&quot;&gt;Homebrew Cask&lt;/a&gt; gestolpert.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Homebrew Cask extends Homebrew and brings its elegance, simplicity, and speed to OS X applications and large binaries alike.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Als einen essentiellen Nachteil habe ich dabei die fehlende Möglichkeit Updates einzuspielen zu können empfunden.&lt;/p&gt;

&lt;p&gt;Vor wenigen Tagen wurde ich dann auf &lt;a href=&quot;https://github.com/Homebrew/homebrew-bundle&quot;&gt;Brew Bundle&lt;/a&gt; aufmerksam gemacht. Aus der Ruby Welt kennt man den &lt;a href=&quot;http://bundler.io&quot;&gt;Bundler&lt;/a&gt;, der es erlaubt dependencies die in einem &lt;em&gt;Gemfile&lt;/em&gt; definiert sind aufzulösen, zu installieren und aktualisieren. &lt;em&gt;Brew Bundle&lt;/em&gt; verfolgt ein ähnliches Konzept. In einem &lt;em&gt;Brewfile&lt;/em&gt; definiert man die Software, die installiert werden soll. Dabei können sowohl &lt;em&gt;Hombrew&lt;/em&gt; Pakete als auch &lt;em&gt;Homebrew Cask&lt;/em&gt; und &lt;em&gt;Mac App Store&lt;/em&gt; Software referenziert werden. Ein einfaches &lt;em&gt;brew bundle&lt;/em&gt; installiert und aktualisiert dann die gewünschten Pakete. Eigene Paket-Definitionen können einfach ge-&lt;em&gt;tap&lt;/em&gt;-t werden.&lt;/p&gt;

&lt;p&gt;Das klicken durch verschiedene installer hat mir &lt;em&gt;Brew Bundle&lt;/em&gt; auf jeden Fall erspart. Der Praxistest beim Update steht jedoch noch aus. Außerdem sollte man sich der Risiken bewusst sein: Ein &lt;em&gt;brew bundle&lt;/em&gt; installiert Software aus nicht direkt ersichtlichen Quellen. Zwar können diese überprüft werden, aber wer macht das schon.&lt;/p&gt;

&lt;p&gt;Mein derzeitiges &lt;em&gt;Brewfile&lt;/em&gt; zum stöbern findet sich &lt;a href=&quot;https://github.com/brototyp/dotfiles/blob/master/Brewfile&quot;&gt;hier&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><summary type="html">Reboot tut gut. So zumindest der alte Spruch der Windows Benutzer. Auf dem Mac wird jeder passionierte Steve Jünger behaupten ist das anders, aber ein Clean install ist nach ein paar Jahren doch ganz erholsam. Man muss nicht mühsam ausmisten, sondern installiert sich nach und nach die Software die man braucht und kümmert sich mit akribischer Sorgfalt um die Konfiguration und das Setup.</summary></entry></feed>